Skip to content

Commit 2ec33a6

Browse files
committed
io_uring/rw: ensure kiocb_end_write() is always called
A previous commit moved the notifications and end-write handling, but it is now missing a few spots where we also want to call both of those. Without that, we can potentially be missing file notifications, and more importantly, have an imbalance in the super_block writers sem accounting. Fixes: b000145 ("io_uring/rw: defer fsnotify calls to task context") Reported-by: Dave Chinner <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Jens Axboe <[email protected]>
1 parent 0092793 commit 2ec33a6

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

io_uring/rw.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,34 @@ static void kiocb_end_write(struct io_kiocb *req)
234234
}
235235
}
236236

237+
/*
238+
* Trigger the notifications after having done some IO, and finish the write
239+
* accounting, if any.
240+
*/
241+
static void io_req_io_end(struct io_kiocb *req)
242+
{
243+
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
244+
245+
WARN_ON(!in_task());
246+
247+
if (rw->kiocb.ki_flags & IOCB_WRITE) {
248+
kiocb_end_write(req);
249+
fsnotify_modify(req->file);
250+
} else {
251+
fsnotify_access(req->file);
252+
}
253+
}
254+
237255
static bool __io_complete_rw_common(struct io_kiocb *req, long res)
238256
{
239257
if (unlikely(res != req->cqe.res)) {
240258
if ((res == -EAGAIN || res == -EOPNOTSUPP) &&
241259
io_rw_should_reissue(req)) {
260+
/*
261+
* Reissue will start accounting again, finish the
262+
* current cycle.
263+
*/
264+
io_req_io_end(req);
242265
req->flags |= REQ_F_REISSUE | REQ_F_PARTIAL_IO;
243266
return true;
244267
}
@@ -264,15 +287,7 @@ static inline int io_fixup_rw_res(struct io_kiocb *req, long res)
264287

265288
static void io_req_rw_complete(struct io_kiocb *req, bool *locked)
266289
{
267-
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
268-
269-
if (rw->kiocb.ki_flags & IOCB_WRITE) {
270-
kiocb_end_write(req);
271-
fsnotify_modify(req->file);
272-
} else {
273-
fsnotify_access(req->file);
274-
}
275-
290+
io_req_io_end(req);
276291
io_req_task_complete(req, locked);
277292
}
278293

@@ -317,6 +332,11 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,
317332
req->file->f_pos = rw->kiocb.ki_pos;
318333
if (ret >= 0 && (rw->kiocb.ki_complete == io_complete_rw)) {
319334
if (!__io_complete_rw_common(req, ret)) {
335+
/*
336+
* Safe to call io_end from here as we're inline
337+
* from the submission path.
338+
*/
339+
io_req_io_end(req);
320340
io_req_set_res(req, final_ret,
321341
io_put_kbuf(req, issue_flags));
322342
return IOU_OK;

0 commit comments

Comments
 (0)