mirror of https://gitee.com/openkylin/linux.git
io_uring: account user memory freed when exit has been queued
We currently account the memory after the exit work has been run, but
that leaves a gap where a process has closed its ring and until the
memory has been accounted as freed. If the memlocked ulimit is
borderline, then that can introduce spurious setup errors returning
-ENOMEM because the free work hasn't been run yet.
Account this as freed when we close the ring, as not to expose a tiny
gap where setting up a new ring can fail.
Fixes: 85faa7b834
("io_uring: punt final io_ring_ctx wait-and-free to workqueue")
Cc: stable@vger.kernel.org # v5.7
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
667e57da35
commit
309fc03a32
|
@ -7351,9 +7351,6 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
|
|||
io_mem_free(ctx->sq_sqes);
|
||||
|
||||
percpu_ref_exit(&ctx->refs);
|
||||
if (ctx->account_mem)
|
||||
io_unaccount_mem(ctx->user,
|
||||
ring_pages(ctx->sq_entries, ctx->cq_entries));
|
||||
free_uid(ctx->user);
|
||||
put_cred(ctx->creds);
|
||||
kfree(ctx->cancel_hash);
|
||||
|
@ -7438,6 +7435,16 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
|
|||
if (ctx->rings)
|
||||
io_cqring_overflow_flush(ctx, true);
|
||||
idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
|
||||
|
||||
/*
|
||||
* Do this upfront, so we won't have a grace period where the ring
|
||||
* is closed but resources aren't reaped yet. This can cause
|
||||
* spurious failure in setting up a new ring.
|
||||
*/
|
||||
if (ctx->account_mem)
|
||||
io_unaccount_mem(ctx->user,
|
||||
ring_pages(ctx->sq_entries, ctx->cq_entries));
|
||||
|
||||
INIT_WORK(&ctx->exit_work, io_ring_exit_work);
|
||||
queue_work(system_wq, &ctx->exit_work);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue