Commit 68d4b3fa authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: qgroup: update all parent qgroups when doing quick inherit



[BUG]
There is a bug that if a subvolume has multi-level parent qgroups, and
is able to do a quick inherit, only the direct parent qgroup got
updated:

  mkfs.btrfs  -f -O quota $dev
  mount $dev $mnt
  btrfs subv create $mnt/subv1
  btrfs qgroup create 1/100 $mnt
  btrfs qgroup create 2/100 $mnt
  btrfs qgroup assign 1/100 2/100 $mnt
  btrfs qgroup assign 0/256 1/100 $mnt
  btrfs qgroup show -p --sync $mnt

  Qgroupid    Referenced    Exclusive Parent     Path
  --------    ----------    --------- ------     ----
  0/5           16.00KiB     16.00KiB -          <toplevel>
  0/256         16.00KiB     16.00KiB 1/100      subv1
  1/100         16.00KiB     16.00KiB 2/100      2/100<1 member qgroup>
  2/100         16.00KiB     16.00KiB -          <0 member qgroups>

  btrfs subv snap -i 1/100 $mnt/subv1 $mnt/snap1
  btrfs qgroup show -p --sync $mnt

  Qgroupid    Referenced    Exclusive Parent     Path
  --------    ----------    --------- ------     ----
  0/5           16.00KiB     16.00KiB -          <toplevel>
  0/256         16.00KiB     16.00KiB 1/100      subv1
  0/257         16.00KiB     16.00KiB 1/100      snap1
  1/100         32.00KiB     32.00KiB 2/100      2/100<1 member qgroup>
  2/100         16.00KiB     16.00KiB -          <0 member qgroups>
  # Note that 2/100 is not updated, and qgroup numbers are inconsistent

  umount $mnt

[CAUSE]
If the snapshot source subvolume belongs to a parent qgroup, and the new
snapshot target is also added to the new same parent qgroup, we allow a
quick update without marking qgroup inconsistent.

But that quick update only update the parent qgroup, without checking if
there is any more parent qgroups.

[FIX]
Iterate through all parent qgroups during the quick inherit.

Reported-by: default avatarBoris Burkov <boris@bur.io>
Fixes: b20fe56c ("btrfs: qgroup: allow quick inherit if snapshot is created and added to the same parent")
Reviewed-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7ee19a59
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -3208,7 +3208,10 @@ static int qgroup_snapshot_quick_inherit(struct btrfs_fs_info *fs_info,
{
	struct btrfs_qgroup *src;
	struct btrfs_qgroup *parent;
	struct btrfs_qgroup *qgroup;
	struct btrfs_qgroup_list *list;
	LIST_HEAD(qgroup_list);
	const u32 nodesize = fs_info->nodesize;
	int nr_parents = 0;

	if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_FULL)
@@ -3248,8 +3251,19 @@ static int qgroup_snapshot_quick_inherit(struct btrfs_fs_info *fs_info,
	if (parent->excl != parent->rfer)
		return 1;

	parent->excl += fs_info->nodesize;
	parent->rfer += fs_info->nodesize;
	qgroup_iterator_add(&qgroup_list, parent);
	list_for_each_entry(qgroup, &qgroup_list, iterator) {
		qgroup->rfer += nodesize;
		qgroup->rfer_cmpr += nodesize;
		qgroup->excl += nodesize;
		qgroup->excl_cmpr += nodesize;
		qgroup_dirty(fs_info, qgroup);

		/* Append parent qgroups to @qgroup_list. */
		list_for_each_entry(list, &qgroup->groups, next_group)
			qgroup_iterator_add(&qgroup_list, list->group);
	}
	qgroup_iterator_clean(&qgroup_list);
	return 0;
}