• Qu Wenruo's avatar
    btrfs: qgroup: Fix qgroup accounting when creating snapshot · 6426c7ad
    Qu Wenruo authored
    
    
    Current btrfs qgroup design implies a requirement that after calling
    btrfs_qgroup_account_extents() there must be a commit root switch.
    
    Normally this is OK, as btrfs_qgroup_accounting_extents() is only called
    inside btrfs_commit_transaction() just be commit_cowonly_roots().
    
    However there is a exception at create_pending_snapshot(), which will
    call btrfs_qgroup_account_extents() but no any commit root switch.
    
    In case of creating a snapshot whose parent root is itself (create a
    snapshot of fs tree), it will corrupt qgroup by the following trace:
    (skipped unrelated data)
    ======
    btrfs_qgroup_account_extent: bytenr = 29786112, num_bytes = 16384, nr_old_roots = 0, nr_new_roots = 1
    qgroup_update_counters: qgid = 5, cur_old_count = 0, cur_new_count = 1, rfer = 0, excl = 0
    qgroup_update_counters: qgid = 5, cur_old_count = 0, cur_new_count = 1, rfer = 16384, excl = 16384
    btrfs_qgroup_account_extent: bytenr = 29786112, num_bytes = 16384, nr_old_roots = 0, nr_new_roots = 0
    ======
    
    The problem here is in first qgroup_account_extent(), the
    nr_new_roots of the extent is 1, which means its reference got
    increased, and qgroup increased its rfer and excl.
    
    But at second qgroup_account_extent(), its reference got decreased, but
    between these two qgroup_account_extent(), there is no switch roots.
    This leads to the same nr_old_roots, and this extent just got ignored by
    qgroup, which means this extent is wrongly accounted.
    
    Fix it by call commit_cowonly_roots() after qgroup_account_extent() in
    create_pending_snapshot(), with needed preparation.
    
    Mark: I added a check at the top of qgroup_account_snapshot() to skip this
    code if qgroups are turned off. xfstest btrfs/122 exposes this problem.
    Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
    Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
    Signed-off-by: default avatarMark Fasheh <mfasheh@suse.de>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    6426c7ad