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