]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
btrfs: fix squota accounting during enable generation
authorBoris Burkov <boris@bur.io>
Tue, 12 May 2026 02:53:46 +0000 (19:53 -0700)
committerDavid Sterba <dsterba@suse.com>
Sat, 16 May 2026 01:07:19 +0000 (03:07 +0200)
commitd7c600554816b8ef70adffe078a0e360c055d82b
tree84090b39c4f1809a33c291ac9c8210c82943109d
parent1e92637722ae4bd417f7a37e8d1485dc23b93935
btrfs: fix squota accounting during enable generation

The first transaction that enables squotas is special and a bit tricky.
We have to set BTRFS_FS_QUOTA_ENABLED after the transaction to avoid a
deadlock, so any delayed refs that run before we set the bit are not
squota accounted. For data this is fine, we don't get an owner_ref, so
there is no real harm, it's as if the extent predated squotas. However
for metadata, the tree block will have gen == enable_gen so when we free
it later, we will decrement the squota accounting, which can result in
an underflow. Before it is freed, btrfs check shows errors, as we have
mismatched usage between the node generations/owners and the squota
values.

There are two angles to this fix:

1. For extents that come in delayed_refs that run during the
   enable_gen transaction, we must actually set enable_gen to the *next*
   transaction. That is the first transaction that we can really
   properly account in any way.
2. For extents that come in between the end of our transaction handle
   and the time we set the BTRFS_FS_QUOTA_ENABLED bit, we need an
   additional bit, BTRFS_FS_SQUOTA_ENABLING which only affects recording
   squota deltas, so we do pick up those extents. Otherwise, we would
   miss them, even for enable_gen + 1.

Fixes: bd7c1ea3a302 ("btrfs: qgroup: check generation when recording simple quota delta")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/fs.h
fs/btrfs/qgroup.c