Re: [PATCH v3] io_uring: annotate remote tasks for kcoverage

Jann Horn <[email protected]>
Newsgroups org.kernel.vger.io-uring
Message-ID <CAG48ez02Sio8ZENVK3gUWM+8j6NgG9LxtnDV=v+FSqsqs_KfnA@mail.gmail.com>
On Tue, May 26, 2026 at 6:49 PM Robert Femmer <[email protected]> wrote:
> Fuzzers use coverage information to guide generation of test cases
> towards new or interesting code paths. Syzkaller, specifically, makes
> use kcoverage (CONFIG_KCOV). Coverage information is not collected for
> kernel tasks unless annotated by kcov_remote_start and kcov_remote_stop.
> This patch annotates io-uring's work queue and sqpoll tasks.

I think this is a useful change overall.

@maintainers: For context, this should have no impact on normal builds
- "struct kcov_common_handle_id" is zero-sized in normal builds, and
all the helpers used here are empty inline functions.

> Depends-on: 20260430-kcov-refactor-common-handle-v1-1-23a0c7a0ba38@google.com
> Signed-off-by: Robert Femmer <[email protected]>
> ---
>  include/linux/io_uring_types.h | 2 ++
>  io_uring/io-wq.c               | 4 ++++
>  io_uring/io_uring.c            | 1 +
>  io_uring/io_uring.h            | 2 ++
>  io_uring/sqpoll.c              | 4 ++++
>  5 files changed, 13 insertions(+)
>
> diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
> index 244392026c6d..b6590b2b350c 100644
> --- a/include/linux/io_uring_types.h
> +++ b/include/linux/io_uring_types.h
> @@ -504,6 +504,8 @@ struct io_ring_ctx {
>         struct io_mapped_region         ring_region;
>         /* used for optimised request parameter and wait argument passing  */
>         struct io_mapped_region         param_region;
> +
> +       struct kcov_common_handle_id    kcov_handle;
>  };
>
>  /*
> diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
> index 8cc7b47d3089..9ade4c4f4983 100644
> --- a/io_uring/io-wq.c
> +++ b/io_uring/io-wq.c
> @@ -639,6 +639,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
>                 /* handle a whole dependent link */
>                 do {
>                         struct io_wq_work *next_hashed, *linked;
> +                       struct io_kiocb *req;
>                         unsigned int work_flags = atomic_read(&work->flags);
>                         unsigned int hash = __io_wq_is_hashed(work_flags)
>                                 ? __io_get_work_hash(work_flags)
> @@ -649,7 +650,10 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
>                         if (do_kill &&
>                             (work_flags & IO_WQ_WORK_UNBOUND))
>                                 atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
> +                       req = container_of(work, struct io_kiocb, work);
> +                       kcov_remote_start_common(req->ctx->kcov_handle);
>                         io_wq_submit_work(work);
> +                       kcov_remote_stop();
>                         io_assign_current_work(worker, NULL);
>
>                         linked = io_wq_free_work(work);
> diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
> index 103b6c88f252..89cb649944d9 100644
> --- a/io_uring/io_uring.c
> +++ b/io_uring/io_uring.c
> @@ -293,6 +293,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
>         INIT_HLIST_HEAD(&ctx->cancelable_uring_cmd);
>         io_napi_init(ctx);
>         mutex_init(&ctx->mmap_lock);
> +       ctx->kcov_handle = kcov_common_handle();
>
>         return ctx;
>
> diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h
> index e612a66ee80e..7226fbbbf9f0 100644
> --- a/io_uring/io_uring.h
> +++ b/io_uring/io_uring.h
> @@ -7,6 +7,7 @@
>  #include <linux/resume_user_mode.h>
>  #include <linux/poll.h>
>  #include <linux/io_uring_types.h>
> +#include <linux/kcov.h>

I think instead of this, normal kernel coding style is to use includes
directly in the files where they are needed.
https://docs.kernel.org/process/submit-checklist.html says:
"If you use a facility then #include the file that defines/declares
that facility. Don’t depend on other header files pulling in ones that
you use."

>  #include <uapi/linux/eventpoll.h>
>  #include "alloc_cache.h"
>  #include "io-wq.h"
> @@ -581,4 +582,5 @@ static inline bool io_has_work(struct io_ring_ctx *ctx)
>         return test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq) ||
>                io_local_work_pending(ctx);
>  }
> +
>  #endif

This looks like an accidental whitespace change.

> diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c
> index 46c12afec73e..c7b78ea98587 100644
> --- a/io_uring/sqpoll.c
> +++ b/io_uring/sqpoll.c
> @@ -342,19 +342,23 @@ static int io_sq_thread(void *data)
>
>                 cap_entries = !list_is_singular(&sqd->ctx_list);
>                 list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
> +                       kcov_remote_start_common(ctx->kcov_handle);
>                         int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist);
>
>                         if (!sqt_spin && (ret > 0 || !list_empty(&ctx->iopoll_list)))
>                                 sqt_spin = true;
> +                       kcov_remote_stop();
>                 }
>                 if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))
>                         sqt_spin = true;
>
>                 list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
> +                       kcov_remote_start_common(ctx->kcov_handle);
>                         if (io_napi(ctx)) {
>                                 io_sq_start_worktime(&ist);
>                                 io_napi_sqpoll_busy_poll(ctx);
>                         }
> +                       kcov_remote_stop();

Someone who knows more about networking than me might know this area
better, but I think we probably don't want to have KCOV coverage
around the call to io_napi_sqpoll_busy_poll() for two reasons:

1. This is NAPI busypolling code, designed to busy-loop until network
packets arrive - meaning the limited KCOV coverage buffer will quickly
fill up even if no data is actually being processed.
2. As far as I know, io_napi_sqpoll_busy_poll() doesn't really process
data related to the uring instance - it (more or less) merely
busy-polls network interfaces specified by the user. Received packets
are not necessarily actually related to this uring instance.

>                 }
>
>                 io_sq_update_worktime(sqd, &ist);
> --
> 2.54.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.