Skip to content

Commit b20fe56

Browse files
adam900710kdave
authored andcommitted
btrfs: qgroup: allow quick inherit if snapshot is created and added to the same parent
Currently "btrfs subvolume snapshot -i <qgroupid>" would always mark the qgroup inconsistent. This can be annoying if the fs has a lot of snapshots, and needs qgroup to get the accounting for the amount of bytes it can free for each snapshot. Although we have the new simple quote as a solution, there is also a case where we can skip the full scan, if all the following conditions are met: - The source subvolume belongs to a higher level parent qgroup - The parent qgroup already owns all its bytes exclusively - The new snapshot is also added to the same parent qgroup In that case, we only need to add nodesize to the parent qgroup and avoid a full rescan. This patch would add the extra quick accounting update for such inherit. Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 86211ee commit b20fe56

File tree

1 file changed

+72
-7
lines changed

1 file changed

+72
-7
lines changed

fs/btrfs/qgroup.c

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3138,6 +3138,62 @@ static int qgroup_auto_inherit(struct btrfs_fs_info *fs_info,
31383138
return 0;
31393139
}
31403140

3141+
/*
3142+
* Check if we can skip rescan when inheriting qgroups. If @src has a single
3143+
* @parent, and that @parent is owning all its bytes exclusively, we can skip
3144+
* the full rescan, by just adding nodesize to the @parent's excl/rfer.
3145+
*
3146+
* Return <0 for fatal errors (like srcid/parentid has no qgroup).
3147+
* Return 0 if a quick inherit is done.
3148+
* Return >0 if a quick inherit is not possible, and a full rescan is needed.
3149+
*/
3150+
static int qgroup_snapshot_quick_inherit(struct btrfs_fs_info *fs_info,
3151+
u64 srcid, u64 parentid)
3152+
{
3153+
struct btrfs_qgroup *src;
3154+
struct btrfs_qgroup *parent;
3155+
struct btrfs_qgroup_list *list;
3156+
int nr_parents = 0;
3157+
3158+
src = find_qgroup_rb(fs_info, srcid);
3159+
if (!src)
3160+
return -ENOENT;
3161+
parent = find_qgroup_rb(fs_info, parentid);
3162+
if (!parent)
3163+
return -ENOENT;
3164+
3165+
/*
3166+
* Source has no parent qgroup, but our new qgroup would have one.
3167+
* Qgroup numbers would become inconsistent.
3168+
*/
3169+
if (list_empty(&src->groups))
3170+
return 1;
3171+
3172+
list_for_each_entry(list, &src->groups, next_group) {
3173+
/* The parent is not the same, quick update is not possible. */
3174+
if (list->group->qgroupid != parentid)
3175+
return 1;
3176+
nr_parents++;
3177+
/*
3178+
* More than one parent qgroup, we can't be sure about accounting
3179+
* consistency.
3180+
*/
3181+
if (nr_parents > 1)
3182+
return 1;
3183+
}
3184+
3185+
/*
3186+
* The parent is not exclusively owning all its bytes. We're not sure
3187+
* if the source has any bytes not fully owned by the parent.
3188+
*/
3189+
if (parent->excl != parent->rfer)
3190+
return 1;
3191+
3192+
parent->excl += fs_info->nodesize;
3193+
parent->rfer += fs_info->nodesize;
3194+
return 0;
3195+
}
3196+
31413197
/*
31423198
* Copy the accounting information between qgroups. This is necessary
31433199
* when a snapshot or a subvolume is created. Throwing an error will
@@ -3306,6 +3362,13 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
33063362

33073363
qgroup_dirty(fs_info, dstgroup);
33083364
qgroup_dirty(fs_info, srcgroup);
3365+
3366+
/*
3367+
* If the source qgroup has parent but the new one doesn't,
3368+
* we need a full rescan.
3369+
*/
3370+
if (!inherit && !list_empty(&srcgroup->groups))
3371+
need_rescan = true;
33093372
}
33103373

33113374
if (!inherit)
@@ -3320,14 +3383,16 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
33203383
if (ret)
33213384
goto unlock;
33223385
}
3386+
if (srcid) {
3387+
/* Check if we can do a quick inherit. */
3388+
ret = qgroup_snapshot_quick_inherit(fs_info, srcid, *i_qgroups);
3389+
if (ret < 0)
3390+
goto unlock;
3391+
if (ret > 0)
3392+
need_rescan = true;
3393+
ret = 0;
3394+
}
33233395
++i_qgroups;
3324-
3325-
/*
3326-
* If we're doing a snapshot, and adding the snapshot to a new
3327-
* qgroup, the numbers are guaranteed to be incorrect.
3328-
*/
3329-
if (srcid)
3330-
need_rescan = true;
33313396
}
33323397

33333398
for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) {

0 commit comments

Comments
 (0)