aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHao Xu <howeyxu@tencent.com>2022-06-11 20:29:52 +0800
committerPavel Begunkov <asml.silence@gmail.com>2022-06-13 11:37:30 +0100
commit42db0c00e275877eb92480beaa16b33507dc3bda (patch)
treec81732f558477373928948e3b7fe7daee5217753
parente71d7c56dd69f720169c1675f87a1d22d8167767 (diff)
downloadstaging-42db0c00e275877eb92480beaa16b33507dc3bda.tar.gz
io_uring: kbuf: fix bug of not consuming ring buffer in partial io case
When we use ring-mapped provided buffer, we should consume it before arm poll if partial io has been done. Otherwise the buffer may be used by other requests and thus we lost the data. Fixes: c7fb19428d67 ("io_uring: add support for ring mapped supplied buffers") Signed-off-by: Hao Xu <howeyxu@tencent.com> [pavel: 5.19 rebase] Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
-rw-r--r--fs/io_uring.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c
index e6d8cafdd28e6a..84b45ed91b2d3b 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1729,9 +1729,16 @@ static void io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
if (!(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)))
return;
- /* don't recycle if we already did IO to this buffer */
- if (req->flags & REQ_F_PARTIAL_IO)
+ /*
+ * For legacy provided buffer mode, don't recycle if we already did
+ * IO to this buffer. For ring-mapped provided buffer mode, we should
+ * increment ring->head to explicitly monopolize the buffer to avoid
+ * multiple use.
+ */
+ if ((req->flags & REQ_F_BUFFER_SELECTED) &&
+ (req->flags & REQ_F_PARTIAL_IO))
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.
@@ -1739,8 +1746,13 @@ static void io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
*/
if (req->flags & REQ_F_BUFFER_RING) {
if (req->buf_list) {
- req->buf_index = req->buf_list->bgid;
- req->flags &= ~REQ_F_BUFFER_RING;
+ if (req->flags & REQ_F_PARTIAL_IO) {
+ req->buf_list->head++;
+ req->buf_list = NULL;
+ } else {
+ req->buf_index = req->buf_list->bgid;
+ req->flags &= ~REQ_F_BUFFER_RING;
+ }
}
return;
}