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/mock: add sync read/write

Add support for synchronous zero read/write for mock files.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/571f3c9fe688e918256a06a722d3db6ced9ca3d5.1750599274.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Pavel Begunkov and committed by
Jens Axboe
d1aa0346 4aac001f

+65 -6
+3 -1
include/uapi/linux/io_uring/mock_file.h
··· 5 5 6 6 enum { 7 7 IORING_MOCK_FEAT_CMD_COPY, 8 + IORING_MOCK_FEAT_RW_ZERO, 8 9 9 10 IORING_MOCK_FEAT_END, 10 11 }; ··· 18 17 struct io_uring_mock_create { 19 18 __u32 out_fd; 20 19 __u32 flags; 21 - __u64 __resv[15]; 20 + __u64 file_size; 21 + __u64 __resv[14]; 22 22 }; 23 23 24 24 enum {
+62 -5
io_uring/mock_file.c
··· 9 9 #include <linux/io_uring_types.h> 10 10 #include <uapi/linux/io_uring/mock_file.h> 11 11 12 + struct io_mock_file { 13 + size_t size; 14 + }; 15 + 12 16 #define IO_VALID_COPY_CMD_FLAGS IORING_MOCK_COPY_FROM 13 17 14 18 static int io_copy_regbuf(struct iov_iter *reg_iter, void __user *ubuf) ··· 86 82 return -ENOTSUPP; 87 83 } 88 84 85 + static ssize_t io_mock_read_iter(struct kiocb *iocb, struct iov_iter *to) 86 + { 87 + struct io_mock_file *mf = iocb->ki_filp->private_data; 88 + size_t len = iov_iter_count(to); 89 + 90 + if (iocb->ki_pos + len > mf->size) 91 + return -EINVAL; 92 + return iov_iter_zero(len, to); 93 + } 94 + 95 + static ssize_t io_mock_write_iter(struct kiocb *iocb, struct iov_iter *from) 96 + { 97 + struct io_mock_file *mf = iocb->ki_filp->private_data; 98 + size_t len = iov_iter_count(from); 99 + 100 + if (iocb->ki_pos + len > mf->size) 101 + return -EINVAL; 102 + iov_iter_advance(from, len); 103 + return len; 104 + } 105 + 106 + static loff_t io_mock_llseek(struct file *file, loff_t offset, int whence) 107 + { 108 + struct io_mock_file *mf = file->private_data; 109 + 110 + return fixed_size_llseek(file, offset, whence, mf->size); 111 + } 112 + 113 + static int io_mock_release(struct inode *inode, struct file *file) 114 + { 115 + struct io_mock_file *mf = file->private_data; 116 + 117 + kfree(mf); 118 + return 0; 119 + } 120 + 89 121 static const struct file_operations io_mock_fops = { 90 122 .owner = THIS_MODULE, 123 + .release = io_mock_release, 91 124 .uring_cmd = io_mock_cmd, 125 + .read_iter = io_mock_read_iter, 126 + .write_iter = io_mock_write_iter, 127 + .llseek = io_mock_llseek, 92 128 }; 93 129 94 130 static int io_create_mock_file(struct io_uring_cmd *cmd, unsigned int issue_flags) 95 131 { 96 132 const struct io_uring_sqe *sqe = cmd->sqe; 97 133 struct io_uring_mock_create mc, __user *uarg; 134 + struct io_mock_file *mf = NULL; 98 135 struct file *file = NULL; 99 136 size_t uarg_size; 100 - int fd, ret; 137 + int fd = -1, ret; 101 138 102 139 /* 103 140 * It's a testing only driver that allows exercising edge cases ··· 159 114 return -EFAULT; 160 115 if (!mem_is_zero(mc.__resv, sizeof(mc.__resv)) || mc.flags) 161 116 return -EINVAL; 117 + if (mc.file_size > SZ_1G) 118 + return -EINVAL; 119 + mf = kzalloc(sizeof(*mf), GFP_KERNEL_ACCOUNT); 120 + if (!mf) 121 + return -ENOMEM; 162 122 163 - fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); 123 + ret = fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); 164 124 if (fd < 0) 165 - return fd; 125 + goto fail; 166 126 127 + mf->size = mc.file_size; 167 128 file = anon_inode_create_getfile("[io_uring_mock]", &io_mock_fops, 168 - NULL, O_RDWR | O_CLOEXEC, NULL); 129 + mf, O_RDWR | O_CLOEXEC, NULL); 169 130 if (IS_ERR(file)) { 170 131 ret = PTR_ERR(file); 171 132 goto fail; 172 133 } 134 + 135 + file->f_mode |= FMODE_READ | FMODE_CAN_READ | 136 + FMODE_WRITE | FMODE_CAN_WRITE | 137 + FMODE_LSEEK; 173 138 174 139 mc.out_fd = fd; 175 140 if (copy_to_user(uarg, &mc, uarg_size)) { ··· 191 136 fd_install(fd, file); 192 137 return 0; 193 138 fail: 194 - put_unused_fd(fd); 139 + if (fd >= 0) 140 + put_unused_fd(fd); 141 + kfree(mf); 195 142 return ret; 196 143 } 197 144