Skip to content

Commit de48bc0

Browse files
joannekoongaxboe
authored andcommitted
io_uring/kbuf: add recycling for kernel managed buffer rings
Add an interface for buffers to be recycled back into a kernel-managed buffer ring. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20260306003224.3620942-6-joannelkoong@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 9aa9e55 commit de48bc0

2 files changed

Lines changed: 60 additions & 1 deletion

File tree

include/linux/io_uring/cmd.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void io_uring_cmd_issue_blocking(struct io_uring_cmd *ioucmd);
7878

7979
/*
8080
* Select a buffer from the provided buffer group for multishot uring_cmd.
81-
* Returns the selected buffer address and size.
81+
* Returns the selected buffer address, size, and id.
8282
*/
8383
struct io_br_sel io_uring_cmd_buffer_select(struct io_uring_cmd *ioucmd,
8484
unsigned buf_group, size_t *len,
@@ -95,6 +95,10 @@ int io_uring_buf_ring_pin(struct io_uring_cmd *cmd, unsigned buf_group,
9595
unsigned issue_flags, struct io_buffer_list **out_bl);
9696
int io_uring_buf_ring_unpin(struct io_uring_cmd *cmd, unsigned buf_group,
9797
unsigned issue_flags);
98+
99+
int io_uring_kmbuf_recycle(struct io_uring_cmd *cmd, unsigned int buf_group,
100+
u64 addr, unsigned int len, unsigned int bid,
101+
unsigned int issue_flags);
98102
#else
99103
static inline int
100104
io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
@@ -150,6 +154,13 @@ static inline int io_uring_buf_ring_unpin(struct io_uring_cmd *cmd,
150154
{
151155
return -EOPNOTSUPP;
152156
}
157+
static inline int io_uring_kmbuf_recycle(struct io_uring_cmd *cmd,
158+
unsigned int buf_group, u64 addr,
159+
unsigned int len, unsigned int bid,
160+
unsigned int issue_flags)
161+
{
162+
return -EOPNOTSUPP;
163+
}
153164
#endif
154165

155166
static inline struct io_uring_cmd *io_uring_cmd_from_tw(struct io_tw_req tw_req)

io_uring/kbuf.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,54 @@ void io_kbuf_drop_legacy(struct io_kiocb *req)
102102
req->kbuf = NULL;
103103
}
104104

105+
int io_uring_kmbuf_recycle(struct io_uring_cmd *cmd, unsigned int buf_group,
106+
u64 addr, unsigned int len, unsigned int bid,
107+
unsigned int issue_flags)
108+
{
109+
struct io_kiocb *req = cmd_to_io_kiocb(cmd);
110+
struct io_ring_ctx *ctx = req->ctx;
111+
struct io_uring_buf_ring *br;
112+
struct io_uring_buf *buf;
113+
struct io_buffer_list *bl;
114+
unsigned int required_flags;
115+
int ret = -EINVAL;
116+
117+
if (WARN_ON_ONCE(req->flags & REQ_F_BUFFERS_COMMIT))
118+
return ret;
119+
120+
io_ring_submit_lock(ctx, issue_flags);
121+
122+
bl = io_buffer_get_list(ctx, buf_group);
123+
124+
if (!bl)
125+
goto err;
126+
127+
required_flags = IOBL_BUF_RING | IOBL_KERNEL_MANAGED;
128+
if (WARN_ON_ONCE((bl->flags & required_flags) != required_flags))
129+
goto err;
130+
131+
br = bl->buf_ring;
132+
133+
if (WARN_ON_ONCE((__u16)(br->tail - bl->head) >= bl->nr_entries))
134+
goto err;
135+
136+
buf = &br->bufs[(br->tail) & bl->mask];
137+
138+
buf->addr = addr;
139+
buf->len = len;
140+
buf->bid = bid;
141+
142+
req->flags &= ~REQ_F_BUFFER_RING;
143+
144+
br->tail++;
145+
ret = 0;
146+
147+
err:
148+
io_ring_submit_unlock(ctx, issue_flags);
149+
return ret;
150+
}
151+
EXPORT_SYMBOL_GPL(io_uring_kmbuf_recycle);
152+
105153
bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags)
106154
{
107155
struct io_ring_ctx *ctx = req->ctx;

0 commit comments

Comments
 (0)