On Tue 08-07-25 19:15:04, libaokun@xxxxxxxxxxxxxxx wrote: > From: Baokun Li <libaokun1@xxxxxxxxxx> > > In ext4_io_end_defer_completion(), check if io_end->list_vec is empty to > avoid adding an io_end that requires no conversion to the > i_rsv_conversion_list, which in turn prevents starting an unnecessary > worker. An ext4_emergency_state() check is also added to avoid attempting > to abort the journal in an emergency state. > > Additionally, ext4_put_io_end_defer() is refactored to call > ext4_io_end_defer_completion() directly instead of being open-coded. > This also prevents starting an unnecessary worker when EXT4_IO_END_FAILED > is set but data_err=abort is not enabled. > > This ensures that the check in ext4_put_io_end_defer() is consistent with > the check in ext4_end_bio(). Otherwise, we might add an io_end to the > i_rsv_conversion_list and then call ext4_finish_bio(), after which the > inode could be freed before ext4_end_io_rsv_work() is called, triggering > a use-after-free issue. > > Fixes: ce51afb8cc5e ("ext4: abort journal on data writeback failure if in data_err=abort mode") > Signed-off-by: Baokun Li <libaokun1@xxxxxxxxxx> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@xxxxxxx> Honza > --- > fs/ext4/page-io.c | 16 ++++++++-------- > 1 file changed, 8 insertions(+), 8 deletions(-) > > diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c > index 179e54f3a3b6..3d8b0f6d2dea 100644 > --- a/fs/ext4/page-io.c > +++ b/fs/ext4/page-io.c > @@ -236,10 +236,12 @@ static void dump_completed_IO(struct inode *inode, struct list_head *head) > > static bool ext4_io_end_defer_completion(ext4_io_end_t *io_end) > { > - if (io_end->flag & EXT4_IO_END_UNWRITTEN) > + if (io_end->flag & EXT4_IO_END_UNWRITTEN && > + !list_empty(&io_end->list_vec)) > return true; > if (test_opt(io_end->inode->i_sb, DATA_ERR_ABORT) && > - io_end->flag & EXT4_IO_END_FAILED) > + io_end->flag & EXT4_IO_END_FAILED && > + !ext4_emergency_state(io_end->inode->i_sb)) > return true; > return false; > } > @@ -256,6 +258,7 @@ static void ext4_add_complete_io(ext4_io_end_t *io_end) > WARN_ON(!(io_end->flag & EXT4_IO_END_DEFER_COMPLETION)); > WARN_ON(io_end->flag & EXT4_IO_END_UNWRITTEN && > !io_end->handle && sbi->s_journal); > + WARN_ON(!io_end->bio); > > spin_lock_irqsave(&ei->i_completed_io_lock, flags); > wq = sbi->rsv_conversion_wq; > @@ -318,12 +321,9 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) > void ext4_put_io_end_defer(ext4_io_end_t *io_end) > { > if (refcount_dec_and_test(&io_end->count)) { > - if (io_end->flag & EXT4_IO_END_FAILED || > - (io_end->flag & EXT4_IO_END_UNWRITTEN && > - !list_empty(&io_end->list_vec))) { > - ext4_add_complete_io(io_end); > - return; > - } > + if (ext4_io_end_defer_completion(io_end)) > + return ext4_add_complete_io(io_end); > + > ext4_release_io_end(io_end); > } > } > -- > 2.46.1 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR