162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#ifndef IOU_KBUF_H
362306a36Sopenharmony_ci#define IOU_KBUF_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <uapi/linux/io_uring.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_cistruct io_buffer_list {
862306a36Sopenharmony_ci	/*
962306a36Sopenharmony_ci	 * If ->buf_nr_pages is set, then buf_pages/buf_ring are used. If not,
1062306a36Sopenharmony_ci	 * then these are classic provided buffers and ->buf_list is used.
1162306a36Sopenharmony_ci	 */
1262306a36Sopenharmony_ci	union {
1362306a36Sopenharmony_ci		struct list_head buf_list;
1462306a36Sopenharmony_ci		struct {
1562306a36Sopenharmony_ci			struct page **buf_pages;
1662306a36Sopenharmony_ci			struct io_uring_buf_ring *buf_ring;
1762306a36Sopenharmony_ci		};
1862306a36Sopenharmony_ci		struct rcu_head rcu;
1962306a36Sopenharmony_ci	};
2062306a36Sopenharmony_ci	__u16 bgid;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	/* below is for ring provided buffers */
2362306a36Sopenharmony_ci	__u16 buf_nr_pages;
2462306a36Sopenharmony_ci	__u16 nr_entries;
2562306a36Sopenharmony_ci	__u16 head;
2662306a36Sopenharmony_ci	__u16 mask;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* ring mapped provided buffers */
2962306a36Sopenharmony_ci	__u8 is_mapped;
3062306a36Sopenharmony_ci	/* ring mapped provided buffers, but mmap'ed by application */
3162306a36Sopenharmony_ci	__u8 is_mmap;
3262306a36Sopenharmony_ci	/* bl is visible from an RCU point of view for lookup */
3362306a36Sopenharmony_ci	__u8 is_ready;
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct io_buffer {
3762306a36Sopenharmony_ci	struct list_head list;
3862306a36Sopenharmony_ci	__u64 addr;
3962306a36Sopenharmony_ci	__u32 len;
4062306a36Sopenharmony_ci	__u16 bid;
4162306a36Sopenharmony_ci	__u16 bgid;
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid __user *io_buffer_select(struct io_kiocb *req, size_t *len,
4562306a36Sopenharmony_ci			      unsigned int issue_flags);
4662306a36Sopenharmony_civoid io_destroy_buffers(struct io_ring_ctx *ctx);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciint io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
4962306a36Sopenharmony_ciint io_remove_buffers(struct io_kiocb *req, unsigned int issue_flags);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciint io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
5262306a36Sopenharmony_ciint io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciint io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg);
5562306a36Sopenharmony_ciint io_unregister_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_civoid io_kbuf_mmap_list_free(struct io_ring_ctx *ctx);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciunsigned int __io_put_kbuf(struct io_kiocb *req, unsigned issue_flags);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_civoid io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_civoid *io_pbuf_get_address(struct io_ring_ctx *ctx, unsigned long bgid);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic inline void io_kbuf_recycle_ring(struct io_kiocb *req)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	/*
6862306a36Sopenharmony_ci	 * We don't need to recycle for REQ_F_BUFFER_RING, we can just clear
6962306a36Sopenharmony_ci	 * the flag and hence ensure that bl->head doesn't get incremented.
7062306a36Sopenharmony_ci	 * If the tail has already been incremented, hang on to it.
7162306a36Sopenharmony_ci	 * The exception is partial io, that case we should increment bl->head
7262306a36Sopenharmony_ci	 * to monopolize the buffer.
7362306a36Sopenharmony_ci	 */
7462306a36Sopenharmony_ci	if (req->buf_list) {
7562306a36Sopenharmony_ci		if (req->flags & REQ_F_PARTIAL_IO) {
7662306a36Sopenharmony_ci			/*
7762306a36Sopenharmony_ci			 * If we end up here, then the io_uring_lock has
7862306a36Sopenharmony_ci			 * been kept held since we retrieved the buffer.
7962306a36Sopenharmony_ci			 * For the io-wq case, we already cleared
8062306a36Sopenharmony_ci			 * req->buf_list when the buffer was retrieved,
8162306a36Sopenharmony_ci			 * hence it cannot be set here for that case.
8262306a36Sopenharmony_ci			 */
8362306a36Sopenharmony_ci			req->buf_list->head++;
8462306a36Sopenharmony_ci			req->buf_list = NULL;
8562306a36Sopenharmony_ci		} else {
8662306a36Sopenharmony_ci			req->buf_index = req->buf_list->bgid;
8762306a36Sopenharmony_ci			req->flags &= ~REQ_F_BUFFER_RING;
8862306a36Sopenharmony_ci		}
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic inline bool io_do_buffer_select(struct io_kiocb *req)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	if (!(req->flags & REQ_F_BUFFER_SELECT))
9562306a36Sopenharmony_ci		return false;
9662306a36Sopenharmony_ci	return !(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING));
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline void io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	if (req->flags & REQ_F_BUFFER_SELECTED)
10262306a36Sopenharmony_ci		io_kbuf_recycle_legacy(req, issue_flags);
10362306a36Sopenharmony_ci	if (req->flags & REQ_F_BUFFER_RING)
10462306a36Sopenharmony_ci		io_kbuf_recycle_ring(req);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic inline unsigned int __io_put_kbuf_list(struct io_kiocb *req,
10862306a36Sopenharmony_ci					      struct list_head *list)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	unsigned int ret = IORING_CQE_F_BUFFER | (req->buf_index << IORING_CQE_BUFFER_SHIFT);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (req->flags & REQ_F_BUFFER_RING) {
11362306a36Sopenharmony_ci		if (req->buf_list) {
11462306a36Sopenharmony_ci			req->buf_index = req->buf_list->bgid;
11562306a36Sopenharmony_ci			req->buf_list->head++;
11662306a36Sopenharmony_ci		}
11762306a36Sopenharmony_ci		req->flags &= ~REQ_F_BUFFER_RING;
11862306a36Sopenharmony_ci	} else {
11962306a36Sopenharmony_ci		req->buf_index = req->kbuf->bgid;
12062306a36Sopenharmony_ci		list_add(&req->kbuf->list, list);
12162306a36Sopenharmony_ci		req->flags &= ~REQ_F_BUFFER_SELECTED;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return ret;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline unsigned int io_put_kbuf_comp(struct io_kiocb *req)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	lockdep_assert_held(&req->ctx->completion_lock);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (!(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)))
13262306a36Sopenharmony_ci		return 0;
13362306a36Sopenharmony_ci	return __io_put_kbuf_list(req, &req->ctx->io_buffers_comp);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic inline unsigned int io_put_kbuf(struct io_kiocb *req,
13762306a36Sopenharmony_ci				       unsigned issue_flags)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	if (!(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)))
14162306a36Sopenharmony_ci		return 0;
14262306a36Sopenharmony_ci	return __io_put_kbuf(req, issue_flags);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci#endif
145