Commit 6b69c4ab authored by Jens Axboe's avatar Jens Axboe
Browse files

io_uring/kbuf: protect io_buffer_list teardown with a reference



No functional changes in this patch, just in preparation for being able
to keep the buffer list alive outside of the ctx->uring_lock.

Cc: stable@vger.kernel.org # v6.4+
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 3b80cff5
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ static int io_buffer_add_list(struct io_ring_ctx *ctx,
	 * always under the ->uring_lock, but the RCU lookup from mmap does.
	 */
	bl->bgid = bgid;
	atomic_set(&bl->refs, 1);
	return xa_err(xa_store(&ctx->io_bl_xa, bgid, bl, GFP_KERNEL));
}

@@ -265,6 +266,14 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx,
	return i;
}

static void io_put_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl)
{
	if (atomic_dec_and_test(&bl->refs)) {
		__io_remove_buffers(ctx, bl, -1U);
		kfree_rcu(bl, rcu);
	}
}

void io_destroy_buffers(struct io_ring_ctx *ctx)
{
	struct io_buffer_list *bl;
@@ -274,8 +283,7 @@ void io_destroy_buffers(struct io_ring_ctx *ctx)

	xa_for_each(&ctx->io_bl_xa, index, bl) {
		xa_erase(&ctx->io_bl_xa, bl->bgid);
		__io_remove_buffers(ctx, bl, -1U);
		kfree_rcu(bl, rcu);
		io_put_bl(ctx, bl);
	}

	/*
@@ -680,9 +688,8 @@ int io_unregister_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
	if (!bl->is_buf_ring)
		return -EINVAL;

	__io_remove_buffers(ctx, bl, -1U);
	xa_erase(&ctx->io_bl_xa, bl->bgid);
	kfree_rcu(bl, rcu);
	io_put_bl(ctx, bl);
	return 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ struct io_buffer_list {
	__u16 head;
	__u16 mask;

	atomic_t refs;

	/* ring mapped provided buffers */
	__u8 is_buf_ring;
	/* ring mapped provided buffers, but mmap'ed by application */