Re: [PATCH 12/19] ext4: check for a metadata write error with buffer_write_io_error()
Jan Kara <[email protected]> Tue, 4 Aug 2026 10:41:40 +0200
| Newsgroups | dev.linux.lists.gfs2,dev.linux.lists.ocfs2-devel,org.kernel.vger.linux-ext4,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <qyfwaoic3qwf6275cp7pvoqlxl6ntxpao23pbaybaqkoi7btjy@drlqk7hxcjsy> |
On Sat 01-08-26 18:00:56, Chao Shi wrote: > Two places detect a failed metadata write by testing !buffer_uptodate() > after waiting for it. That relies on the write completion handler clearing > BH_Uptodate on error, which this series removes: a buffer whose write > failed still holds the data the filesystem asked to be written, so > declaring it not up to date is wrong and makes callers re-read it. > > ext4 already does this correctly for the superblock - see > ext4_commit_super(), which tests buffer_write_io_error() - so this brings > the other two into line. > > In __ext4_handle_dirty_metadata() the old test also required BH_Req. > BH_Write_EIO implies it, so the pair collapses into one test. The new test > is also strictly stronger than consuming sync_dirty_buffer()'s return > value, because it still fires when the buffer was written by background > writeback and that write hit an error, which sync_dirty_buffer() does not > report. > > Note that BH_Write_EIO stays set until the buffer is written again, > forgotten or invalidated, so an unrepaired itable block now reports on > every subsequent sync of that inode rather than only on the write that > failed. That is the intended behaviour and matches what ocfs2 has always > done with this flag. > > No behaviour change today - a failed write sets BH_Write_EIO and clears > BH_Uptodate together. It stops being a no-op at the end of the series, > where the new test is the one that still works. > > Signed-off-by: Chao Shi <[email protected]> Looks good. Feel free to add: Reviewed-by: Jan Kara <[email protected]> Honza > --- > fs/ext4/ext4_jbd2.c | 2 +- > fs/ext4/mmp.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c > index 02b066299164..f338d6e3c29f 100644 > --- a/fs/ext4/ext4_jbd2.c > +++ b/fs/ext4/ext4_jbd2.c > @@ -413,7 +413,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, > } > if (inode && inode_needs_sync(inode)) { > sync_dirty_buffer(bh); > - if (buffer_req(bh) && !buffer_uptodate(bh)) { > + if (buffer_write_io_error(bh)) { > ext4_error_inode_err(inode, where, line, > bh->b_blocknr, EIO, > "IO error syncing itable block"); > diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c > index 7ce361484b38..4b18ddef468d 100644 > --- a/fs/ext4/mmp.c > +++ b/fs/ext4/mmp.c > @@ -49,7 +49,7 @@ static int write_mmp_block_thawed(struct super_block *sb, > bh_submit(bh, REQ_OP_WRITE | REQ_SYNC | REQ_META | REQ_PRIO, > bh_end_write); > wait_on_buffer(bh); > - if (unlikely(!buffer_uptodate(bh))) > + if (unlikely(buffer_write_io_error(bh))) > return -EIO; > return 0; > } > -- > 2.43.0 > -- Jan Kara <[email protected]> SUSE Labs, CR