Skip to content

Commit 50cf5f3

Browse files
committed
io_uring/msg_ring: add an alloc cache for io_kiocb entries
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 <[email protected]>
1 parent 0617bb5 commit 50cf5f3

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

include/linux/io_uring_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ struct io_ring_ctx {
397397
struct callback_head poll_wq_task_work;
398398
struct list_head defer_list;
399399

400+
struct io_alloc_cache msg_cache;
401+
spinlock_t msg_lock;
402+
400403
#ifdef CONFIG_NET_RX_BUSY_POLL
401404
struct list_head napi_list; /* track busy poll napi_id */
402405
spinlock_t napi_lock; /* napi_list lock */

io_uring/io_uring.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#include "futex.h"
9696
#include "napi.h"
9797
#include "uring_cmd.h"
98+
#include "msg_ring.h"
9899
#include "memmap.h"
99100

100101
#include "timeout.h"
@@ -315,6 +316,9 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
315316
sizeof(struct io_async_rw));
316317
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
317318
sizeof(struct uring_cache));
319+
spin_lock_init(&ctx->msg_lock);
320+
ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
321+
sizeof(struct io_kiocb));
318322
ret |= io_futex_cache_init(ctx);
319323
if (ret)
320324
goto err;
@@ -351,6 +355,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
351355
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
352356
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
353357
io_alloc_cache_free(&ctx->uring_cache, kfree);
358+
io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
354359
io_futex_cache_free(ctx);
355360
kfree(ctx->cancel_table.hbs);
356361
kfree(ctx->cancel_table_locked.hbs);
@@ -2599,6 +2604,7 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
25992604
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
26002605
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
26012606
io_alloc_cache_free(&ctx->uring_cache, kfree);
2607+
io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
26022608
io_futex_cache_free(ctx);
26032609
io_destroy_buffers(ctx);
26042610
mutex_unlock(&ctx->uring_lock);

io_uring/msg_ring.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "io_uring.h"
1212
#include "rsrc.h"
1313
#include "filetable.h"
14+
#include "alloc_cache.h"
1415
#include "msg_ring.h"
1516

1617
/* 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)
7576
struct io_ring_ctx *ctx = req->ctx;
7677

7778
io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
78-
kmem_cache_free(req_cachep, req);
79+
if (spin_trylock(&ctx->msg_lock)) {
80+
if (io_alloc_cache_put(&ctx->msg_cache, req))
81+
req = NULL;
82+
spin_unlock(&ctx->msg_lock);
83+
}
84+
if (req)
85+
kfree(req);
7986
percpu_ref_put(&ctx->refs);
8087
}
8188

@@ -91,14 +98,27 @@ static void io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
9198
io_req_task_work_add_remote(req, ctx, IOU_F_TWQ_LAZY_WAKE);
9299
}
93100

101+
static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx)
102+
{
103+
struct io_kiocb *req = NULL;
104+
105+
if (spin_trylock(&ctx->msg_lock)) {
106+
req = io_alloc_cache_get(&ctx->msg_cache);
107+
spin_unlock(&ctx->msg_lock);
108+
}
109+
if (req)
110+
return req;
111+
return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN);
112+
}
113+
94114
static int io_msg_data_remote(struct io_kiocb *req)
95115
{
96116
struct io_ring_ctx *target_ctx = req->file->private_data;
97117
struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
98118
struct io_kiocb *target;
99119
u32 flags = 0;
100120

101-
target = kmem_cache_alloc(req_cachep, GFP_KERNEL);
121+
target = io_msg_get_kiocb(req->ctx);
102122
if (unlikely(!target))
103123
return -ENOMEM;
104124

@@ -296,3 +316,10 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)
296316
io_req_set_res(req, ret, 0);
297317
return IOU_OK;
298318
}
319+
320+
void io_msg_cache_free(const void *entry)
321+
{
322+
struct io_kiocb *req = (struct io_kiocb *) entry;
323+
324+
kmem_cache_free(req_cachep, req);
325+
}

io_uring/msg_ring.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
44
int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags);
55
void io_msg_ring_cleanup(struct io_kiocb *req);
6+
void io_msg_cache_free(const void *entry);

0 commit comments

Comments
 (0)