FAILED: patch "[PATCH] io_uring: convert io_buffer_idr to XArray" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9e15c3a0ced5a61f320b989072c24983cb1620c1 Mon Sep 17 00:00:00 2001
From: Jens Axboe <[email protected]>
Date: Sat, 13 Mar 2021 12:29:43 -0700
Subject: [PATCH] io_uring: convert io_buffer_idr to XArray
Like we did for the personality idr, convert the IO buffer idr to use XArray. This avoids a use-after-free on removal of entries, since idr doesn't like doing so from inside an iterator, and it nicely reduces the amount of code we need to support this feature.
fs/io_uring.c +15 -28
@@ -402,7 +402,7 @@ struct io_ring_ctx {struct socket *ring_sock;#endif -struct idr io_buffer_idr; +struct xarray io_buffers;struct xarray personalities;u32 pers_next;
@@ -1135,7 +1135,7 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)init_waitqueue_head (&ctx->cq_wait);INIT_LIST_HEAD (&ctx->cq_overflow_list);init_completion (&ctx->ref_comp); -idr_init (&ctx->io_buffer_idr); +xa_init_flags (&ctx->io_buffers,XA_FLAGS_ALLOC1 );xa_init_flags (&ctx->personalities,XA_FLAGS_ALLOC1 );mutex_init (&ctx->uring_lock);init_waitqueue_head (&ctx->wait);
@@ -2843,7 +2843,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,lockdep_assert_held (&req->ctx->uring_lock); - head =idr_find (&req->ctx->io_buffer_idr, bgid); + head =xa_load (&req->ctx->io_buffers, bgid);if (head) {if (!list_empty (&head->list)) { kbuf = list_last_entry(&head->list, struct io_buffer,
@@ -2851,7 +2851,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,list_del (&kbuf->list); }else { kbuf = head; -idr_remove (&req->ctx->io_buffer_idr, bgid); +xa_erase (&req->ctx->io_buffers, bgid); }if (*len > kbuf->len) *len = kbuf->len;
@@ -3892,7 +3892,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf, } i++;kfree (buf); -idr_remove (&ctx->io_buffer_idr, bgid); +xa_erase (&ctx->io_buffers, bgid);return i; }
@@ -3910,7 +3910,7 @@ static int io_remove_buffers(struct io_kiocb *req, unsigned int issue_flags)lockdep_assert_held (&ctx->uring_lock); ret = -ENOENT ; - head =idr_find (&ctx->io_buffer_idr, p->bgid); + head =xa_load (&ctx->io_buffers, p->bgid);if (head) ret =__io_remove_buffers (ctx, head, p->bgid, p->nbufs);if (ret <0 )
@@ -3993,21 +3993,14 @@ static int io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags)lockdep_assert_held (&ctx->uring_lock); - list = head =idr_find (&ctx->io_buffer_idr, p->bgid); + list = head =xa_load (&ctx->io_buffers, p->bgid); ret =io_add_buffers (p, &head); -if (ret <0 ) - goto out; - -if (!list) { - ret =idr_alloc (&ctx->io_buffer_idr, head, p->bgid, p->bgid +1 , -GFP_KERNEL ); -if (ret <0 ) { +if (ret >=0 && !list) { + ret =xa_insert (&ctx->io_buffers, p->bgid, head,GFP_KERNEL ); +if (ret <0 )__io_remove_buffers (ctx, head, p->bgid,-1U ); - goto out; - } } -out:if (ret <0 )req_set_fail_links (req);
@@ -8333,19 +8326,13 @@ static int io_eventfd_unregister(struct io_ring_ctx *ctx)return -ENXIO ; } -static int __io_destroy_buffers (int id,void *p,void *data) -{ -struct io_ring_ctx *ctx = data; -struct io_buffer *buf = p; - -__io_remove_buffers (ctx, buf, id,-1U ); -return 0 ; -} -static void io_destroy_buffers (struct io_ring_ctx *ctx) { -idr_for_each (&ctx->io_buffer_idr, __io_destroy_buffers, ctx); -idr_destroy (&ctx->io_buffer_idr); +struct io_buffer *buf; +unsigned long index; + +xa_for_each (&ctx->io_buffers, index, buf) +__io_remove_buffers (ctx, buf, index,-1U ); }static void io_req_cache_free (struct list_head *list,struct task_struct *tsk)