Re: [PATCH] nilfs2: clear dirty flag on bdev buffers on log write failure

From: Viacheslav Dubeyko

Date: Tue Sep 29 2026 - 13:56:23 EST


On Tue, 2026-09-29 at 15:38 +0900, Ryusuke Konishi wrote:
> Since the commit referenced in the Fixes tag stopped directly calling
> inode_attach_wb(), a dirty flag is set on buffers (with
> mark_buffer_dirty()) allocated to the backing device for segment
> summaries and the super root block during log writes.
>
> While this dirty flag is cleared upon a successful log write, it
> remains
> uncleared if the log write fails.
>
> Consequently, when a log write fails, these backing device buffers
> are
> left in an inconsistent state where their uptodate flag and the dirty
> flag of the containing page/folio are cleared, but the buffer's dirty
> flag remains as stale garbage.
>
> Particularly when the block size is smaller than the page size, if
> other
> buffers on the same page/folio become dirty, this buffer unexpectedly
> becomes a target for writeback again.  As a result, if the block is
> later reused for other data or metadata, that contents risks being
> corrupted.
>
> Fix this issue by calling clear_buffer_dirty() for the backing device
> buffers when aborting log writes in nilfs_abort_logs().
>
> Fixes: 68142cb628f7 ("nilfs2: do not call inode_attach_wb()
> directly")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxx>
> ---
> Hi Viacheslav,
>
> Please apply this bug fix.
>
> This fixes an omitted clear of the dirty flag on backing device
> buffers,
> which could cause an abnormal buffer state and potential block
> overwriting data corruption.
>
> Thanks,
> Ryusuke Konishi
>
>  fs/nilfs2/segment.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
> index 829573cb6131..2f0e59847d02 100644
> --- a/fs/nilfs2/segment.c
> +++ b/fs/nilfs2/segment.c
> @@ -1829,6 +1829,7 @@ static void nilfs_abort_logs(struct list_head
> *logs, int err)
>   list_for_each_entry(segbuf, logs, sb_list) {
>   list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
>       b_assoc_buffers) {
> + clear_buffer_dirty(bh);
>   clear_buffer_uptodate(bh);
>   if (bh->b_folio != bd_folio) {
>   if (bd_folio)
> @@ -1840,6 +1841,7 @@ static void nilfs_abort_logs(struct list_head
> *logs, int err)
>   list_for_each_entry(bh, &segbuf->sb_payload_buffers,
>       b_assoc_buffers) {
>   if (bh == segbuf->sb_super_root) {
> + clear_buffer_dirty(bh);
>   clear_buffer_uptodate(bh);
>   if (bh->b_folio != bd_folio) {
>   folio_end_writeback(bd_folio
> );

Applied.

Thanks,
Slava.