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: support for async read/write

Let the user to specify a delay to read/write request. io_uring will
start a timer, return -EIOCBQUEUED and complete the request
asynchronously after the delay pass.

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

authored by

Pavel Begunkov and committed by
Jens Axboe
0c98a443 2f71d238

+58 -5
+3 -1
include/uapi/linux/io_uring/mock_file.h
··· 7 7 IORING_MOCK_FEAT_CMD_COPY, 8 8 IORING_MOCK_FEAT_RW_ZERO, 9 9 IORING_MOCK_FEAT_RW_NOWAIT, 10 + IORING_MOCK_FEAT_RW_ASYNC, 10 11 11 12 IORING_MOCK_FEAT_END, 12 13 }; ··· 25 24 __u32 out_fd; 26 25 __u32 flags; 27 26 __u64 file_size; 28 - __u64 __resv[14]; 27 + __u64 rw_delay_ns; 28 + __u64 __resv[13]; 29 29 }; 30 30 31 31 enum {
+55 -4
io_uring/mock_file.c
··· 4 4 #include <linux/miscdevice.h> 5 5 #include <linux/module.h> 6 6 #include <linux/anon_inodes.h> 7 + #include <linux/ktime.h> 8 + #include <linux/hrtimer.h> 7 9 8 10 #include <linux/io_uring/cmd.h> 9 11 #include <linux/io_uring_types.h> 10 12 #include <uapi/linux/io_uring/mock_file.h> 11 13 14 + struct io_mock_iocb { 15 + struct kiocb *iocb; 16 + struct hrtimer timer; 17 + int res; 18 + }; 19 + 12 20 struct io_mock_file { 13 - size_t size; 21 + size_t size; 22 + u64 rw_delay_ns; 14 23 }; 15 24 16 25 #define IO_VALID_COPY_CMD_FLAGS IORING_MOCK_COPY_FROM ··· 95 86 return -ENOTSUPP; 96 87 } 97 88 89 + static enum hrtimer_restart io_mock_rw_timer_expired(struct hrtimer *timer) 90 + { 91 + struct io_mock_iocb *mio = container_of(timer, struct io_mock_iocb, timer); 92 + struct kiocb *iocb = mio->iocb; 93 + 94 + WRITE_ONCE(iocb->private, NULL); 95 + iocb->ki_complete(iocb, mio->res); 96 + kfree(mio); 97 + return HRTIMER_NORESTART; 98 + } 99 + 100 + static ssize_t io_mock_delay_rw(struct kiocb *iocb, size_t len) 101 + { 102 + struct io_mock_file *mf = iocb->ki_filp->private_data; 103 + struct io_mock_iocb *mio; 104 + 105 + mio = kzalloc(sizeof(*mio), GFP_KERNEL); 106 + if (!mio) 107 + return -ENOMEM; 108 + 109 + mio->iocb = iocb; 110 + mio->res = len; 111 + hrtimer_setup(&mio->timer, io_mock_rw_timer_expired, 112 + CLOCK_MONOTONIC, HRTIMER_MODE_REL); 113 + hrtimer_start(&mio->timer, ns_to_ktime(mf->rw_delay_ns), 114 + HRTIMER_MODE_REL); 115 + return -EIOCBQUEUED; 116 + } 117 + 98 118 static ssize_t io_mock_read_iter(struct kiocb *iocb, struct iov_iter *to) 99 119 { 100 120 struct io_mock_file *mf = iocb->ki_filp->private_data; 101 121 size_t len = iov_iter_count(to); 122 + size_t nr_zeroed; 102 123 103 124 if (iocb->ki_pos + len > mf->size) 104 125 return -EINVAL; 105 - return iov_iter_zero(len, to); 126 + nr_zeroed = iov_iter_zero(len, to); 127 + if (!mf->rw_delay_ns || nr_zeroed != len) 128 + return nr_zeroed; 129 + 130 + return io_mock_delay_rw(iocb, len); 106 131 } 107 132 108 133 static ssize_t io_mock_write_iter(struct kiocb *iocb, struct iov_iter *from) ··· 146 103 147 104 if (iocb->ki_pos + len > mf->size) 148 105 return -EINVAL; 149 - iov_iter_advance(from, len); 150 - return len; 106 + if (!mf->rw_delay_ns) { 107 + iov_iter_advance(from, len); 108 + return len; 109 + } 110 + 111 + return io_mock_delay_rw(iocb, len); 151 112 } 152 113 153 114 static loff_t io_mock_llseek(struct file *file, loff_t offset, int whence) ··· 212 165 return -EINVAL; 213 166 if (mc.file_size > SZ_1G) 214 167 return -EINVAL; 168 + if (mc.rw_delay_ns > NSEC_PER_SEC) 169 + return -EINVAL; 170 + 215 171 mf = kzalloc(sizeof(*mf), GFP_KERNEL_ACCOUNT); 216 172 if (!mf) 217 173 return -ENOMEM; ··· 224 174 goto fail; 225 175 226 176 mf->size = mc.file_size; 177 + mf->rw_delay_ns = mc.rw_delay_ns; 227 178 file = anon_inode_create_getfile("[io_uring_mock]", &io_mock_fops, 228 179 mf, O_RDWR | O_CLOEXEC, NULL); 229 180 if (IS_ERR(file)) {