• Qu Wenruo's avatar
    btrfs: qgroup: Dirty all qgroups before rescan · 08374d8b
    Qu Wenruo authored
    commit 9c7b0c2e upstream.
    
    [BUG]
    In the following case, rescan won't zero out the number of qgroup 1/0:
    
      $ mkfs.btrfs -fq $DEV
      $ mount $DEV /mnt
    
      $ btrfs quota enable /mnt
      $ btrfs qgroup create 1/0 /mnt
      $ btrfs sub create /mnt/sub
      $ btrfs qgroup assign 0/257 1/0 /mnt
    
      $ dd if=/dev/urandom of=/mnt/sub/file bs=1k count=1000
      $ btrfs sub snap /mnt/sub /mnt/snap
      $ btrfs quota rescan -w /mnt
      $ btrfs qgroup show -pcre /mnt
      qgroupid         rfer         excl     max_rfer     max_excl parent  child
      --------         ----         ----     --------     -------- ------  -----
      0/5          16.00KiB     16.00KiB         none         none ---     ---
      0/257      1016.00KiB     16.00KiB         none         none 1/0     ---
      0/258      1016.00KiB     16.00KiB         none         none ---     ---
      1/0        1016.00KiB     16.00KiB         none         none ---     0/257
    
    So far so good, but:
    
      $ btrfs qgroup remove 0/257 1/0 /mnt
      WARNING: quotas may be inconsistent, rescan needed
      $ btrfs quota rescan -w /mnt
      $ btrfs qgroup show -pcre  /mnt
      qgoupid         rfer         excl     max_rfer     max_excl parent  child
      --------         ----         ----     --------     -------- ------  -----
      0/5          16.00KiB     16.00KiB         none         none ---     ---
      0/257      1016.00KiB     16.00KiB         none         none ---     ---
      0/258      1016.00KiB     16.00KiB         none         none ---     ---
      1/0        1016.00KiB     16.00KiB         none         none ---     ---
    	     ^^^^^^^^^^     ^^^^^^^^ not cleared
    
    [CAUSE]
    Before rescan we call qgroup_rescan_zero_tracking() to zero out all
    qgroups' accounting numbers.
    
    However we don't mark all qgroups dirty, but rely on rescan to do so.
    
    If we have any high level qgroup without children, it won't be marked
    dirty during rescan, since we cannot reach that qgroup.
    
    This will cause QGROUP_INFO items of childless qgroups never get updated
    in the quota tree, thus their numbers will stay the same in "btrfs
    qgroup show" output.
    
    [FIX]
    Just mark all qgroups dirty in qgroup_rescan_zero_tracking(), so even if
    we have childless qgroups, their QGROUP_INFO items will still get
    updated during rescan.
    Reported-by: default avatarMisono Tomohiro <misono.tomohiro@jp.fujitsu.com>
    CC: stable@vger.kernel.org # 4.4+
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Reviewed-by: default avatarMisono Tomohiro <misono.tomohiro@jp.fujitsu.com>
    Tested-by: default avatarMisono Tomohiro <misono.tomohiro@jp.fujitsu.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    08374d8b
qgroup.c 77.9 KB