mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +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) | static bool __io_complete_rw_common(struct io_kiocb *req, long res) | ||||||
| { | { | ||||||
| 	if (unlikely(res != req->cqe.res)) { | 	if (unlikely(res != req->cqe.res)) { | ||||||
| 		if ((res == -EAGAIN || res == -EOPNOTSUPP) && | 		if ((res == -EAGAIN || res == -EOPNOTSUPP) && | ||||||
| 		    io_rw_should_reissue(req)) { | 		    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; | 			req->flags |= REQ_F_REISSUE | REQ_F_PARTIAL_IO; | ||||||
| 			return true; | 			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) | static void io_req_rw_complete(struct io_kiocb *req, bool *locked) | ||||||
| { | { | ||||||
| 	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw); | 	io_req_io_end(req); | ||||||
| 
 |  | ||||||
| 	if (rw->kiocb.ki_flags & IOCB_WRITE) { |  | ||||||
| 		kiocb_end_write(req); |  | ||||||
| 		fsnotify_modify(req->file); |  | ||||||
| 	} else { |  | ||||||
| 		fsnotify_access(req->file); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	io_req_task_complete(req, locked); | 	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; | 		req->file->f_pos = rw->kiocb.ki_pos; | ||||||
| 	if (ret >= 0 && (rw->kiocb.ki_complete == io_complete_rw)) { | 	if (ret >= 0 && (rw->kiocb.ki_complete == io_complete_rw)) { | ||||||
| 		if (!__io_complete_rw_common(req, ret)) { | 		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_req_set_res(req, final_ret, | ||||||
| 				       io_put_kbuf(req, issue_flags)); | 				       io_put_kbuf(req, issue_flags)); | ||||||
| 			return IOU_OK; | 			return IOU_OK; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jens Axboe
						Jens Axboe