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.

Merge tag 'io_uring-6.1-2022-11-18' of git://git.kernel.dk/linux

Pull io_uring fixes from Jens Axboe:
"This is mostly fixing issues around the poll rework, but also two
tweaks for the multishot handling for accept and receive.

All stable material"

* tag 'io_uring-6.1-2022-11-18' of git://git.kernel.dk/linux:
io_uring: disallow self-propelled ring polling
io_uring: fix multishot recv request leaks
io_uring: fix multishot accept request leaks
io_uring: fix tw losing poll events
io_uring: update res mask in io_poll_check_events

+27 -17
+3
include/linux/io_uring.h
··· 16 16 IO_URING_F_SQE128 = 4, 17 17 IO_URING_F_CQE32 = 8, 18 18 IO_URING_F_IOPOLL = 16, 19 + 20 + /* the request is executed from poll, it should not be freed */ 21 + IO_URING_F_MULTISHOT = 32, 19 22 }; 20 23 21 24 struct io_uring_cmd {
+1 -1
io_uring/io_uring.c
··· 1768 1768 io_tw_lock(req->ctx, locked); 1769 1769 if (unlikely(req->task->flags & PF_EXITING)) 1770 1770 return -EFAULT; 1771 - return io_issue_sqe(req, IO_URING_F_NONBLOCK); 1771 + return io_issue_sqe(req, IO_URING_F_NONBLOCK|IO_URING_F_MULTISHOT); 1772 1772 } 1773 1773 1774 1774 struct io_wq_work *io_wq_free_work(struct io_wq_work *work)
+2 -2
io_uring/io_uring.h
··· 17 17 IOU_ISSUE_SKIP_COMPLETE = -EIOCBQUEUED, 18 18 19 19 /* 20 - * Intended only when both REQ_F_POLLED and REQ_F_APOLL_MULTISHOT 21 - * are set to indicate to the poll runner that multishot should be 20 + * Intended only when both IO_URING_F_MULTISHOT is passed 21 + * to indicate to the poll runner that multishot should be 22 22 * removed and the result is set on req->cqe.res. 23 23 */ 24 24 IOU_STOP_MULTISHOT = -ECANCELED,
+9 -14
io_uring/net.c
··· 67 67 struct io_kiocb *notif; 68 68 }; 69 69 70 - #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED) 71 - 72 70 int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 73 71 { 74 72 struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown); ··· 589 591 * again (for multishot). 590 592 */ 591 593 static inline bool io_recv_finish(struct io_kiocb *req, int *ret, 592 - unsigned int cflags, bool mshot_finished) 594 + unsigned int cflags, bool mshot_finished, 595 + unsigned issue_flags) 593 596 { 594 597 if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { 595 598 io_req_set_res(req, *ret, cflags); ··· 613 614 614 615 io_req_set_res(req, *ret, cflags); 615 616 616 - if (req->flags & REQ_F_POLLED) 617 + if (issue_flags & IO_URING_F_MULTISHOT) 617 618 *ret = IOU_STOP_MULTISHOT; 618 619 else 619 620 *ret = IOU_OK; ··· 772 773 if (ret < min_ret) { 773 774 if (ret == -EAGAIN && force_nonblock) { 774 775 ret = io_setup_async_msg(req, kmsg, issue_flags); 775 - if (ret == -EAGAIN && (req->flags & IO_APOLL_MULTI_POLLED) == 776 - IO_APOLL_MULTI_POLLED) { 776 + if (ret == -EAGAIN && (issue_flags & IO_URING_F_MULTISHOT)) { 777 777 io_kbuf_recycle(req, issue_flags); 778 778 return IOU_ISSUE_SKIP_COMPLETE; 779 779 } ··· 801 803 if (kmsg->msg.msg_inq) 802 804 cflags |= IORING_CQE_F_SOCK_NONEMPTY; 803 805 804 - if (!io_recv_finish(req, &ret, cflags, mshot_finished)) 806 + if (!io_recv_finish(req, &ret, cflags, mshot_finished, issue_flags)) 805 807 goto retry_multishot; 806 808 807 809 if (mshot_finished) { ··· 867 869 ret = sock_recvmsg(sock, &msg, flags); 868 870 if (ret < min_ret) { 869 871 if (ret == -EAGAIN && force_nonblock) { 870 - if ((req->flags & IO_APOLL_MULTI_POLLED) == IO_APOLL_MULTI_POLLED) { 872 + if (issue_flags & IO_URING_F_MULTISHOT) { 871 873 io_kbuf_recycle(req, issue_flags); 872 874 return IOU_ISSUE_SKIP_COMPLETE; 873 875 } ··· 900 902 if (msg.msg_inq) 901 903 cflags |= IORING_CQE_F_SOCK_NONEMPTY; 902 904 903 - if (!io_recv_finish(req, &ret, cflags, ret <= 0)) 905 + if (!io_recv_finish(req, &ret, cflags, ret <= 0, issue_flags)) 904 906 goto retry_multishot; 905 907 906 908 return ret; ··· 1287 1289 * return EAGAIN to arm the poll infra since it 1288 1290 * has already been done 1289 1291 */ 1290 - if ((req->flags & IO_APOLL_MULTI_POLLED) == 1291 - IO_APOLL_MULTI_POLLED) 1292 + if (issue_flags & IO_URING_F_MULTISHOT) 1292 1293 ret = IOU_ISSUE_SKIP_COMPLETE; 1293 1294 return ret; 1294 1295 } ··· 1312 1315 goto retry; 1313 1316 1314 1317 io_req_set_res(req, ret, 0); 1315 - if (req->flags & REQ_F_POLLED) 1316 - return IOU_STOP_MULTISHOT; 1317 - return IOU_OK; 1318 + return (issue_flags & IO_URING_F_MULTISHOT) ? IOU_STOP_MULTISHOT : IOU_OK; 1318 1319 } 1319 1320 1320 1321 int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+12
io_uring/poll.c
··· 228 228 return IOU_POLL_DONE; 229 229 if (v & IO_POLL_CANCEL_FLAG) 230 230 return -ECANCELED; 231 + /* 232 + * cqe.res contains only events of the first wake up 233 + * and all others are be lost. Redo vfs_poll() to get 234 + * up to date state. 235 + */ 236 + if ((v & IO_POLL_REF_MASK) != 1) 237 + req->cqe.res = 0; 231 238 232 239 /* the mask was stashed in __io_poll_execute */ 233 240 if (!req->cqe.res) { ··· 245 238 if ((unlikely(!req->cqe.res))) 246 239 continue; 247 240 if (req->apoll_events & EPOLLONESHOT) 241 + return IOU_POLL_DONE; 242 + if (io_is_uring_fops(req->file)) 248 243 return IOU_POLL_DONE; 249 244 250 245 /* multishot, just fill a CQE and proceed */ ··· 266 257 if (ret < 0) 267 258 return ret; 268 259 } 260 + 261 + /* force the next iteration to vfs_poll() */ 262 + req->cqe.res = 0; 269 263 270 264 /* 271 265 * Release all references, retry if someone tried to restart