mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 15:40:03 +02:00
io_uring-7.3-20260911
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmqj5fsQHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgpmGsD/0W7eNXJd/tFNPOdDwTr1/3yciqYXw5QO5Q eb2SLyr34sAODOItTYoBrIZ5b1Mbgm0yhT1wJ3YrVKLNLVSvbDPNtx5qtnAGcKvm 09XsPmvlDcW8JLRsjd5dcsP+EDmgTNLuNGSeVycuTG91f5VD63vPHTKUhgKDabtC InM1LbIs2rz0tojdV6n4MOOF2AwZAOHqFtac+cQUCwuJhNtwUFClSUHxqYoP+JzE 97ores3f+ArAtmOoVeH2wSCZTmwdB7MxOB8jmt8fdNSprW8nxTO3oT/eQzYXvlM9 7LRJV/6SGVsWjuoEHAfW8G0p+JOzGGFvFIXGWEBenjtNmlyXJqfxYhkcLMw826ob pct3Rc5nheZbxKdCkHnY1AmEibS/c1kTZbDvSBXk9GLBKyQuI7B3yo163zMs3JjO YSAlLllDjdzOR6gCPg5HHZlywBWtXveC/xVBzDq7b1q07ysHFNO1yQplMM3U8sC0 Eic4RcFU4ld+/L2GmbdgRZ9ataZsju+RFojSogA0NzR18HqVNQuZiVbY764GSop9 HVW28lzoYamgvg5fLWJPrzJmdFrj/p8pi+cw1dK8uMk9VnFwdA740Nfhz1NWFS0Y TpvJtxc0f2ofrI1ilaa95vHC+wMyds1zxq9Bf4i9cgIhT17WqvE4SD0JMXmvza4k Yi72jzTTfQ== =zpCb -----END PGP SIGNATURE----- Merge tag 'io_uring-7.3-20260911' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux Pull io_uring fixes from Jens Axboe: - Fix a deadlock in the write path with superblock freezing - Fix an issue where a provided buffer ring would overconsume when using MSG_TRUNC - Keep the CQE flags on iopoll requests when adding kbuf flags * tag 'io_uring-7.3-20260911' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: io_uring/rw: keep CQE flags on iopoll requests when adding kbuf flags io_uring/net: don't overconsume buffers when using MSG_TRUNC io_uring/net: let io_recv_buf_select return the length of the buffer region io_uring/rw: end write accounting from ->ki_complete
This commit is contained in:
commit
42f961c42b
|
|
@ -853,7 +853,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||
static inline bool io_recv_finish(struct io_kiocb *req,
|
||||
struct io_async_msghdr *kmsg,
|
||||
struct io_br_sel *sel, bool mshot_finished,
|
||||
unsigned issue_flags)
|
||||
unsigned issue_flags, int consumed)
|
||||
{
|
||||
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
|
||||
unsigned int cflags = 0;
|
||||
|
|
@ -877,7 +877,7 @@ static inline bool io_recv_finish(struct io_kiocb *req,
|
|||
if (sr->flags & IORING_RECVSEND_BUNDLE) {
|
||||
size_t this_ret = sel->val - sr->done_io;
|
||||
|
||||
cflags |= io_put_kbufs(req, this_ret, sel->buf_list, io_bundle_nbufs(kmsg, this_ret));
|
||||
cflags |= io_put_kbufs(req, consumed, sel->buf_list, io_bundle_nbufs(kmsg, consumed));
|
||||
if (sr->flags & IORING_RECV_RETRY)
|
||||
cflags = req->cqe.flags | (cflags & CQE_F_MASK);
|
||||
if (sr->mshot_len && sel->val >= sr->mshot_len)
|
||||
|
|
@ -899,7 +899,7 @@ static inline bool io_recv_finish(struct io_kiocb *req,
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
cflags |= io_put_kbuf(req, sel->val, sel->buf_list);
|
||||
cflags |= io_put_kbuf(req, consumed, sel->buf_list);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1027,6 +1027,8 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
int ret, min_ret = 0;
|
||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||
bool mshot_finished = true;
|
||||
int consumed = 0;
|
||||
size_t len;
|
||||
|
||||
sock = sock_from_file(req->file);
|
||||
if (unlikely(!sock))
|
||||
|
|
@ -1042,9 +1044,8 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
|
||||
retry_multishot:
|
||||
sel.buf_list = NULL;
|
||||
len = sr->len;
|
||||
if (io_do_buffer_select(req)) {
|
||||
size_t len = sr->len;
|
||||
|
||||
sel = io_buffer_select(req, &len, sr->buf_group, issue_flags);
|
||||
if (!sel.addr)
|
||||
return -ENOBUFS;
|
||||
|
|
@ -1065,6 +1066,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
if (req->flags & REQ_F_APOLL_MULTISHOT) {
|
||||
ret = io_recvmsg_multishot(sock, sr, kmsg, flags,
|
||||
&mshot_finished);
|
||||
consumed = ret;
|
||||
} else {
|
||||
/* disable partial retry for recvmsg with cmsg attached */
|
||||
if (flags & MSG_WAITALL && !kmsg->msg.msg_controllen)
|
||||
|
|
@ -1072,6 +1074,15 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
|
||||
ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
|
||||
kmsg->uaddr, flags);
|
||||
/*
|
||||
* With MSG_TRUNC, the net layer will return the full size of
|
||||
* the packet, even if we only filled part of it in the buffers.
|
||||
* Adjust the returned size to consume only the real part of the
|
||||
* buffer.
|
||||
*/
|
||||
consumed = ret;
|
||||
if (ret > 0)
|
||||
consumed = min_t(size_t, ret, len);
|
||||
}
|
||||
|
||||
if (ret < min_ret) {
|
||||
|
|
@ -1098,7 +1109,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
io_kbuf_recycle(req, sel.buf_list, issue_flags);
|
||||
|
||||
sel.val = ret;
|
||||
if (!io_recv_finish(req, kmsg, &sel, mshot_finished, issue_flags))
|
||||
if (!io_recv_finish(req, kmsg, &sel, mshot_finished, issue_flags, consumed))
|
||||
goto retry_multishot;
|
||||
|
||||
return sel.val;
|
||||
|
|
@ -1108,6 +1119,7 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
|
|||
struct io_br_sel *sel, unsigned int issue_flags)
|
||||
{
|
||||
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
|
@ -1153,13 +1165,14 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
|
|||
/* special case 1 vec, can be a fast path */
|
||||
if (ret == 1) {
|
||||
sr->buf = arg.iovs[0].iov_base;
|
||||
sr->len = arg.iovs[0].iov_len;
|
||||
len = sr->len = arg.iovs[0].iov_len;
|
||||
goto map_ubuf;
|
||||
}
|
||||
iov_iter_init(&kmsg->msg.msg_iter, ITER_DEST, arg.iovs, ret,
|
||||
arg.out_len);
|
||||
arg.out_len);
|
||||
len = arg.out_len;
|
||||
} else {
|
||||
size_t len = sel->val;
|
||||
len = sel->val;
|
||||
|
||||
*sel = io_buffer_select(req, &len, sr->buf_group, issue_flags);
|
||||
if (!sel->addr)
|
||||
|
|
@ -1173,7 +1186,7 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
||||
|
|
@ -1183,9 +1196,10 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
struct io_br_sel sel;
|
||||
struct socket *sock;
|
||||
unsigned flags;
|
||||
int ret, min_ret = 0;
|
||||
int ret, min_ret = 0, consumed = 0;
|
||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||
bool mshot_finished;
|
||||
size_t len = 0;
|
||||
|
||||
sock = sock_from_file(req->file);
|
||||
if (unlikely(!sock))
|
||||
|
|
@ -1213,6 +1227,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
|
||||
retry_multishot:
|
||||
sel.buf_list = NULL;
|
||||
len = sr->len;
|
||||
if (io_do_buffer_select(req)) {
|
||||
sel.val = sr->len;
|
||||
ret = io_recv_buf_select(req, kmsg, &sel, issue_flags);
|
||||
|
|
@ -1220,6 +1235,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
kmsg->msg.msg_inq = -1;
|
||||
goto out_free;
|
||||
}
|
||||
len = ret;
|
||||
sr->buf = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1250,6 +1266,17 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
}
|
||||
|
||||
mshot_finished = ret <= 0;
|
||||
|
||||
/*
|
||||
* With MSG_TRUNC, the net layer will return the full size of
|
||||
* the packet, even if we only filled part of it in the buffers.
|
||||
* Adjust the returned size to consume only the real part of the
|
||||
* buffer.
|
||||
*/
|
||||
consumed = ret;
|
||||
if (ret > 0)
|
||||
consumed = min_t(size_t, ret, len);
|
||||
|
||||
if (ret > 0)
|
||||
ret += sr->done_io;
|
||||
else if (sr->done_io)
|
||||
|
|
@ -1258,7 +1285,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
io_kbuf_recycle(req, sel.buf_list, issue_flags);
|
||||
|
||||
sel.val = ret;
|
||||
if (!io_recv_finish(req, kmsg, &sel, mshot_finished, issue_flags))
|
||||
if (!io_recv_finish(req, kmsg, &sel, mshot_finished, issue_flags, consumed))
|
||||
goto retry_multishot;
|
||||
|
||||
return sel.val;
|
||||
|
|
|
|||
|
|
@ -517,20 +517,25 @@ static void io_req_end_write(struct io_kiocb *req)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger the notifications after having done some IO, and finish the write
|
||||
* accounting, if any.
|
||||
*/
|
||||
/* Trigger the notifications after having done some IO. */
|
||||
static void io_req_io_notify(struct io_kiocb *req)
|
||||
{
|
||||
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
|
||||
|
||||
if (rw->kiocb.ki_flags & IOCB_WRITE)
|
||||
fsnotify_modify(req->file);
|
||||
else
|
||||
fsnotify_access(req->file);
|
||||
}
|
||||
|
||||
/* Finish write accounting and notify, for inline completions only. */
|
||||
static void io_req_io_end(struct io_kiocb *req)
|
||||
{
|
||||
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
|
||||
|
||||
if (rw->kiocb.ki_flags & IOCB_WRITE) {
|
||||
if (rw->kiocb.ki_flags & IOCB_WRITE)
|
||||
io_req_end_write(req);
|
||||
fsnotify_modify(req->file);
|
||||
} else {
|
||||
fsnotify_access(req->file);
|
||||
}
|
||||
io_req_io_notify(req);
|
||||
}
|
||||
|
||||
static void __io_complete_rw_common(struct io_kiocb *req, long res)
|
||||
|
|
@ -563,7 +568,7 @@ void io_req_rw_complete(struct io_tw_req tw_req, io_tw_token_t tw)
|
|||
{
|
||||
struct io_kiocb *req = tw_req.req;
|
||||
|
||||
io_req_io_end(req);
|
||||
io_req_io_notify(req);
|
||||
|
||||
if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING))
|
||||
req->cqe.flags |= io_put_kbuf(req, max(req->cqe.res, 0), NULL);
|
||||
|
|
@ -577,6 +582,10 @@ static void io_complete_rw(struct kiocb *kiocb, long res)
|
|||
struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb);
|
||||
struct io_kiocb *req = cmd_to_io_kiocb(rw);
|
||||
|
||||
/* ring owner may block in freeze_super() before task_work runs */
|
||||
if (kiocb->ki_flags & IOCB_WRITE)
|
||||
io_req_end_write(req);
|
||||
|
||||
__io_complete_rw_common(req, res);
|
||||
io_req_set_res(req, io_fixup_rw_res(req, res), 0);
|
||||
req->io_task_work.func = io_req_rw_complete;
|
||||
|
|
@ -871,6 +880,7 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type)
|
|||
kiocb->private = NULL;
|
||||
kiocb->ki_flags |= IOCB_HIPRI;
|
||||
req->iopoll_completed = 0;
|
||||
req->cqe.flags = 0;
|
||||
if (ctx->flags & IORING_SETUP_HYBRID_IOPOLL) {
|
||||
/* make sure every req only blocks once*/
|
||||
req->flags &= ~REQ_F_IOPOLL_STATE;
|
||||
|
|
@ -1373,7 +1383,7 @@ int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin)
|
|||
list_del(&req->iopoll_node);
|
||||
wq_list_add_tail(&req->comp_list, &ctx->submit_state.compl_reqs);
|
||||
nr_events++;
|
||||
req->cqe.flags = io_put_kbuf(req, max(req->cqe.res, 0), NULL);
|
||||
req->cqe.flags |= io_put_kbuf(req, max(req->cqe.res, 0), NULL);
|
||||
if (!io_is_uring_cmd(req))
|
||||
io_req_rw_cleanup(req, 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user