Re: [PATCH 2/3] io_uring: get rid of alloc cache init_once handling

Gabriel Krisman Bertazi
2025-01-23T19:47:31Z

Jens Axboe <axboe@kernel.dk> writes:

> init_once is called when an object doesn't come from the cache, and
> hence needs initial clearing of certain members. While the whole
> struct could get cleared by memset() in that case, a few of the cache
> members are large enough that this may cause unnecessary overhead if
> the caches used aren't large enough to satisfy the workload. For those
> cases, some churn of kmalloc+kfree is to be expected.
>
> Ensure that the 3 users that need clearing put the members they need
> cleared at the start of the struct, and wrap the rest of the struct in
> a struct group so the offset is known.
>
> While at it, improve the interaction with KASAN such that when/if
> KASAN writes to members inside the struct that should be retained over
> caching, it won't trip over itself. For rw and net, the retaining of
> the iovec over caching is disabled if KASAN is enabled. A helper will
> free and clear those members in that case.
>
> @@ -1813,11 +1798,10 @@ void io_netmsg_cache_free(const void *entry)
> {
> struct io_async_msghdr *kmsg = (struct io_async_msghdr *) entry;
>
> - if (kmsg->free_iov) {
> - kasan_mempool_unpoison_object(kmsg->free_iov,
> - kmsg->free_iov_nr * sizeof(struct iovec));
> +#if !defined(CONFIG_KASAN)
> + if (kmsg->free_iov)
> io_netmsg_iovec_free(kmsg);
> - }
> +#endif

Among mostly ugly choices, this is an improvement over the init_once
callback. I'd just fold the above codeguard into the code:

if (IS_DEFINED(CONFIG_KASAN) && kmsg->free_iov)

Other than that,

Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>

> kfree(kmsg);
> }
> #endif
> diff --git a/io_uring/net.h b/io_uring/net.h
> index 52bfee05f06a..b804c2b36e60 100644
> --- a/io_uring/net.h
> +++ b/io_uring/net.h
> @@ -5,16 +5,20 @@
>
> struct io_async_msghdr {
> #if defined(CONFIG_NET)
> - struct iovec fast_iov;
> - /* points to an allocated iov, if NULL we use fast_iov instead */
> struct iovec *free_iov;
> + /* points to an allocated iov, if NULL we use fast_iov instead */
> int free_iov_nr;
> - int namelen;
> - __kernel_size_t controllen;
> - __kernel_size_t payloadlen;
> - struct sockaddr __user *uaddr;
> - struct msghdr msg;
> - struct sockaddr_storage addr;
> + struct_group(clear,

--
Gabriel Krisman Bertazi