Skip to content

Commit c3f9109

Browse files
committed
io_uring/kbuf: flag request if buffer pool is empty after buffer pick
Normally we do an extra roundtrip for retries even if the buffer pool has depleted, as we don't check that upfront. Rather than add this check, have the buffer selection methods mark the request with REQ_F_BL_EMPTY if the used buffer group is out of buffers after this selection. This is very cheap to do once we're all the way inside there anyway, and it gives the caller a chance to make better decisions on how to proceed. For example, recv/recvmsg multishot could check this flag when it decides whether to keep receiving or not. Signed-off-by: Jens Axboe <[email protected]>
1 parent 792060d commit c3f9109

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

include/linux/io_uring_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ enum {
480480
REQ_F_POLL_NO_LAZY_BIT,
481481
REQ_F_CANCEL_SEQ_BIT,
482482
REQ_F_CAN_POLL_BIT,
483+
REQ_F_BL_EMPTY_BIT,
483484

484485
/* not a real bit, just to check we're not overflowing the space */
485486
__REQ_F_LAST_BIT,
@@ -556,6 +557,8 @@ enum {
556557
REQ_F_CANCEL_SEQ = IO_REQ_FLAG(REQ_F_CANCEL_SEQ_BIT),
557558
/* file is pollable */
558559
REQ_F_CAN_POLL = IO_REQ_FLAG(REQ_F_CAN_POLL_BIT),
560+
/* buffer list was empty after selection of buffer */
561+
REQ_F_BL_EMPTY = IO_REQ_FLAG(REQ_F_BL_EMPTY_BIT),
559562
};
560563

561564
typedef void (*io_req_tw_func_t)(struct io_kiocb *req, struct io_tw_state *ts);

io_uring/kbuf.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ static void __user *io_provided_buffer_select(struct io_kiocb *req, size_t *len,
139139
list_del(&kbuf->list);
140140
if (*len == 0 || *len > kbuf->len)
141141
*len = kbuf->len;
142+
if (list_empty(&bl->buf_list))
143+
req->flags |= REQ_F_BL_EMPTY;
142144
req->flags |= REQ_F_BUFFER_SELECTED;
143145
req->kbuf = kbuf;
144146
req->buf_index = kbuf->bid;
@@ -152,12 +154,16 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
152154
unsigned int issue_flags)
153155
{
154156
struct io_uring_buf_ring *br = bl->buf_ring;
157+
__u16 tail, head = bl->head;
155158
struct io_uring_buf *buf;
156-
__u16 head = bl->head;
157159

158-
if (unlikely(smp_load_acquire(&br->tail) == head))
160+
tail = smp_load_acquire(&br->tail);
161+
if (unlikely(tail == head))
159162
return NULL;
160163

164+
if (head + 1 == tail)
165+
req->flags |= REQ_F_BL_EMPTY;
166+
161167
head &= bl->mask;
162168
/* mmaped buffers are always contig */
163169
if (bl->is_mmap || head < IO_BUFFER_LIST_BUF_PER_PAGE) {

0 commit comments

Comments
 (0)