mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:02:20 +00:00
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 <axboe@kernel.dk>
This commit is contained in:
parent
0617bb500b
commit
50cf5f3842
@ -397,6 +397,9 @@ struct io_ring_ctx {
|
|||||||
struct callback_head poll_wq_task_work;
|
struct callback_head poll_wq_task_work;
|
||||||
struct list_head defer_list;
|
struct list_head defer_list;
|
||||||
|
|
||||||
|
struct io_alloc_cache msg_cache;
|
||||||
|
spinlock_t msg_lock;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||||
struct list_head napi_list; /* track busy poll napi_id */
|
struct list_head napi_list; /* track busy poll napi_id */
|
||||||
spinlock_t napi_lock; /* napi_list lock */
|
spinlock_t napi_lock; /* napi_list lock */
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
#include "futex.h"
|
#include "futex.h"
|
||||||
#include "napi.h"
|
#include "napi.h"
|
||||||
#include "uring_cmd.h"
|
#include "uring_cmd.h"
|
||||||
|
#include "msg_ring.h"
|
||||||
#include "memmap.h"
|
#include "memmap.h"
|
||||||
|
|
||||||
#include "timeout.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));
|
sizeof(struct io_async_rw));
|
||||||
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
|
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
|
||||||
sizeof(struct uring_cache));
|
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);
|
ret |= io_futex_cache_init(ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@ -351,6 +355,7 @@ err:
|
|||||||
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
|
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->rw_cache, io_rw_cache_free);
|
||||||
io_alloc_cache_free(&ctx->uring_cache, kfree);
|
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_futex_cache_free(ctx);
|
||||||
kfree(ctx->cancel_table.hbs);
|
kfree(ctx->cancel_table.hbs);
|
||||||
kfree(ctx->cancel_table_locked.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->netmsg_cache, io_netmsg_cache_free);
|
||||||
io_alloc_cache_free(&ctx->rw_cache, io_rw_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->uring_cache, kfree);
|
||||||
|
io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);
|
||||||
io_futex_cache_free(ctx);
|
io_futex_cache_free(ctx);
|
||||||
io_destroy_buffers(ctx);
|
io_destroy_buffers(ctx);
|
||||||
mutex_unlock(&ctx->uring_lock);
|
mutex_unlock(&ctx->uring_lock);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "io_uring.h"
|
#include "io_uring.h"
|
||||||
#include "rsrc.h"
|
#include "rsrc.h"
|
||||||
#include "filetable.h"
|
#include "filetable.h"
|
||||||
|
#include "alloc_cache.h"
|
||||||
#include "msg_ring.h"
|
#include "msg_ring.h"
|
||||||
|
|
||||||
/* All valid masks for MSG_RING */
|
/* 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;
|
struct io_ring_ctx *ctx = req->ctx;
|
||||||
|
|
||||||
io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
|
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);
|
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);
|
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)
|
static int io_msg_data_remote(struct io_kiocb *req)
|
||||||
{
|
{
|
||||||
struct io_ring_ctx *target_ctx = req->file->private_data;
|
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;
|
struct io_kiocb *target;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
|
||||||
target = kmem_cache_alloc(req_cachep, GFP_KERNEL);
|
target = io_msg_get_kiocb(req->ctx);
|
||||||
if (unlikely(!target))
|
if (unlikely(!target))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -296,3 +316,10 @@ done:
|
|||||||
io_req_set_res(req, ret, 0);
|
io_req_set_res(req, ret, 0);
|
||||||
return IOU_OK;
|
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);
|
||||||
|
}
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
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);
|
int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags);
|
||||||
void io_msg_ring_cleanup(struct io_kiocb *req);
|
void io_msg_ring_cleanup(struct io_kiocb *req);
|
||||||
|
void io_msg_cache_free(const void *entry);
|
||||||
|
Loading…
Reference in New Issue
Block a user