13b77495aSJens Axboe // SPDX-License-Identifier: GPL-2.0 23b77495aSJens Axboe #ifndef IOU_KBUF_H 33b77495aSJens Axboe #define IOU_KBUF_H 43b77495aSJens Axboe 53b77495aSJens Axboe #include <uapi/linux/io_uring.h> 63b77495aSJens Axboe 7*a69307a5SJens Axboe enum { 8*a69307a5SJens Axboe /* ring mapped provided buffers */ 9*a69307a5SJens Axboe IOBL_BUF_RING = 1, 10*a69307a5SJens Axboe /* ring mapped provided buffers, but mmap'ed by application */ 11*a69307a5SJens Axboe IOBL_MMAP = 2, 12*a69307a5SJens Axboe }; 13*a69307a5SJens Axboe 143b77495aSJens Axboe struct io_buffer_list { 153b77495aSJens Axboe /* 163b77495aSJens Axboe * If ->buf_nr_pages is set, then buf_pages/buf_ring are used. If not, 173b77495aSJens Axboe * then these are classic provided buffers and ->buf_list is used. 183b77495aSJens Axboe */ 193b77495aSJens Axboe union { 203b77495aSJens Axboe struct list_head buf_list; 213b77495aSJens Axboe struct { 223b77495aSJens Axboe struct page **buf_pages; 233b77495aSJens Axboe struct io_uring_buf_ring *buf_ring; 243b77495aSJens Axboe }; 255cf4f52eSJens Axboe struct rcu_head rcu; 263b77495aSJens Axboe }; 273b77495aSJens Axboe __u16 bgid; 283b77495aSJens Axboe 293b77495aSJens Axboe /* below is for ring provided buffers */ 303b77495aSJens Axboe __u16 buf_nr_pages; 313b77495aSJens Axboe __u16 nr_entries; 323b77495aSJens Axboe __u16 head; 333b77495aSJens Axboe __u16 mask; 3425a2c188SJens Axboe 35*a69307a5SJens Axboe __u16 flags; 366b69c4abSJens Axboe 37*a69307a5SJens Axboe atomic_t refs; 383b77495aSJens Axboe }; 393b77495aSJens Axboe 403b77495aSJens Axboe struct io_buffer { 413b77495aSJens Axboe struct list_head list; 423b77495aSJens Axboe __u64 addr; 433b77495aSJens Axboe __u32 len; 443b77495aSJens Axboe __u16 bid; 453b77495aSJens Axboe __u16 bgid; 463b77495aSJens Axboe }; 473b77495aSJens Axboe 4835c8711cSJens Axboe enum { 4935c8711cSJens Axboe /* can alloc a bigger vec */ 5035c8711cSJens Axboe KBUF_MODE_EXPAND = 1, 5135c8711cSJens Axboe /* if bigger vec allocated, free old one */ 5235c8711cSJens Axboe KBUF_MODE_FREE = 2, 5335c8711cSJens Axboe }; 5435c8711cSJens Axboe 5535c8711cSJens Axboe struct buf_sel_arg { 5635c8711cSJens Axboe struct iovec *iovs; 5735c8711cSJens Axboe size_t out_len; 5835c8711cSJens Axboe size_t max_len; 5935c8711cSJens Axboe int nr_iovs; 6035c8711cSJens Axboe int mode; 6135c8711cSJens Axboe }; 6235c8711cSJens Axboe 633b77495aSJens Axboe void __user *io_buffer_select(struct io_kiocb *req, size_t *len, 643b77495aSJens Axboe unsigned int issue_flags); 6535c8711cSJens Axboe int io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg, 6635c8711cSJens Axboe unsigned int issue_flags); 6735c8711cSJens Axboe int io_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg); 683b77495aSJens Axboe void io_destroy_buffers(struct io_ring_ctx *ctx); 693b77495aSJens Axboe 703b77495aSJens Axboe int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 713b77495aSJens Axboe int io_remove_buffers(struct io_kiocb *req, unsigned int issue_flags); 723b77495aSJens Axboe 733b77495aSJens Axboe int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 743b77495aSJens Axboe int io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags); 753b77495aSJens Axboe 763b77495aSJens Axboe int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg); 773b77495aSJens Axboe int io_unregister_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg); 78d293b1a8SJens Axboe int io_register_pbuf_status(struct io_ring_ctx *ctx, void __user *arg); 793b77495aSJens Axboe 808435c6f3SJens Axboe void __io_put_kbuf(struct io_kiocb *req, unsigned issue_flags); 8153ccf69bSPavel Begunkov 8289d528baSDylan Yudaken bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags); 83795bbbc8SHao Xu 84561e4f94SJens Axboe void io_put_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl); 85561e4f94SJens Axboe struct io_buffer_list *io_pbuf_get_bl(struct io_ring_ctx *ctx, 86561e4f94SJens Axboe unsigned long bgid); 8787585b05SJens Axboe int io_pbuf_mmap(struct file *file, struct vm_area_struct *vma); 88c56e022cSJens Axboe 8989d528baSDylan Yudaken static inline bool io_kbuf_recycle_ring(struct io_kiocb *req) 90795bbbc8SHao Xu { 91795bbbc8SHao Xu /* 92795bbbc8SHao Xu * We don't need to recycle for REQ_F_BUFFER_RING, we can just clear 93795bbbc8SHao Xu * the flag and hence ensure that bl->head doesn't get incremented. 94795bbbc8SHao Xu * If the tail has already been incremented, hang on to it. 95795bbbc8SHao Xu * The exception is partial io, that case we should increment bl->head 96795bbbc8SHao Xu * to monopolize the buffer. 97795bbbc8SHao Xu */ 98795bbbc8SHao Xu if (req->buf_list) { 99795bbbc8SHao Xu req->buf_index = req->buf_list->bgid; 10035c8711cSJens Axboe req->flags &= ~(REQ_F_BUFFER_RING|REQ_F_BUFFERS_COMMIT); 10189d528baSDylan Yudaken return true; 102795bbbc8SHao Xu } 10389d528baSDylan Yudaken return false; 104795bbbc8SHao Xu } 105024b8fdeSHao Xu 1063b77495aSJens Axboe static inline bool io_do_buffer_select(struct io_kiocb *req) 1073b77495aSJens Axboe { 1083b77495aSJens Axboe if (!(req->flags & REQ_F_BUFFER_SELECT)) 1093b77495aSJens Axboe return false; 1103b77495aSJens Axboe return !(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)); 1113b77495aSJens Axboe } 1123b77495aSJens Axboe 11389d528baSDylan Yudaken static inline bool io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags) 1143b77495aSJens Axboe { 115186daf23SJens Axboe if (req->flags & REQ_F_BL_NO_RECYCLE) 116186daf23SJens Axboe return false; 117024b8fdeSHao Xu if (req->flags & REQ_F_BUFFER_SELECTED) 11889d528baSDylan Yudaken return io_kbuf_recycle_legacy(req, issue_flags); 119024b8fdeSHao Xu if (req->flags & REQ_F_BUFFER_RING) 12089d528baSDylan Yudaken return io_kbuf_recycle_ring(req); 12189d528baSDylan Yudaken return false; 1223b77495aSJens Axboe } 1233b77495aSJens Axboe 12435c8711cSJens Axboe static inline void __io_put_kbuf_ring(struct io_kiocb *req, int nr) 1253b77495aSJens Axboe { 12635c8711cSJens Axboe struct io_buffer_list *bl = req->buf_list; 12735c8711cSJens Axboe 12835c8711cSJens Axboe if (bl) { 12935c8711cSJens Axboe if (req->flags & REQ_F_BUFFERS_COMMIT) { 13035c8711cSJens Axboe bl->head += nr; 13135c8711cSJens Axboe req->flags &= ~REQ_F_BUFFERS_COMMIT; 13235c8711cSJens Axboe } 13335c8711cSJens Axboe req->buf_index = bl->bgid; 13432f3c434SDylan Yudaken } 1353b77495aSJens Axboe req->flags &= ~REQ_F_BUFFER_RING; 1368435c6f3SJens Axboe } 1378435c6f3SJens Axboe 1388435c6f3SJens Axboe static inline void __io_put_kbuf_list(struct io_kiocb *req, 1398435c6f3SJens Axboe struct list_head *list) 1408435c6f3SJens Axboe { 1418435c6f3SJens Axboe if (req->flags & REQ_F_BUFFER_RING) { 14235c8711cSJens Axboe __io_put_kbuf_ring(req, 1); 1433b77495aSJens Axboe } else { 14432f3c434SDylan Yudaken req->buf_index = req->kbuf->bgid; 1453b77495aSJens Axboe list_add(&req->kbuf->list, list); 1463b77495aSJens Axboe req->flags &= ~REQ_F_BUFFER_SELECTED; 1473b77495aSJens Axboe } 1483b77495aSJens Axboe } 1493b77495aSJens Axboe 150bbbef3e9SMing Lei static inline void io_kbuf_drop(struct io_kiocb *req) 1513b77495aSJens Axboe { 1523b77495aSJens Axboe lockdep_assert_held(&req->ctx->completion_lock); 1533b77495aSJens Axboe 1543b77495aSJens Axboe if (!(req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING))) 155bbbef3e9SMing Lei return; 1568435c6f3SJens Axboe 1578435c6f3SJens Axboe __io_put_kbuf_list(req, &req->ctx->io_buffers_comp); 1583b77495aSJens Axboe } 1593b77495aSJens Axboe 16035c8711cSJens Axboe static inline unsigned int __io_put_kbufs(struct io_kiocb *req, int nbufs, 1613b77495aSJens Axboe unsigned issue_flags) 1623b77495aSJens Axboe { 1638435c6f3SJens Axboe unsigned int ret; 1643b77495aSJens Axboe 1658435c6f3SJens Axboe if (!(req->flags & (REQ_F_BUFFER_RING | REQ_F_BUFFER_SELECTED))) 1663b77495aSJens Axboe return 0; 1678435c6f3SJens Axboe 1688435c6f3SJens Axboe ret = IORING_CQE_F_BUFFER | (req->buf_index << IORING_CQE_BUFFER_SHIFT); 1698435c6f3SJens Axboe if (req->flags & REQ_F_BUFFER_RING) 17035c8711cSJens Axboe __io_put_kbuf_ring(req, nbufs); 1718435c6f3SJens Axboe else 1728435c6f3SJens Axboe __io_put_kbuf(req, issue_flags); 1738435c6f3SJens Axboe return ret; 1743b77495aSJens Axboe } 17535c8711cSJens Axboe 17635c8711cSJens Axboe static inline unsigned int io_put_kbuf(struct io_kiocb *req, 17735c8711cSJens Axboe unsigned issue_flags) 17835c8711cSJens Axboe { 17935c8711cSJens Axboe return __io_put_kbufs(req, 1, issue_flags); 18035c8711cSJens Axboe } 18135c8711cSJens Axboe 18235c8711cSJens Axboe static inline unsigned int io_put_kbufs(struct io_kiocb *req, int nbufs, 18335c8711cSJens Axboe unsigned issue_flags) 18435c8711cSJens Axboe { 18535c8711cSJens Axboe return __io_put_kbufs(req, nbufs, issue_flags); 18635c8711cSJens Axboe } 1873b77495aSJens Axboe #endif 188