| @@ -7118,7 +7118,8 @@ static int io_run_task_work_sig(void) · 7117 unmodified lines |
| 7118 | 7118 | * application must reap them itself, as they reside on the shared cq ring. |
| 7119 | 7119 | */ |
| 7120 | 7120 | static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, |
| 7121 | | − const sigset_t __user *sig, size_t sigsz) |
| 7121 | + const sigset_t __user *sig, size_t sigsz, |
| 7122 | + struct __kernel_timespec __user *uts) |
| 7122 | 7123 | { |
| 7123 | 7124 | struct io_wait_queue iowq = { |
| 7124 | 7125 | .wq = { |
| @@ -7130,6 +7131,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 5 unmodified lines |
| 7130 | 7131 | .to_wait = min_events, |
| 7131 | 7132 | }; |
| 7132 | 7133 | struct io_rings *rings = ctx->rings; |
| 7134 | + struct timespec64 ts; |
| 7135 | + signed long timeout = 0; |
| 7133 | 7136 | int ret = 0; |
| 7134 | 7137 | |
| 7135 | 7138 | do { |
| @@ -7152,6 +7155,12 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 16 unmodified lines |
| 7152 | 7155 | return ret; |
| 7153 | 7156 | } |
| 7154 | 7157 | |
| 7158 | + if (uts) { |
| 7159 | + if (get_timespec64(&ts, uts)) |
| 7160 | + return -EFAULT; |
| 7161 | + timeout = timespec64_to_jiffies(&ts); |
| 7162 | + } |
| 7163 | + |
| 7155 | 7164 | iowq.nr_timeouts = atomic_read(&ctx->cq_timeouts); |
| 7156 | 7165 | trace_io_uring_cqring_wait(ctx, min_events); |
| 7157 | 7166 | do { |
| @@ -7165,7 +7174,15 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 7 unmodified lines |
| 7165 | 7174 | break; |
| 7166 | 7175 | if (io_should_wake(&iowq, false)) |
| 7167 | 7176 | break; |
| 7168 | | − schedule(); |
| 7177 | + if (uts) { |
| 7178 | + timeout = schedule_timeout(timeout); |
| 7179 | + if (timeout == 0) { |
| 7180 | + ret = -ETIME; |
| 7181 | + break; |
| 7182 | + } |
| 7183 | + } else { |
| 7184 | + schedule(); |
| 7185 | + } |
| 7169 | 7186 | } while (1); |
| 7170 | 7187 | finish_wait(&ctx->wait, &iowq.wq); |
| 7171 | 7188 | |
| @@ -9167,9 +9184,39 @@ static void io_sqpoll_wait_sq(struct io_ring_ctx *ctx) · 1995 unmodified lines |
| 9167 | 9184 | finish_wait(&ctx->sqo_sq_wait, &wait); |
| 9168 | 9185 | } |
| 9169 | 9186 | |
| 9187 | +static int io_get_ext_arg(unsigned flags, const void __user *argp, size_t *argsz, |
| 9188 | + struct __kernel_timespec __user **ts, |
| 9189 | + const sigset_t __user **sig) |
| 9190 | +{ |
| 9191 | + struct io_uring_getevents_arg arg; |
| 9192 | + |
| 9193 | + /* |
| 9194 | + * If EXT_ARG isn't set, then we have no timespec and the argp pointer |
| 9195 | + * is just a pointer to the sigset_t. |
| 9196 | + */ |
| 9197 | + if (!(flags & IORING_ENTER_EXT_ARG)) { |
| 9198 | + *sig = (const sigset_t __user *) argp; |
| 9199 | + *ts = NULL; |
| 9200 | + return 0; |
| 9201 | + } |
| 9202 | + |
| 9203 | + /* |
| 9204 | + * EXT_ARG is set - ensure we agree on the size of it and copy in our |
| 9205 | + * timespec and sigset_t pointers if good. |
| 9206 | + */ |
| 9207 | + if (*argsz != sizeof(arg)) |
| 9208 | + return -EINVAL; |
| 9209 | + if (copy_from_user(&arg, argp, sizeof(arg))) |
| 9210 | + return -EFAULT; |
| 9211 | + *sig = u64_to_user_ptr(arg.sigmask); |
| 9212 | + *argsz = arg.sigmask_sz; |
| 9213 | + *ts = u64_to_user_ptr(arg.ts); |
| 9214 | + return 0; |
| 9215 | +} |
| 9216 | + |
| 9170 | 9217 | SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit, |
| 9171 | | − u32, min_complete, u32, flags, const sigset_t __user *, sig, |
| 9172 | | − size_t, sigsz) |
| 9218 | + u32, min_complete, u32, flags, const void __user *, argp, |
| 9219 | + size_t, argsz) |
| 9173 | 9220 | { |
| 9174 | 9221 | struct io_ring_ctx *ctx; |
| 9175 | 9222 | long ret = -EBADF; |
| @@ -9179,7 +9226,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit, · 3 unmodified lines |
| 9179 | 9226 | io_run_task_work(); |
| 9180 | 9227 | |
| 9181 | 9228 | if (flags & ~(IORING_ENTER_GETEVENTS | IORING_ENTER_SQ_WAKEUP | |
| 9182 | | − IORING_ENTER_SQ_WAIT)) |
| 9229 | + IORING_ENTER_SQ_WAIT | IORING_ENTER_EXT_ARG)) |
| 9183 | 9230 | return -EINVAL; |
| 9184 | 9231 | |
| 9185 | 9232 | f = fdget(fd); |
| @@ -9225,6 +9272,13 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit, · 39 unmodified lines |
| 9225 | 9272 | goto out; |
| 9226 | 9273 | } |
| 9227 | 9274 | if (flags & IORING_ENTER_GETEVENTS) { |
| 9275 | + const sigset_t __user *sig; |
| 9276 | + struct __kernel_timespec __user *ts; |
| 9277 | + |
| 9278 | + ret = io_get_ext_arg(flags, argp, &argsz, &ts, &sig); |
| 9279 | + if (unlikely(ret)) |
| 9280 | + goto out; |
| 9281 | + |
| 9228 | 9282 | min_complete = min(min_complete, ctx->cq_entries); |
| 9229 | 9283 | |
| 9230 | 9284 | /* |
| @@ -9237,7 +9291,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit, · 6 unmodified lines |
| 9237 | 9291 | !(ctx->flags & IORING_SETUP_SQPOLL)) { |
| 9238 | 9292 | ret = io_iopoll_check(ctx, min_complete); |
| 9239 | 9293 | } else { |
| 9240 | | − ret = io_cqring_wait(ctx, min_complete, sig, sigsz); |
| 9294 | + ret = io_cqring_wait(ctx, min_complete, sig, argsz, ts); |
| 9241 | 9295 | } |
| 9242 | 9296 | } |
| 9243 | 9297 | |
| @@ -9600,7 +9654,8 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, · 356 unmodified lines |
| 9600 | 9654 | p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP | |
| 9601 | 9655 | IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS | |
| 9602 | 9656 | IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL | |
| 9603 | | − IORING_FEAT_POLL_32BITS | IORING_FEAT_SQPOLL_NONFIXED; |
| 9657 | + IORING_FEAT_POLL_32BITS | IORING_FEAT_SQPOLL_NONFIXED | |
| 9658 | + IORING_FEAT_EXT_ARG; |
| 9604 | 9659 | |
| 9605 | 9660 | if (copy_to_user(params, p, sizeof(*p))) { |
| 9606 | 9661 | ret = -EFAULT; |