• Qu Wenruo's avatar
    btrfs: qgroup: do not warn on record without old_roots populated · 75181406
    Qu Wenruo authored
    [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 #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 e15e9f43 ("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: default avatarLukas Straub <lukasstraub2@web.de>
    Reported-by: default avatarHanatoK <summersnow9403@gmail.com>
    Fixes: e15e9f43 ("btrfs: introduce BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING to skip qgroup accounting")
    CC: stable@vger.kernel.org # 6.1
    Link: https://lore.kernel.org/linux-btrfs/2403c697-ddaf-58ad-3829-0335fc89df09@gmail.com/Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    75181406
qgroup.c 115 KB