]> Git Repo - J-linux.git/commitdiff
btrfs: fix leak of qgroup extent records after transaction abort
authorFilipe Manana <[email protected]>
Mon, 3 Jun 2024 11:49:08 +0000 (12:49 +0100)
committerDavid Sterba <[email protected]>
Wed, 5 Jun 2024 16:06:54 +0000 (18:06 +0200)
Qgroup extent records are created when delayed ref heads are created and
then released after accounting extents at btrfs_qgroup_account_extents(),
called during the transaction commit path.

If a transaction is aborted we free the qgroup records by calling
btrfs_qgroup_destroy_extent_records() at btrfs_destroy_delayed_refs(),
unless we don't have delayed references. We are incorrectly assuming
that no delayed references means we don't have qgroup extents records.

We can currently have no delayed references because we ran them all
during a transaction commit and the transaction was aborted after that
due to some error in the commit path.

So fix this by ensuring we btrfs_qgroup_destroy_extent_records() at
btrfs_destroy_delayed_refs() even if we don't have any delayed references.

Reported-by: [email protected]
Link: https://lore.kernel.org/linux-btrfs/[email protected]/
Fixes: 81f7eb00ff5b ("btrfs: destroy qgroup extent records on transaction abort")
CC: [email protected] # 6.1+
Reviewed-by: Josef Bacik <[email protected]>
Reviewed-by: Qu Wenruo <[email protected]>
Signed-off-by: Filipe Manana <[email protected]>
Signed-off-by: David Sterba <[email protected]>
fs/btrfs/disk-io.c

index a91a8056758a3286d3a99900a115be70a92a8a60..242ada7e47b405750106a52acbaf516444a189f8 100644 (file)
@@ -4538,18 +4538,10 @@ static void btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                                       struct btrfs_fs_info *fs_info)
 {
        struct rb_node *node;
-       struct btrfs_delayed_ref_root *delayed_refs;
+       struct btrfs_delayed_ref_root *delayed_refs = &trans->delayed_refs;
        struct btrfs_delayed_ref_node *ref;
 
-       delayed_refs = &trans->delayed_refs;
-
        spin_lock(&delayed_refs->lock);
-       if (atomic_read(&delayed_refs->num_entries) == 0) {
-               spin_unlock(&delayed_refs->lock);
-               btrfs_debug(fs_info, "delayed_refs has NO entry");
-               return;
-       }
-
        while ((node = rb_first_cached(&delayed_refs->href_root)) != NULL) {
                struct btrfs_delayed_ref_head *head;
                struct rb_node *n;
This page took 0.057208 seconds and 4 git commands to generate.