Skip to content

Commit bb2c2e6

Browse files
adam900710gregkh
authored andcommitted
btrfs: qgroup: do not warn on record without old_roots populated
commit 7518140 upstream. [BUG] There are some reports from the mailing list that since v6.1 kernel, the WARN_ON() inside btrfs_qgroup_account_extent() gets triggered during rescan: WARNING: CPU: 3 PID: 6424 at fs/btrfs/qgroup.c:2756 btrfs_qgroup_account_extents+0x1ae/0x260 [btrfs] CPU: 3 PID: 6424 Comm: snapperd Tainted: P OE 6.1.2-1-default Freescale#1 openSUSE Tumbleweed 05c7a1b1b61d5627475528f71f50444637b5aad7 RIP: 0010:btrfs_qgroup_account_extents+0x1ae/0x260 [btrfs] Call Trace: <TASK> btrfs_commit_transaction+0x30c/0xb40 [btrfs c39c9c546c241c593f03bd6d5f39ea1b676250f6] ? start_transaction+0xc3/0x5b0 [btrfs c39c9c546c241c593f03bd6d5f39ea1b676250f6] btrfs_qgroup_rescan+0x42/0xc0 [btrfs c39c9c546c241c593f03bd6d5f39ea1b676250f6] btrfs_ioctl+0x1ab9/0x25c0 [btrfs c39c9c546c241c593f03bd6d5f39ea1b676250f6] ? __rseq_handle_notify_resume+0xa9/0x4a0 ? mntput_no_expire+0x4a/0x240 ? __seccomp_filter+0x319/0x4d0 __x64_sys_ioctl+0x90/0xd0 do_syscall_64+0x5b/0x80 ? syscall_exit_to_user_mode+0x17/0x40 ? do_syscall_64+0x67/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7fd9b790d9bf </TASK> [CAUSE] Since commit e15e9f4 ("btrfs: introduce BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING to skip qgroup accounting"), if our qgroup is already in inconsistent state, we will no longer do the time-consuming backref walk. This can leave some qgroup records without a valid old_roots ulist. Normally this is fine, as btrfs_qgroup_account_extents() would also skip those records if we have NO_ACCOUNTING flag set. But there is a small window, if we have NO_ACCOUNTING flag set, and inserted some qgroup_record without a old_roots ulist, but then the user triggered a qgroup rescan. During btrfs_qgroup_rescan(), we firstly clear NO_ACCOUNTING flag, then commit current transaction. And since we have a qgroup_record with old_roots = NULL, we trigger the WARN_ON() during btrfs_qgroup_account_extents(). [FIX] Unfortunately due to the introduction of NO_ACCOUNTING flag, the assumption that every qgroup_record would have its old_roots populated is no longer correct. Fix the false alerts and drop the WARN_ON(). Reported-by: Lukas Straub <[email protected]> Reported-by: HanatoK <[email protected]> Fixes: e15e9f4 ("btrfs: introduce BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING to skip qgroup accounting") CC: [email protected] # 6.1 Link: https://lore.kernel.org/linux-btrfs/[email protected]/ Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 34fe5b5 commit bb2c2e6

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

fs/btrfs/qgroup.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -2751,9 +2751,19 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
27512751
BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING)) {
27522752
/*
27532753
* Old roots should be searched when inserting qgroup
2754-
* extent record
2754+
* extent record.
2755+
*
2756+
* But for INCONSISTENT (NO_ACCOUNTING) -> rescan case,
2757+
* we may have some record inserted during
2758+
* NO_ACCOUNTING (thus no old_roots populated), but
2759+
* later we start rescan, which clears NO_ACCOUNTING,
2760+
* leaving some inserted records without old_roots
2761+
* populated.
2762+
*
2763+
* Those cases are rare and should not cause too much
2764+
* time spent during commit_transaction().
27552765
*/
2756-
if (WARN_ON(!record->old_roots)) {
2766+
if (!record->old_roots) {
27572767
/* Search commit root to find old_roots */
27582768
ret = btrfs_find_all_roots(NULL, fs_info,
27592769
record->bytenr, 0,

0 commit comments

Comments
 (0)