diff options
Diffstat (limited to 'io_uring/kbuf.c')
| -rw-r--r-- | io_uring/kbuf.c | 60 | 
1 files changed, 60 insertions, 0 deletions
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 815fb58da3ba..3478be6d02ab 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -20,6 +20,9 @@  /* BIDs are addressed by a 16-bit field in a CQE */  #define MAX_BIDS_PER_BGID (1 << 16) +/* Mapped buffer ring, return io_uring_buf from head */ +#define io_ring_head_to_buf(br, head, mask)	&(br)->bufs[(head) & (mask)] +  struct io_provide_buf {  	struct file			*file;  	__u64				addr; @@ -29,6 +32,34 @@ struct io_provide_buf {  	__u16				bid;  }; +bool io_kbuf_commit(struct io_kiocb *req, +		    struct io_buffer_list *bl, int len, int nr) +{ +	if (unlikely(!(req->flags & REQ_F_BUFFERS_COMMIT))) +		return true; + +	req->flags &= ~REQ_F_BUFFERS_COMMIT; + +	if (unlikely(len < 0)) +		return true; + +	if (bl->flags & IOBL_INC) { +		struct io_uring_buf *buf; + +		buf = io_ring_head_to_buf(bl->buf_ring, bl->head, bl->mask); +		if (WARN_ON_ONCE(len > buf->len)) +			len = buf->len; +		buf->len -= len; +		if (buf->len) { +			buf->addr += len; +			return false; +		} +	} + +	bl->head += nr; +	return true; +} +  static inline struct io_buffer_list *io_buffer_get_list(struct io_ring_ctx *ctx,  							unsigned int bgid)  { @@ -323,6 +354,35 @@ int io_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg)  	return io_provided_buffers_select(req, &arg->max_len, bl, arg->iovs);  } +static inline bool __io_put_kbuf_ring(struct io_kiocb *req, int len, int nr) +{ +	struct io_buffer_list *bl = req->buf_list; +	bool ret = true; + +	if (bl) { +		ret = io_kbuf_commit(req, bl, len, nr); +		req->buf_index = bl->bgid; +	} +	req->flags &= ~REQ_F_BUFFER_RING; +	return ret; +} + +unsigned int __io_put_kbufs(struct io_kiocb *req, int len, int nbufs) +{ +	unsigned int ret; + +	ret = IORING_CQE_F_BUFFER | (req->buf_index << IORING_CQE_BUFFER_SHIFT); + +	if (unlikely(!(req->flags & REQ_F_BUFFER_RING))) { +		io_kbuf_drop_legacy(req); +		return ret; +	} + +	if (!__io_put_kbuf_ring(req, len, nbufs)) +		ret |= IORING_CQE_F_BUF_MORE; +	return ret; +} +  static int __io_remove_buffers(struct io_ring_ctx *ctx,  			       struct io_buffer_list *bl, unsigned nbufs)  {  | 
