mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	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: b000145e99 ("io_uring/rw: defer fsnotify calls to task context")
Reported-by: Dave Chinner <david@fromorbit.com>
Link: https://lore.kernel.org/all/20221010050319.GC2703033@dread.disaster.area/
Signed-off-by: Jens Axboe <axboe@kernel.dk>
			
			
This commit is contained in:
		
							parent
							
								
									00927931cb
								
							
						
					
					
						commit
						2ec33a6c3c
					
				
					 1 changed files with 29 additions and 9 deletions
				
			
		|  | @ -234,11 +234,34 @@ static void kiocb_end_write(struct io_kiocb *req) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Trigger the notifications after having done some IO, and finish the write | ||||
|  * accounting, if any. | ||||
|  */ | ||||
| static void io_req_io_end(struct io_kiocb *req) | ||||
| { | ||||
| 	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); | ||||
| 
 | ||||
| 	WARN_ON(!in_task()); | ||||
| 
 | ||||
| 	if (rw->kiocb.ki_flags & IOCB_WRITE) { | ||||
| 		kiocb_end_write(req); | ||||
| 		fsnotify_modify(req->file); | ||||
| 	} else { | ||||
| 		fsnotify_access(req->file); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool __io_complete_rw_common(struct io_kiocb *req, long res) | ||||
| { | ||||
| 	if (unlikely(res != req->cqe.res)) { | ||||
| 		if ((res == -EAGAIN || res == -EOPNOTSUPP) && | ||||
| 		    io_rw_should_reissue(req)) { | ||||
| 			/*
 | ||||
| 			 * Reissue will start accounting again, finish the | ||||
| 			 * current cycle. | ||||
| 			 */ | ||||
| 			io_req_io_end(req); | ||||
| 			req->flags |= REQ_F_REISSUE | REQ_F_PARTIAL_IO; | ||||
| 			return true; | ||||
| 		} | ||||
|  | @ -264,15 +287,7 @@ static inline int io_fixup_rw_res(struct io_kiocb *req, long res) | |||
| 
 | ||||
| static void io_req_rw_complete(struct io_kiocb *req, bool *locked) | ||||
| { | ||||
| 	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); | ||||
| 
 | ||||
| 	if (rw->kiocb.ki_flags & IOCB_WRITE) { | ||||
| 		kiocb_end_write(req); | ||||
| 		fsnotify_modify(req->file); | ||||
| 	} else { | ||||
| 		fsnotify_access(req->file); | ||||
| 	} | ||||
| 
 | ||||
| 	io_req_io_end(req); | ||||
| 	io_req_task_complete(req, locked); | ||||
| } | ||||
| 
 | ||||
|  | @ -317,6 +332,11 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret, | |||
| 		req->file->f_pos = rw->kiocb.ki_pos; | ||||
| 	if (ret >= 0 && (rw->kiocb.ki_complete == io_complete_rw)) { | ||||
| 		if (!__io_complete_rw_common(req, ret)) { | ||||
| 			/*
 | ||||
| 			 * Safe to call io_end from here as we're inline | ||||
| 			 * from the submission path. | ||||
| 			 */ | ||||
| 			io_req_io_end(req); | ||||
| 			io_req_set_res(req, final_ret, | ||||
| 				       io_put_kbuf(req, issue_flags)); | ||||
| 			return IOU_OK; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jens Axboe
						Jens Axboe