]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
io_uring: add IORING_REGISTER_RSRC
authorPavel Begunkov <asml.silence@gmail.com>
Sun, 25 Apr 2021 13:32:21 +0000 (14:32 +0100)
committerJens Axboe <axboe@kernel.dk>
Sun, 25 Apr 2021 16:14:04 +0000 (10:14 -0600)
Add a new io_uring_register() opcode for rsrc registeration. Instead of
accepting a pointer to resources, fds or iovecs, it @arg is now pointing
to a struct io_uring_rsrc_register, and the second argument tells how
large that struct is to make it easily extendible by adding new fields.

All that is done mainly to be able to pass in a pointer with tags. Pass
it in and enable CQE posting for file resources. Doesn't support setting
tags on update yet.

A design choice made here is to not post CQEs on rsrc de-registration,
but only when we updated-removed it by rsrc dynamic update.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/c498aaec32a4bb277b2406b9069662c02cdda98c.1619356238.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c
include/uapi/linux/io_uring.h

index 36b9651588f9838eef4e2711da0d99145a899cdd..0088eeef82ec2e0bda09acee7c0476fff24aa82f 100644 (file)
@@ -7589,7 +7589,7 @@ static struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx)
 }
 
 static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
-                                unsigned nr_args)
+                                unsigned nr_args, u64 __user *tags)
 {
        __s32 __user *fds = (__s32 __user *) arg;
        struct file *file;
@@ -7616,17 +7616,24 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
                goto out_free;
 
        for (i = 0; i < nr_args; i++, ctx->nr_user_files++) {
-               if (copy_from_user(&fd, &fds[i], sizeof(fd))) {
+               u64 tag = 0;
+
+               if ((tags && copy_from_user(&tag, &tags[i], sizeof(tag))) ||
+                   copy_from_user(&fd, &fds[i], sizeof(fd))) {
                        ret = -EFAULT;
                        goto out_fput;
                }
                /* allow sparse sets */
-               if (fd == -1)
+               if (fd == -1) {
+                       ret = -EINVAL;
+                       if (unlikely(tag))
+                               goto out_fput;
                        continue;
+               }
 
                file = fget(fd);
                ret = -EBADF;
-               if (!file)
+               if (unlikely(!file))
                        goto out_fput;
 
                /*
@@ -7640,6 +7647,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
                        fput(file);
                        goto out_fput;
                }
+               ctx->file_data->tags[i] = tag;
                io_fixed_file_set(io_fixed_file_slot(&ctx->file_table, i), file);
        }
 
@@ -9743,6 +9751,29 @@ static int io_register_rsrc_update(struct io_ring_ctx *ctx, unsigned type,
        return __io_register_rsrc_update(ctx, type, &up, nr_args);
 }
 
+static int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
+                           unsigned int size)
+{
+       struct io_uring_rsrc_register rr;
+
+       /* keep it extendible */
+       if (size != sizeof(rr))
+               return -EINVAL;
+
+       memset(&rr, 0, sizeof(rr));
+       if (copy_from_user(&rr, arg, size))
+               return -EFAULT;
+       if (!rr.nr)
+               return -EINVAL;
+
+       switch (rr.type) {
+       case IORING_RSRC_FILE:
+               return io_sqe_files_register(ctx, u64_to_user_ptr(rr.data),
+                                            rr.nr, u64_to_user_ptr(rr.tags));
+       }
+       return -EINVAL;
+}
+
 static bool io_register_op_must_quiesce(int op)
 {
        switch (op) {
@@ -9752,6 +9783,7 @@ static bool io_register_op_must_quiesce(int op)
        case IORING_REGISTER_PROBE:
        case IORING_REGISTER_PERSONALITY:
        case IORING_UNREGISTER_PERSONALITY:
+       case IORING_REGISTER_RSRC:
                return false;
        default:
                return true;
@@ -9820,7 +9852,7 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
                ret = io_sqe_buffers_unregister(ctx);
                break;
        case IORING_REGISTER_FILES:
-               ret = io_sqe_files_register(ctx, arg, nr_args);
+               ret = io_sqe_files_register(ctx, arg, nr_args, NULL);
                break;
        case IORING_UNREGISTER_FILES:
                ret = -EINVAL;
@@ -9877,6 +9909,9 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
        case IORING_REGISTER_RESTRICTIONS:
                ret = io_register_restrictions(ctx, arg, nr_args);
                break;
+       case IORING_REGISTER_RSRC:
+               ret = io_register_rsrc(ctx, arg, nr_args);
+               break;
        default:
                ret = -EINVAL;
                break;
index d363e0c4fd218f2f2612f31238516c3b6a23489a..ce7b2fce6713a26cff131cff9c0ec5bd3edafcda 100644 (file)
@@ -298,6 +298,7 @@ enum {
        IORING_UNREGISTER_PERSONALITY           = 10,
        IORING_REGISTER_RESTRICTIONS            = 11,
        IORING_REGISTER_ENABLE_RINGS            = 12,
+       IORING_REGISTER_RSRC                    = 13,
 
        /* this goes last */
        IORING_REGISTER_LAST
@@ -320,6 +321,13 @@ enum {
        IORING_RSRC_FILE                = 0,
 };
 
+struct io_uring_rsrc_register {
+       __u32 type;
+       __u32 nr;
+       __aligned_u64 data;
+       __aligned_u64 tags;
+};
+
 /* Skip updating fd indexes set to this value in the fd table */
 #define IORING_REGISTER_FILES_SKIP     (-2)