diff mbox series

[5.19,6/6] io_uring: kbuf: fix bug of not consuming ring buffer in partial io case

Message ID 20220611122952.942096-1-hao.xu@linux.dev (mailing list archive)
State New
Headers show
Series [for-5.20,1/6] io_uring: poll: remove unnecessary req->ref set | expand

Commit Message

Hao Xu June 11, 2022, 12:29 p.m. UTC
From: Hao Xu <howeyxu@tencent.com>

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>
---
 io_uring/kbuf.c |  9 +++++++--
 io_uring/kbuf.h | 10 ++++++++--
 2 files changed, 15 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index d2b2b4728381..0680b63af1d2 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -49,8 +49,13 @@  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;
 	}
diff --git a/io_uring/kbuf.h b/io_uring/kbuf.h
index b58d9d20c97e..9ecb175e60a9 100644
--- a/io_uring/kbuf.h
+++ b/io_uring/kbuf.h
@@ -58,8 +58,14 @@  static inline 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;
 	__io_kbuf_recycle(req, issue_flags);
 }