Skip to content

Commit d139ded

Browse files
adam900710kdave
authored andcommitted
btrfs: qgroup: always free reserved space for extent records
[BUG] If qgroup is marked inconsistent (e.g. caused by operations needing full subtree rescan, like creating a snapshot and assign to a higher level qgroup), btrfs would immediately start leaking its data reserved space. The following script can easily reproduce it: mkfs.btrfs -O quota -f $dev mount $dev $mnt btrfs subvolume create $mnt/subv1 btrfs qgroup create 1/0 $mnt # This snapshot creation would mark qgroup inconsistent, # as the ownership involves different higher level qgroup, thus # we have to rescan both source and snapshot, which can be very # time consuming, thus here btrfs just choose to mark qgroup # inconsistent, and let users to determine when to do the rescan. btrfs subv snapshot -i 1/0 $mnt/subv1 $mnt/snap1 # Now this write would lead to qgroup rsv leak. xfs_io -f -c "pwrite 0 64k" $mnt/file1 # And at unmount time, btrfs would report 64K DATA rsv space leaked. umount $mnt And we would have the following dmesg output for the unmount: BTRFS info (device dm-1): last unmount of filesystem 14a3d84e-f47b-4f72-b053-a8a36eef74d3 BTRFS warning (device dm-1): qgroup 0/5 has unreleased space, type 0 rsv 65536 [CAUSE] Since commit e15e9f4 ("btrfs: introduce BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING to skip qgroup accounting"), we introduce a mode for btrfs qgroup to skip the timing consuming backref walk, if the qgroup is already inconsistent. But this skip also covered the data reserved freeing, thus the qgroup reserved space for each newly created data extent would not be freed, thus cause the leakage. [FIX] Make the data extent reserved space freeing mandatory. The qgroup reserved space handling is way cheaper compared to the backref walking part, and we always have the super sensitive leak detector, thus it's definitely worth to always free the qgroup reserved data space. Reported-by: Fabian Vogt <[email protected]> Fixes: e15e9f4 ("btrfs: introduce BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING to skip qgroup accounting") CC: [email protected] # 6.1+ Link: https://bugzilla.suse.com/show_bug.cgi?id=1216196 Reviewed-by: Filipe Manana <[email protected]> Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent dd6a571 commit d139ded

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

fs/btrfs/qgroup.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,11 +2957,6 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
29572957
ctx.roots = NULL;
29582958
}
29592959

2960-
/* Free the reserved data space */
2961-
btrfs_qgroup_free_refroot(fs_info,
2962-
record->data_rsv_refroot,
2963-
record->data_rsv,
2964-
BTRFS_QGROUP_RSV_DATA);
29652960
/*
29662961
* Use BTRFS_SEQ_LAST as time_seq to do special search,
29672962
* which doesn't lock tree or delayed_refs and search
@@ -2985,6 +2980,11 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
29852980
record->old_roots = NULL;
29862981
new_roots = NULL;
29872982
}
2983+
/* Free the reserved data space */
2984+
btrfs_qgroup_free_refroot(fs_info,
2985+
record->data_rsv_refroot,
2986+
record->data_rsv,
2987+
BTRFS_QGROUP_RSV_DATA);
29882988
cleanup:
29892989
ulist_free(record->old_roots);
29902990
ulist_free(new_roots);

0 commit comments

Comments
 (0)