]> www.infradead.org Git - users/willy/xarray.git/commitdiff
io_uring/msg_ring: add an alloc cache for io_kiocb entries
authorJens Axboe <axboe@kernel.dk>
Thu, 6 Jun 2024 18:25:01 +0000 (12:25 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 24 Jun 2024 14:39:55 +0000 (08:39 -0600)
With slab accounting, allocating and freeing memory has considerable
overhead. Add a basic alloc cache for the io_kiocb allocations that
msg_ring needs to do. Unlike other caches, this one is used by the
sender, grabbing it from the remote ring. When the remote ring gets
the posted completion, it'll free it locally. Hence it is separately
locked, using ctx->msg_lock.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/io_uring_types.h
io_uring/io_uring.c
io_uring/msg_ring.c
io_uring/msg_ring.h

index 1052a68fd68df4d71be10a4c14dc2fb6132ef766..ede42dce15067c6f47051a9b161cb11d908ac78b 100644 (file)
@@ -397,6 +397,9 @@ struct io_ring_ctx {
        struct callback_head            poll_wq_task_work;
        struct list_head                defer_list;
 
+       struct io_alloc_cache           msg_cache;
+       spinlock_t                      msg_lock;
+
 #ifdef CONFIG_NET_RX_BUSY_POLL
        struct list_head        napi_list;      /* track busy poll napi_id */
        spinlock_t              napi_lock;      /* napi_list lock */
index cdeb94d2a26b613014e239a1cbe8dce5b848e938..7ed1e009aaecb04907e16a659ed6817d03f71cac 100644 (file)
@@ -95,6 +95,7 @@
 #include "futex.h"
 #include "napi.h"
 #include "uring_cmd.h"
+#include "msg_ring.h"
 #include "memmap.h"
 
 #include "timeout.h"
@@ -315,6 +316,9 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
                            sizeof(struct io_async_rw));
        ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
                            sizeof(struct uring_cache));
+       spin_lock_init(&ctx->msg_lock);
+       ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
+                           sizeof(struct io_kiocb));
        ret |= io_futex_cache_init(ctx);
        if (ret)
                goto err;
@@ -351,6 +355,7 @@ err:
        io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
        io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
        io_alloc_cache_free(&ctx->uring_cache, kfree);
+       io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
        io_futex_cache_free(ctx);
        kfree(ctx->cancel_table.hbs);
        kfree(ctx->cancel_table_locked.hbs);
@@ -2599,6 +2604,7 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
        io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
        io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
        io_alloc_cache_free(&ctx->uring_cache, kfree);
+       io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
        io_futex_cache_free(ctx);
        io_destroy_buffers(ctx);
        mutex_unlock(&ctx->uring_lock);
index ad7d67d444612b27d57f48be138d397ae156378d..47a754e83b49a9dd8fba40b813be0980517ab8b5 100644 (file)
@@ -11,6 +11,7 @@
 #include "io_uring.h"
 #include "rsrc.h"
 #include "filetable.h"
+#include "alloc_cache.h"
 #include "msg_ring.h"
 
 /* All valid masks for MSG_RING */
@@ -75,7 +76,13 @@ static void io_msg_tw_complete(struct io_kiocb *req, struct io_tw_state *ts)
        struct io_ring_ctx *ctx = req->ctx;
 
        io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
-       kmem_cache_free(req_cachep, req);
+       if (spin_trylock(&ctx->msg_lock)) {
+               if (io_alloc_cache_put(&ctx->msg_cache, req))
+                       req = NULL;
+               spin_unlock(&ctx->msg_lock);
+       }
+       if (req)
+               kfree(req);
        percpu_ref_put(&ctx->refs);
 }
 
@@ -91,6 +98,19 @@ static void io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
        io_req_task_work_add_remote(req, ctx, IOU_F_TWQ_LAZY_WAKE);
 }
 
+static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx)
+{
+       struct io_kiocb *req = NULL;
+
+       if (spin_trylock(&ctx->msg_lock)) {
+               req = io_alloc_cache_get(&ctx->msg_cache);
+               spin_unlock(&ctx->msg_lock);
+       }
+       if (req)
+               return req;
+       return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN);
+}
+
 static int io_msg_data_remote(struct io_kiocb *req)
 {
        struct io_ring_ctx *target_ctx = req->file->private_data;
@@ -98,7 +118,7 @@ static int io_msg_data_remote(struct io_kiocb *req)
        struct io_kiocb *target;
        u32 flags = 0;
 
-       target = kmem_cache_alloc(req_cachep, GFP_KERNEL);
+       target = io_msg_get_kiocb(req->ctx);
        if (unlikely(!target))
                return -ENOMEM;
 
@@ -296,3 +316,10 @@ done:
        io_req_set_res(req, ret, 0);
        return IOU_OK;
 }
+
+void io_msg_cache_free(const void *entry)
+{
+       struct io_kiocb *req = (struct io_kiocb *) entry;
+
+       kmem_cache_free(req_cachep, req);
+}
index 3987ee6c0e5f1d63c97e5e152007813649adbcb7..3030f3942f0f5eb6b76e13cd924b71d2253f2480 100644 (file)
@@ -3,3 +3,4 @@
 int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags);
 void io_msg_ring_cleanup(struct io_kiocb *req);
+void io_msg_cache_free(const void *entry);