#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>
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;
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;
enum {
IORING_RSRC_FILE = 0,
IORING_RSRC_BUFFER = 1,
+ IORING_RSRC_KBUFFER = 2,
};
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;
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,