io_uring: charge tctx nodes and personalities

The io_tctx_node allocated the first time a task touches a ring, and
the XArray nodes behind tctx->xa and ctx->personalities, are plain
GFP_KERNEL. tctx->xa is indexed by the ring pointer, so nearly every
entry needs nodes of its own, and a task gets one entry per ring it has
used. 642 threads on 4000 rings held 2.3GB with 59MB charged against a
64MB memory.max.

Allocate the node with GFP_KERNEL_ACCOUNT and set XA_FLAGS_ACCOUNT on
both XArrays.

Fixes: 0f2122045b ("io_uring: don't rely on weak ->files references")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Chris Mason 2026-10-19 16:57:44 +00:00 committed by Jens Axboe
parent 075d5837ba
commit 0b34e7b20a
2 changed files with 3 additions and 3 deletions

View File

@ -271,7 +271,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
if (ret)
goto free_ref;
init_completion(&ctx->ref_comp);
xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
mutex_init(&ctx->uring_lock);
init_waitqueue_head(&ctx->cq_wait);
init_waitqueue_head(&ctx->poll_wq);

View File

@ -104,7 +104,7 @@ __cold struct io_uring_task *io_uring_alloc_task_context(struct task_struct *tas
}
tctx->task = task;
xa_init(&tctx->xa);
xa_init_flags(&tctx->xa, XA_FLAGS_ACCOUNT);
init_waitqueue_head(&tctx->wait);
atomic_set(&tctx->in_cancel, 0);
atomic_set(&tctx->inflight_tracked, 0);
@ -123,7 +123,7 @@ static int io_tctx_install_node(struct io_ring_ctx *ctx,
if (xa_load(&tctx->xa, (unsigned long)ctx))
return 0;
node = kmalloc_obj(*node);
node = kmalloc_obj(*node, GFP_KERNEL_ACCOUNT);
if (!node)
return -ENOMEM;
node->ctx = ctx;