summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-07-22 21:47:09 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2022-07-22 21:47:09 +0200
commita5235996e1b04405fbd6deea37b051715214fd2a (patch)
tree1b13a3f3900a8ee2649fe221f1f839144de55437 /fs
parentMerge tag 'block-5.19-2022-07-21' of git://git.kernel.dk/linux-block (diff)
parentio_uring: do not recycle buffer in READV (diff)
downloadlinux-a5235996e1b04405fbd6deea37b051715214fd2a.tar.xz
linux-a5235996e1b04405fbd6deea37b051715214fd2a.zip
Merge tag 'io_uring-5.19-2022-07-21' of git://git.kernel.dk/linux-block
Pull io_uring fixes from Jens Axboe: "Fix for a bad kfree() introduced in this cycle, and a quick fix for disabling buffer recycling for IORING_OP_READV. The latter will get reworked for 5.20, but it gets the job done for 5.19" * tag 'io_uring-5.19-2022-07-21' of git://git.kernel.dk/linux-block: io_uring: do not recycle buffer in READV io_uring: fix free of unallocated buffer list
Diffstat (limited to 'fs')
-rw-r--r--fs/io_uring.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c
index a01ea49f3017..e8e769be9ed0 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1738,6 +1738,14 @@ static void io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
return;
/*
+ * READV uses fields in `struct io_rw` (len/addr) to stash the selected
+ * buffer data. However if that buffer is recycled the original request
+ * data stored in addr is lost. Therefore forbid recycling for now.
+ */
+ if (req->opcode == IORING_OP_READV)
+ return;
+
+ /*
* We don't need to recycle for REQ_F_BUFFER_RING, we can just clear
* the flag and hence ensure that bl->head doesn't get incremented.
* If the tail has already been incremented, hang on to it.
@@ -12931,7 +12939,7 @@ static int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
{
struct io_uring_buf_ring *br;
struct io_uring_buf_reg reg;
- struct io_buffer_list *bl;
+ struct io_buffer_list *bl, *free_bl = NULL;
struct page **pages;
int nr_pages;
@@ -12963,7 +12971,7 @@ static int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
if (bl->buf_nr_pages || !list_empty(&bl->buf_list))
return -EEXIST;
} else {
- bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+ free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL);
if (!bl)
return -ENOMEM;
}
@@ -12972,7 +12980,7 @@ static int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
struct_size(br, bufs, reg.ring_entries),
&nr_pages);
if (IS_ERR(pages)) {
- kfree(bl);
+ kfree(free_bl);
return PTR_ERR(pages);
}