io_uring/kbuf: add helpers for getting/peeking multiple buffers
[linux-block.git] / io_uring / kbuf.h
index 5a9635ee021738c78f10c097b0ac9fc6e30f64fe..b90aca3a57fa7cac1c0c0ad70bb9fb161b197cf4 100644 (file)
@@ -41,8 +41,26 @@ struct io_buffer {
        __u16 bgid;
 };
 
+enum {
+       /* can alloc a bigger vec */
+       KBUF_MODE_EXPAND        = 1,
+       /* if bigger vec allocated, free old one */
+       KBUF_MODE_FREE          = 2,
+};
+
+struct buf_sel_arg {
+       struct iovec *iovs;
+       size_t out_len;
+       size_t max_len;
+       int nr_iovs;
+       int mode;
+};
+
 void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
                              unsigned int issue_flags);
+int io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg,
+                     unsigned int issue_flags);
+int io_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg);
 void io_destroy_buffers(struct io_ring_ctx *ctx);
 
 int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
@@ -75,7 +93,7 @@ static inline bool io_kbuf_recycle_ring(struct io_kiocb *req)
         */
        if (req->buf_list) {
                req->buf_index = req->buf_list->bgid;
-               req->flags &= ~REQ_F_BUFFER_RING;
+               req->flags &= ~(REQ_F_BUFFER_RING|REQ_F_BUFFERS_COMMIT);
                return true;
        }
        return false;
@@ -99,11 +117,16 @@ static inline bool io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
        return false;
 }
 
-static inline void __io_put_kbuf_ring(struct io_kiocb *req)
+static inline void __io_put_kbuf_ring(struct io_kiocb *req, int nr)
 {
-       if (req->buf_list) {
-               req->buf_index = req->buf_list->bgid;
-               req->buf_list->head++;
+       struct io_buffer_list *bl = req->buf_list;
+
+       if (bl) {
+               if (req->flags & REQ_F_BUFFERS_COMMIT) {
+                       bl->head += nr;
+                       req->flags &= ~REQ_F_BUFFERS_COMMIT;
+               }
+               req->buf_index = bl->bgid;
        }
        req->flags &= ~REQ_F_BUFFER_RING;
 }
@@ -112,7 +135,7 @@ static inline void __io_put_kbuf_list(struct io_kiocb *req,
                                      struct list_head *list)
 {
        if (req->flags & REQ_F_BUFFER_RING) {
-               __io_put_kbuf_ring(req);
+               __io_put_kbuf_ring(req, 1);
        } else {
                req->buf_index = req->kbuf->bgid;
                list_add(&req->kbuf->list, list);
@@ -130,8 +153,8 @@ static inline void io_kbuf_drop(struct io_kiocb *req)
        __io_put_kbuf_list(req, &req->ctx->io_buffers_comp);
 }
 
-static inline unsigned int io_put_kbuf(struct io_kiocb *req,
-                                      unsigned issue_flags)
+static inline unsigned int __io_put_kbufs(struct io_kiocb *req, int nbufs,
+                                         unsigned issue_flags)
 {
        unsigned int ret;
 
@@ -140,9 +163,21 @@ static inline unsigned int io_put_kbuf(struct io_kiocb *req,
 
        ret = IORING_CQE_F_BUFFER | (req->buf_index << IORING_CQE_BUFFER_SHIFT);
        if (req->flags & REQ_F_BUFFER_RING)
-               __io_put_kbuf_ring(req);
+               __io_put_kbuf_ring(req, nbufs);
        else
                __io_put_kbuf(req, issue_flags);
        return ret;
 }
+
+static inline unsigned int io_put_kbuf(struct io_kiocb *req,
+                                      unsigned issue_flags)
+{
+       return __io_put_kbufs(req, 1, issue_flags);
+}
+
+static inline unsigned int io_put_kbufs(struct io_kiocb *req, int nbufs,
+                                       unsigned issue_flags)
+{
+       return __io_put_kbufs(req, nbufs, issue_flags);
+}
 #endif