Re: [PATCH] tracing: Fix to avoid wakeup loop in splice read of per-cpu buffer

From: kernel test robot
Date: Wed Aug 23 2023 - 08:20:01 EST


Hi Masami,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.5-rc7 next-20230823]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Masami-Hiramatsu-Google/tracing-Fix-to-avoid-wakeup-loop-in-splice-read-of-per-cpu-buffer/20230821-222307
base: linus/master
patch link: https://lore.kernel.org/r/169262755804.106231.8245792908363050528.stgit%40devnote2
patch subject: [PATCH] tracing: Fix to avoid wakeup loop in splice read of per-cpu buffer
config: mips-randconfig-r131-20230823 (https://download.01.org/0day-ci/archive/20230823/202308232056.401OxapL-lkp@xxxxxxxxx/config)
compiler: mipsel-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230823/202308232056.401OxapL-lkp@xxxxxxxxx/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@xxxxxxxxx>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308232056.401OxapL-lkp@xxxxxxxxx/

sparse warnings: (new ones prefixed by >>)
kernel/trace/trace.c:446:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct trace_export **list @@ got struct trace_export [noderef] __rcu ** @@
kernel/trace/trace.c:446:28: sparse: expected struct trace_export **list
kernel/trace/trace.c:446:28: sparse: got struct trace_export [noderef] __rcu **
kernel/trace/trace.c:460:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct trace_export **list @@ got struct trace_export [noderef] __rcu ** @@
kernel/trace/trace.c:460:33: sparse: expected struct trace_export **list
kernel/trace/trace.c:460:33: sparse: got struct trace_export [noderef] __rcu **
kernel/trace/trace.c:2959:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct event_filter *filter @@ got struct event_filter [noderef] __rcu *filter @@
kernel/trace/trace.c:2959:38: sparse: expected struct event_filter *filter
kernel/trace/trace.c:2959:38: sparse: got struct event_filter [noderef] __rcu *filter
>> kernel/trace/trace.c:8481:25: sparse: sparse: incompatible types in comparison expression (different type sizes):
>> kernel/trace/trace.c:8481:25: sparse: unsigned int *
>> kernel/trace/trace.c:8481:25: sparse: unsigned long long [usertype] *
kernel/trace/trace.c:400:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/trace.c:400:9: sparse: struct trace_export [noderef] __rcu *
kernel/trace/trace.c:400:9: sparse: struct trace_export *
kernel/trace/trace.c:415:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/trace/trace.c:415:9: sparse: struct trace_export [noderef] __rcu *
kernel/trace/trace.c:415:9: sparse: struct trace_export *
>> kernel/trace/trace.c:8481:25: sparse: sparse: shift too big (32) for type unsigned int

vim +8481 kernel/trace/trace.c

8400
8401 if (*ppos & (PAGE_SIZE - 1))
8402 return -EINVAL;
8403
8404 if (len & (PAGE_SIZE - 1)) {
8405 if (len < PAGE_SIZE)
8406 return -EINVAL;
8407 len &= PAGE_MASK;
8408 }
8409
8410 if (splice_grow_spd(pipe, &spd))
8411 return -ENOMEM;
8412
8413 again:
8414 trace_access_lock(iter->cpu_file);
8415 entries = ring_buffer_entries_cpu(iter->array_buffer->buffer, iter->cpu_file);
8416
8417 for (i = 0; i < spd.nr_pages_max && len && entries; i++, len -= PAGE_SIZE) {
8418 struct page *page;
8419 int r;
8420
8421 ref = kzalloc(sizeof(*ref), GFP_KERNEL);
8422 if (!ref) {
8423 ret = -ENOMEM;
8424 break;
8425 }
8426
8427 refcount_set(&ref->refcount, 1);
8428 ref->buffer = iter->array_buffer->buffer;
8429 ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file);
8430 if (IS_ERR(ref->page)) {
8431 ret = PTR_ERR(ref->page);
8432 ref->page = NULL;
8433 kfree(ref);
8434 break;
8435 }
8436 ref->cpu = iter->cpu_file;
8437
8438 r = ring_buffer_read_page(ref->buffer, &ref->page,
8439 len, iter->cpu_file, 1);
8440 if (r < 0) {
8441 ring_buffer_free_read_page(ref->buffer, ref->cpu,
8442 ref->page);
8443 kfree(ref);
8444 break;
8445 }
8446
8447 page = virt_to_page(ref->page);
8448
8449 spd.pages[i] = page;
8450 spd.partial[i].len = PAGE_SIZE;
8451 spd.partial[i].offset = 0;
8452 spd.partial[i].private = (unsigned long)ref;
8453 spd.nr_pages++;
8454 *ppos += PAGE_SIZE;
8455
8456 entries = ring_buffer_entries_cpu(iter->array_buffer->buffer, iter->cpu_file);
8457 }
8458
8459 trace_access_unlock(iter->cpu_file);
8460 spd.nr_pages = i;
8461
8462 /* did we read anything? */
8463 if (!spd.nr_pages) {
8464 long wait_index;
8465 size_t nr_pages;
8466 size_t full;
8467
8468 if (ret)
8469 goto out;
8470
8471 ret = -EAGAIN;
8472 if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK))
8473 goto out;
8474
8475 wait_index = READ_ONCE(iter->wait_index);
8476
8477 /* For splice, we have to ensure at least 1 page is filled */
8478 nr_pages = ring_buffer_nr_pages(iter->array_buffer->buffer, iter->cpu_file);
8479 if (nr_pages * iter->tr->buffer_percent < 100) {
8480 full = nr_pages + 99;
> 8481 do_div(full, nr_pages);
8482 } else
8483 full = iter->tr->buffer_percent;
8484
8485 ret = wait_on_pipe(iter, full);
8486 if (ret)
8487 goto out;
8488
8489 /* No need to wait after waking up when tracing is off */
8490 if (!tracer_tracing_is_on(iter->tr))
8491 goto out;
8492
8493 /* Make sure we see the new wait_index */
8494 smp_rmb();
8495 if (wait_index != iter->wait_index)
8496 goto out;
8497
8498 goto again;
8499 }
8500
8501 ret = splice_to_pipe(pipe, &spd);
8502 out:
8503 splice_shrink_spd(&spd);
8504
8505 return ret;
8506 }
8507

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki