io_uring/rsrc: add request -> io_rsrc_node mapper io_uring-rsrc
authorJens Axboe <axboe@kernel.dk>
Wed, 30 Oct 2024 00:06:53 +0000 (18:06 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 31 Oct 2024 00:54:43 +0000 (18:54 -0600)
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/rsrc.c
io_uring/rsrc.h

index 9791f70d5d866270fb8a182d7fd2244827d1ce3d..4362a3ad56ec2c0865ca23e781ea3012413e0fae 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/nospec.h>
 #include <linux/hugetlb.h>
 #include <linux/compat.h>
+#include <linux/bvec.h>
+#include <linux/blk-mq.h>
 #include <linux/io_uring.h>
 
 #include <uapi/linux/io_uring.h>
@@ -461,6 +463,9 @@ void io_free_rsrc_node(struct io_rsrc_node *node)
                if (node->buf)
                        io_buffer_unmap(node->ctx, node);
                break;
+       case IORING_RSRC_KBUFFER:
+               node->kbuf_fn(node);
+               break;
        default:
                WARN_ON_ONCE(1);
                break;
@@ -1079,6 +1084,62 @@ int io_register_clone_buffers(struct io_ring_ctx *ctx, void __user *arg)
        return ret;
 }
 
+struct io_rsrc_node *io_rsrc_map_request(struct io_ring_ctx *ctx,
+                                        struct request *req,
+                                        void (*kbuf_fn)(struct io_rsrc_node *))
+{
+       struct io_mapped_ubuf *imu = NULL;
+       struct io_rsrc_node *node = NULL;
+       struct req_iterator rq_iter;
+       struct bio_vec bv;
+       int nr_bvecs;
+
+       if (!bio_has_data(req->bio))
+               goto out;
+
+       nr_bvecs = 0;
+       rq_for_each_bvec(bv, req, rq_iter)
+               nr_bvecs++;
+       if (!nr_bvecs)
+               goto out;
+
+       node = io_rsrc_node_alloc(ctx, IORING_RSRC_KBUFFER);
+       if (!node)
+               goto out;
+       node->buf = NULL;
+
+       imu = kvmalloc(struct_size(imu, bvec, nr_bvecs), GFP_NOIO);
+       if (!imu)
+               goto out;
+
+       imu->ubuf = 0;
+       imu->len = 0;
+       if (req->bio != req->biotail) {
+               int idx = 0;
+
+               rq_for_each_bvec(bv, req, rq_iter) {
+                       imu->bvec[idx++] = bv;
+                       imu->len += bv.bv_len;
+               }
+       } else {
+               struct bio *bio = req->bio;
+
+               imu->bvec[0] = *__bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
+               imu->len = imu->bvec[0].bv_len;
+       }
+       imu->nr_bvecs = nr_bvecs;
+       imu->folio_shift = PAGE_SHIFT;
+       refcount_set(&imu->refs, 1);
+       node->buf = imu;
+       node->kbuf_fn = kbuf_fn;
+       return node;
+out:
+       if (node)
+               io_put_rsrc_node(node);
+       kfree(imu);
+       return NULL;
+}
+
 int io_local_buf_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_ring_ctx *ctx = req->ctx;
index b0cd0a644ea2fc93ce9ee9e49375e320a13c338b..1f968315a33f0b90f31220135b6178e69ba85f7d 100644 (file)
@@ -11,6 +11,7 @@
 enum {
        IORING_RSRC_FILE                = 0,
        IORING_RSRC_BUFFER              = 1,
+       IORING_RSRC_KBUFFER             = 2,
 };
 
 struct io_rsrc_node {
@@ -19,6 +20,7 @@ struct io_rsrc_node {
        u16                             type;
 
        u64 tag;
+       void (*kbuf_fn)(struct io_rsrc_node *);
        union {
                unsigned long file_ptr;
                struct io_mapped_ubuf *buf;
@@ -52,6 +54,10 @@ int io_import_fixed(int ddir, struct iov_iter *iter,
                           struct io_mapped_ubuf *imu,
                           u64 buf_addr, size_t len);
 
+struct io_rsrc_node *io_rsrc_map_request(struct io_ring_ctx *ctx,
+                                        struct request *req,
+                                        void (*kbuf_fn)(struct io_rsrc_node *));
+
 int io_register_clone_buffers(struct io_ring_ctx *ctx, void __user *arg);
 int io_sqe_buffers_unregister(struct io_ring_ctx *ctx);
 int io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,