Skip to content

Commit 6f1cbf6

Browse files
Ming Leiaxboe
authored andcommitted
io_uring: fix buffer auto-commit for multishot uring_cmd
Commit 620a50c ("io_uring: uring_cmd: add multishot support") added multishot uring_cmd support with explicit buffer upfront commit via io_uring_mshot_cmd_post_cqe(). However, the buffer selection path in io_ring_buffer_select() was auto-committing buffers for non-pollable files, which conflicts with uring_cmd's explicit upfront commit model. This way consumes the whole selected buffer immediately, and causes failure on the following buffer selection. Fix this by checking uring_cmd to identify operations that handle buffer commit explicitly, and skip auto-commit for these operations. Cc: Caleb Sander Mateos <[email protected]> Fixes: 620a50c ("io_uring: uring_cmd: add multishot support") Signed-off-by: Ming Lei <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent c5efc6a commit 6f1cbf6

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

io_uring/kbuf.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,27 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len,
155155
return 1;
156156
}
157157

158+
static bool io_should_commit(struct io_kiocb *req, unsigned int issue_flags)
159+
{
160+
/*
161+
* If we came in unlocked, we have no choice but to consume the
162+
* buffer here, otherwise nothing ensures that the buffer won't
163+
* get used by others. This does mean it'll be pinned until the
164+
* IO completes, coming in unlocked means we're being called from
165+
* io-wq context and there may be further retries in async hybrid
166+
* mode. For the locked case, the caller must call commit when
167+
* the transfer completes (or if we get -EAGAIN and must poll of
168+
* retry).
169+
*/
170+
if (issue_flags & IO_URING_F_UNLOCKED)
171+
return true;
172+
173+
/* uring_cmd commits kbuf upfront, no need to auto-commit */
174+
if (!io_file_can_poll(req) && req->opcode != IORING_OP_URING_CMD)
175+
return true;
176+
return false;
177+
}
178+
158179
static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len,
159180
struct io_buffer_list *bl,
160181
unsigned int issue_flags)
@@ -181,17 +202,7 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len,
181202
sel.buf_list = bl;
182203
sel.addr = u64_to_user_ptr(buf->addr);
183204

184-
if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) {
185-
/*
186-
* If we came in unlocked, we have no choice but to consume the
187-
* buffer here, otherwise nothing ensures that the buffer won't
188-
* get used by others. This does mean it'll be pinned until the
189-
* IO completes, coming in unlocked means we're being called from
190-
* io-wq context and there may be further retries in async hybrid
191-
* mode. For the locked case, the caller must call commit when
192-
* the transfer completes (or if we get -EAGAIN and must poll of
193-
* retry).
194-
*/
205+
if (io_should_commit(req, issue_flags)) {
195206
io_kbuf_commit(req, sel.buf_list, *len, 1);
196207
sel.buf_list = NULL;
197208
}

0 commit comments

Comments
 (0)