Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring/rsrc: allow cloning at an offset

Right now buffer cloning is an all-or-nothing kind of thing - either the
whole table is cloned from a source to a destination ring, or nothing at
all.

However, it's not always desired to clone the whole thing. Allow for
the application to specify a source and destination offset, and a
number of buffers to clone. If the destination offset is non-zero, then
allocate sparse nodes upfront.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

+30 -7
+4 -1
include/uapi/linux/io_uring.h
··· 719 719 struct io_uring_clone_buffers { 720 720 __u32 src_fd; 721 721 __u32 flags; 722 - __u32 pad[6]; 722 + __u32 src_off; 723 + __u32 dst_off; 724 + __u32 nr; 725 + __u32 pad[3]; 723 726 }; 724 727 725 728 struct io_uring_buf {
+26 -6
io_uring/rsrc.c
··· 927 927 return 0; 928 928 } 929 929 930 - static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx) 930 + static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx, 931 + struct io_uring_clone_buffers *arg) 931 932 { 933 + int i, ret, nbufs, off, nr; 932 934 struct io_rsrc_data data; 933 - int i, ret, nbufs; 934 935 935 936 /* 936 937 * Drop our own lock here. We'll setup the data we need and reference ··· 944 943 nbufs = src_ctx->buf_table.nr; 945 944 if (!nbufs) 946 945 goto out_unlock; 947 - ret = io_rsrc_data_alloc(&data, nbufs); 946 + ret = -EINVAL; 947 + if (!arg->nr) 948 + arg->nr = nbufs; 949 + else if (arg->nr > nbufs) 950 + goto out_unlock; 951 + ret = -EOVERFLOW; 952 + if (check_add_overflow(arg->nr, arg->src_off, &off)) 953 + goto out_unlock; 954 + if (off > nbufs) 955 + goto out_unlock; 956 + if (check_add_overflow(arg->nr, arg->dst_off, &off)) 957 + goto out_unlock; 958 + ret = -EINVAL; 959 + if (off > IORING_MAX_REG_BUFFERS) 960 + goto out_unlock; 961 + ret = io_rsrc_data_alloc(&data, off); 948 962 if (ret) 949 963 goto out_unlock; 950 964 951 - for (i = 0; i < nbufs; i++) { 965 + off = arg->dst_off; 966 + i = arg->src_off; 967 + nr = arg->nr; 968 + while (nr--) { 952 969 struct io_rsrc_node *dst_node, *src_node; 953 970 954 971 src_node = io_rsrc_node_lookup(&src_ctx->buf_table, i); ··· 982 963 refcount_inc(&src_node->buf->refs); 983 964 dst_node->buf = src_node->buf; 984 965 } 985 - data.nodes[i] = dst_node; 966 + data.nodes[off++] = dst_node; 967 + i++; 986 968 } 987 969 988 970 /* Have a ref on the bufs now, drop src lock and re-grab our own lock */ ··· 1038 1018 file = io_uring_register_get_file(buf.src_fd, registered_src); 1039 1019 if (IS_ERR(file)) 1040 1020 return PTR_ERR(file); 1041 - ret = io_clone_buffers(ctx, file->private_data); 1021 + ret = io_clone_buffers(ctx, file->private_data, &buf); 1042 1022 if (!registered_src) 1043 1023 fput(file); 1044 1024 return ret;