io_uring: account user memory freed when exit has been queued
Jens Axboe
maintainerPATCH 1/1 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.
Signed-off-by Jens Axboe <[email protected]>
---
fs/io_uring.c +10 -3
@@ -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); }
Signature · 1 line
Jens Axboe