All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Foster <bfoster@redhat.com>
To: Baokun Li <libaokun1@huawei.com>
Cc: linux-ext4@vger.kernel.org
Subject: Re: [PATCH v2] ext4: fix dirtyclusters double decrement on fs shutdown
Date: Tue, 13 Jan 2026 10:11:05 -0500	[thread overview]
Message-ID: <aWZgiRHn2EEdh_Qq@bfoster> (raw)
In-Reply-To: <94ccc367-f631-40fe-a99e-635d1eb0a3dd@huawei.com>

On Tue, Jan 13, 2026 at 09:44:16AM +0800, Baokun Li wrote:
> On 2026-01-12 22:36, Brian Foster wrote:
> > fstests test generic/388 occasionally reproduces a warning in
> > ext4_put_super() associated with the dirty clusters count:
> >
> >   WARNING: CPU: 7 PID: 76064 at fs/ext4/super.c:1324 ext4_put_super+0x48c/0x590 [ext4]
> >
> > Tracing the failure shows that the warning fires due to an
> > s_dirtyclusters_counter value of -1. IOW, this appears to be a
> > spurious decrement as opposed to some sort of leak. Further tracing
> > of the dirty cluster count deltas and an LLM scan of the resulting
> > output identified the cause as a double decrement in the error path
> > between ext4_mb_mark_diskspace_used() and the caller
> > ext4_mb_new_blocks().
> >
> > First, note that generic/388 is a shutdown vs. fsstress test and so
> > produces a random set of operations and shutdown injections. In the
> > problematic case, the shutdown triggers an error return from the
> > ext4_handle_dirty_metadata() call(s) made from
> > ext4_mb_mark_context(). The changed value is non-zero at this point,
> > so ext4_mb_mark_diskspace_used() does not exit after the error
> > bubbles up from ext4_mb_mark_context(). Instead, the former
> > decrements both cluster counters and returns the error up to
> > ext4_mb_new_blocks(). The latter falls into the !ar->len out path
> > which decrements the dirty clusters counter a second time, creating
> > the inconsistency.
> >
> > To avoid this problem and simplify ownership of the cluster
> > reservation in this codepath, lift the counter reduction to a single
> > place in the caller. This makes it more clear that
> > ext4_mb_new_blocks() is responsible for acquiring cluster
> > reservation (via ext4_claim_free_clusters()) in the !delalloc case
> > as well as releasing it, regardless of whether it ends up consumed
> > or returned due to failure.
> >
> > Fixes: 0087d9fb3f29 ("ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc")
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> 
> Thanks for the patch.
> 
> However, the call site in test_mark_diskspace_used_range() missed the
> argument update, which triggered a Kernel Test Robot warning. Also,
> I have one nit below.

Ugh yeah, I guess I didn't have KUNIT enabled so I missed that one. Will
fix.

> 
> > ---
> >
> > v2:
> > - Condense counter update logic instead of modifying return flow.
> > - Added Fixes: tag.
> > v1: https://lore.kernel.org/linux-ext4/20251212154735.512651-1-bfoster@redhat.com/
> >
> >  fs/ext4/mballoc.c | 21 +++++----------------
> >  1 file changed, 5 insertions(+), 16 deletions(-)
> >
> > diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> > index 56d50fd3310b..b31d7ddc52a9 100644
> > --- a/fs/ext4/mballoc.c
> > +++ b/fs/ext4/mballoc.c
> > @@ -4185,8 +4185,7 @@ ext4_mb_mark_context(handle_t *handle, struct super_block *sb, bool state,
> >   * Returns 0 if success or error code
> >   */
> >  static noinline_for_stack int
> > -ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
> > -				handle_t *handle, unsigned int reserv_clstrs)
> > +ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, handle_t *handle)
> >  {
> >  	struct ext4_group_desc *gdp;
> >  	struct ext4_sb_info *sbi;
> > @@ -4241,13 +4240,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
> >  	BUG_ON(changed != ac->ac_b_ex.fe_len);
> >  #endif
> >  	percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
> > -	/*
> > -	 * Now reduce the dirty block count also. Should not go negative
> > -	 */
> > -	if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
> > -		/* release all the reserved blocks if non delalloc */
> > -		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
> > -				   reserv_clstrs);
> >  
> >  	return err;
> >  }
> > @@ -6332,7 +6324,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
> >  			ext4_mb_pa_put_free(ac);
> >  	}
> >  	if (likely(ac->ac_status == AC_STATUS_FOUND)) {
> > -		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs);
> > +		*errp = ext4_mb_mark_diskspace_used(ac, handle);
> >  		if (*errp) {
> >  			ext4_discard_allocated_blocks(ac);
> >  			goto errout;
> > @@ -6363,12 +6355,9 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
> >  out:
> >  	if (inquota && ar->len < inquota)
> >  		dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
> > -	if (!ar->len) {
> > -		if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
> > -			/* release all the reserved blocks if non delalloc */
> > -			percpu_counter_sub(&sbi->s_dirtyclusters_counter,
> > -						reserv_clstrs);
> > -	}
> > +	/* release all the reserved blocks if non delalloc */
> > +	if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
> 
> Nit: It might be better to check if (reserv_clstrs) directly. It’s more
> straightforward and stays robust even if the flag logic changes later.

Sure.

Brian

> 
> > +		percpu_counter_sub(&sbi->s_dirtyclusters_counter, reserv_clstrs);
> >  
> >  	trace_ext4_allocate_blocks(ar, (unsigned long long)block);
> >  
> 
> 


      reply	other threads:[~2026-01-13 15:11 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-12 14:36 [PATCH v2] ext4: fix dirtyclusters double decrement on fs shutdown Brian Foster
2026-01-12 21:43 ` kernel test robot
2026-01-12 22:28 ` kernel test robot
2026-01-13  1:44 ` Baokun Li
2026-01-13 15:11   ` Brian Foster [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aWZgiRHn2EEdh_Qq@bfoster \
    --to=bfoster@redhat.com \
    --cc=libaokun1@huawei.com \
    --cc=linux-ext4@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.