Skip to content

Commit bf4a6eb

Browse files
joannekoongaxboe
authored andcommitted
io_uring/kbuf: support kernel-managed buffer rings in buffer selection
Allow kernel-managed buffers to be selected. This requires modifying the io_br_sel struct to separate the fields for address and val, since a kernel address cannot be distinguished from a negative val when error checking. Auto-commit any selected kernel-managed buffer. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260306003224.3620942-3-joannelkoong@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent ff16884 commit bf4a6eb

2 files changed

Lines changed: 16 additions & 8 deletions

File tree

include/linux/io_uring_types.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ struct io_mapped_region {
9898
*/
9999
struct io_br_sel {
100100
struct io_buffer_list *buf_list;
101-
/*
102-
* Some selection parts return the user address, others return an error.
103-
*/
104101
union {
102+
/* for classic/ring provided buffers */
105103
void __user *addr;
106-
ssize_t val;
104+
/* for kernel-managed buffers */
105+
void *kaddr;
107106
};
107+
ssize_t val;
108108
};
109109

110110

io_uring/kbuf.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len,
164164
return 1;
165165
}
166166

167-
static bool io_should_commit(struct io_kiocb *req, unsigned int issue_flags)
167+
static bool io_should_commit(struct io_kiocb *req, struct io_buffer_list *bl,
168+
unsigned int issue_flags)
168169
{
169170
/*
170171
* If we came in unlocked, we have no choice but to consume the
@@ -179,7 +180,11 @@ static bool io_should_commit(struct io_kiocb *req, unsigned int issue_flags)
179180
if (issue_flags & IO_URING_F_UNLOCKED)
180181
return true;
181182

182-
/* uring_cmd commits kbuf upfront, no need to auto-commit */
183+
/* kernel-managed buffers are auto-committed */
184+
if (bl->flags & IOBL_KERNEL_MANAGED)
185+
return true;
186+
187+
/* multishot uring_cmd commits kbuf upfront, no need to auto-commit */
183188
if (!io_file_can_poll(req) && !io_is_uring_cmd(req))
184189
return true;
185190
return false;
@@ -209,9 +214,12 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len,
209214
req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT;
210215
req->buf_index = READ_ONCE(buf->bid);
211216
sel.buf_list = bl;
212-
sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr));
217+
if (bl->flags & IOBL_KERNEL_MANAGED)
218+
sel.kaddr = (void *)(uintptr_t)READ_ONCE(buf->addr);
219+
else
220+
sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr));
213221

214-
if (io_should_commit(req, issue_flags)) {
222+
if (io_should_commit(req, bl, issue_flags)) {
215223
io_kbuf_commit(req, sel.buf_list, *len, 1);
216224
sel.buf_list = NULL;
217225
}

0 commit comments

Comments
 (0)