Skip to content

Commit a66e4cb

Browse files
committed
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
2 parents 23a60a0 + 7fdbc5f commit a66e4cb

File tree

5 files changed

+27
-17
lines changed

5 files changed

+27
-17
lines changed

include/linux/io_uring.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ enum io_uring_cmd_flags {
1616
IO_URING_F_SQE128 = 4,
1717
IO_URING_F_CQE32 = 8,
1818
IO_URING_F_IOPOLL = 16,
19+
20+
/* the request is executed from poll, it should not be freed */
21+
IO_URING_F_MULTISHOT = 32,
1922
};
2023

2124
struct io_uring_cmd {

io_uring/io_uring.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,7 @@ int io_poll_issue(struct io_kiocb *req, bool *locked)
17681768
io_tw_lock(req->ctx, locked);
17691769
if (unlikely(req->task->flags & PF_EXITING))
17701770
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);
17721772
}
17731773

17741774
struct io_wq_work *io_wq_free_work(struct io_wq_work *work)

io_uring/io_uring.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ enum {
1717
IOU_ISSUE_SKIP_COMPLETE = -EIOCBQUEUED,
1818

1919
/*
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
2222
* removed and the result is set on req->cqe.res.
2323
*/
2424
IOU_STOP_MULTISHOT = -ECANCELED,

io_uring/net.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ struct io_sr_msg {
6767
struct io_kiocb *notif;
6868
};
6969

70-
#define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED)
71-
7270
int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
7371
{
7472
struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown);
@@ -591,7 +589,8 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
591589
* again (for multishot).
592590
*/
593591
static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
594-
unsigned int cflags, bool mshot_finished)
592+
unsigned int cflags, bool mshot_finished,
593+
unsigned issue_flags)
595594
{
596595
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
597596
io_req_set_res(req, *ret, cflags);
@@ -614,7 +613,7 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
614613

615614
io_req_set_res(req, *ret, cflags);
616615

617-
if (req->flags & REQ_F_POLLED)
616+
if (issue_flags & IO_URING_F_MULTISHOT)
618617
*ret = IOU_STOP_MULTISHOT;
619618
else
620619
*ret = IOU_OK;
@@ -773,8 +772,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
773772
if (ret < min_ret) {
774773
if (ret == -EAGAIN && force_nonblock) {
775774
ret = io_setup_async_msg(req, kmsg, issue_flags);
776-
if (ret == -EAGAIN && (req->flags & IO_APOLL_MULTI_POLLED) ==
777-
IO_APOLL_MULTI_POLLED) {
775+
if (ret == -EAGAIN && (issue_flags & IO_URING_F_MULTISHOT)) {
778776
io_kbuf_recycle(req, issue_flags);
779777
return IOU_ISSUE_SKIP_COMPLETE;
780778
}
@@ -803,7 +801,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
803801
if (kmsg->msg.msg_inq)
804802
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
805803

806-
if (!io_recv_finish(req, &ret, cflags, mshot_finished))
804+
if (!io_recv_finish(req, &ret, cflags, mshot_finished, issue_flags))
807805
goto retry_multishot;
808806

809807
if (mshot_finished) {
@@ -869,7 +867,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
869867
ret = sock_recvmsg(sock, &msg, flags);
870868
if (ret < min_ret) {
871869
if (ret == -EAGAIN && force_nonblock) {
872-
if ((req->flags & IO_APOLL_MULTI_POLLED) == IO_APOLL_MULTI_POLLED) {
870+
if (issue_flags & IO_URING_F_MULTISHOT) {
873871
io_kbuf_recycle(req, issue_flags);
874872
return IOU_ISSUE_SKIP_COMPLETE;
875873
}
@@ -902,7 +900,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
902900
if (msg.msg_inq)
903901
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
904902

905-
if (!io_recv_finish(req, &ret, cflags, ret <= 0))
903+
if (!io_recv_finish(req, &ret, cflags, ret <= 0, issue_flags))
906904
goto retry_multishot;
907905

908906
return ret;
@@ -1289,8 +1287,7 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
12891287
* return EAGAIN to arm the poll infra since it
12901288
* has already been done
12911289
*/
1292-
if ((req->flags & IO_APOLL_MULTI_POLLED) ==
1293-
IO_APOLL_MULTI_POLLED)
1290+
if (issue_flags & IO_URING_F_MULTISHOT)
12941291
ret = IOU_ISSUE_SKIP_COMPLETE;
12951292
return ret;
12961293
}
@@ -1315,9 +1312,7 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
13151312
goto retry;
13161313

13171314
io_req_set_res(req, ret, 0);
1318-
if (req->flags & REQ_F_POLLED)
1319-
return IOU_STOP_MULTISHOT;
1320-
return IOU_OK;
1315+
return (issue_flags & IO_URING_F_MULTISHOT) ? IOU_STOP_MULTISHOT : IOU_OK;
13211316
}
13221317

13231318
int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)

io_uring/poll.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
228228
return IOU_POLL_DONE;
229229
if (v & IO_POLL_CANCEL_FLAG)
230230
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;
231238

232239
/* the mask was stashed in __io_poll_execute */
233240
if (!req->cqe.res) {
@@ -239,6 +246,8 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
239246
continue;
240247
if (req->apoll_events & EPOLLONESHOT)
241248
return IOU_POLL_DONE;
249+
if (io_is_uring_fops(req->file))
250+
return IOU_POLL_DONE;
242251

243252
/* multishot, just fill a CQE and proceed */
244253
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
@@ -258,6 +267,9 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
258267
return ret;
259268
}
260269

270+
/* force the next iteration to vfs_poll() */
271+
req->cqe.res = 0;
272+
261273
/*
262274
* Release all references, retry if someone tried to restart
263275
* task_work while we were executing it.

0 commit comments

Comments
 (0)