|
@@ -1076,21 +1076,30 @@ static void report_reserved_underflow(struct btrfs_fs_info *fs_info,
|
|
#endif
|
|
#endif
|
|
qgroup->reserved = 0;
|
|
qgroup->reserved = 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
- * The easy accounting, if we are adding/removing the only ref for an extent
|
|
|
|
- * then this qgroup and all of the parent qgroups get their reference and
|
|
|
|
- * exclusive counts adjusted.
|
|
|
|
|
|
+ * The easy accounting, we're updating qgroup relationship whose child qgroup
|
|
|
|
+ * only has exclusive extents.
|
|
|
|
+ *
|
|
|
|
+ * In this case, all exclsuive extents will also be exlusive for parent, so
|
|
|
|
+ * excl/rfer just get added/removed.
|
|
|
|
+ *
|
|
|
|
+ * So is qgroup reservation space, which should also be added/removed to
|
|
|
|
+ * parent.
|
|
|
|
+ * Or when child tries to release reservation space, parent will underflow its
|
|
|
|
+ * reservation (for relationship adding case).
|
|
*
|
|
*
|
|
* Caller should hold fs_info->qgroup_lock.
|
|
* Caller should hold fs_info->qgroup_lock.
|
|
*/
|
|
*/
|
|
static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
|
|
static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
|
|
struct ulist *tmp, u64 ref_root,
|
|
struct ulist *tmp, u64 ref_root,
|
|
- u64 num_bytes, int sign)
|
|
|
|
|
|
+ struct btrfs_qgroup *src, int sign)
|
|
{
|
|
{
|
|
struct btrfs_qgroup *qgroup;
|
|
struct btrfs_qgroup *qgroup;
|
|
struct btrfs_qgroup_list *glist;
|
|
struct btrfs_qgroup_list *glist;
|
|
struct ulist_node *unode;
|
|
struct ulist_node *unode;
|
|
struct ulist_iterator uiter;
|
|
struct ulist_iterator uiter;
|
|
|
|
+ u64 num_bytes = src->excl;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
qgroup = find_qgroup_rb(fs_info, ref_root);
|
|
qgroup = find_qgroup_rb(fs_info, ref_root);
|
|
@@ -1103,13 +1112,11 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
|
|
WARN_ON(sign < 0 && qgroup->excl < num_bytes);
|
|
WARN_ON(sign < 0 && qgroup->excl < num_bytes);
|
|
qgroup->excl += sign * num_bytes;
|
|
qgroup->excl += sign * num_bytes;
|
|
qgroup->excl_cmpr += sign * num_bytes;
|
|
qgroup->excl_cmpr += sign * num_bytes;
|
|
- if (sign > 0) {
|
|
|
|
- trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes);
|
|
|
|
- if (qgroup->reserved < num_bytes)
|
|
|
|
- report_reserved_underflow(fs_info, qgroup, num_bytes);
|
|
|
|
- else
|
|
|
|
- qgroup->reserved -= num_bytes;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ if (sign > 0)
|
|
|
|
+ qgroup_rsv_add_by_qgroup(qgroup, src);
|
|
|
|
+ else
|
|
|
|
+ qgroup_rsv_release_by_qgroup(qgroup, src);
|
|
|
|
|
|
qgroup_dirty(fs_info, qgroup);
|
|
qgroup_dirty(fs_info, qgroup);
|
|
|
|
|
|
@@ -1129,15 +1136,10 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
|
|
qgroup->rfer_cmpr += sign * num_bytes;
|
|
qgroup->rfer_cmpr += sign * num_bytes;
|
|
WARN_ON(sign < 0 && qgroup->excl < num_bytes);
|
|
WARN_ON(sign < 0 && qgroup->excl < num_bytes);
|
|
qgroup->excl += sign * num_bytes;
|
|
qgroup->excl += sign * num_bytes;
|
|
- if (sign > 0) {
|
|
|
|
- trace_qgroup_update_reserve(fs_info, qgroup,
|
|
|
|
- -(s64)num_bytes);
|
|
|
|
- if (qgroup->reserved < num_bytes)
|
|
|
|
- report_reserved_underflow(fs_info, qgroup,
|
|
|
|
- num_bytes);
|
|
|
|
- else
|
|
|
|
- qgroup->reserved -= num_bytes;
|
|
|
|
- }
|
|
|
|
|
|
+ if (sign > 0)
|
|
|
|
+ qgroup_rsv_add_by_qgroup(qgroup, src);
|
|
|
|
+ else
|
|
|
|
+ qgroup_rsv_release_by_qgroup(qgroup, src);
|
|
qgroup->excl_cmpr += sign * num_bytes;
|
|
qgroup->excl_cmpr += sign * num_bytes;
|
|
qgroup_dirty(fs_info, qgroup);
|
|
qgroup_dirty(fs_info, qgroup);
|
|
|
|
|
|
@@ -1180,7 +1182,7 @@ static int quick_update_accounting(struct btrfs_fs_info *fs_info,
|
|
if (qgroup->excl == qgroup->rfer) {
|
|
if (qgroup->excl == qgroup->rfer) {
|
|
ret = 0;
|
|
ret = 0;
|
|
err = __qgroup_excl_accounting(fs_info, tmp, dst,
|
|
err = __qgroup_excl_accounting(fs_info, tmp, dst,
|
|
- qgroup->excl, sign);
|
|
|
|
|
|
+ qgroup, sign);
|
|
if (err < 0) {
|
|
if (err < 0) {
|
|
ret = err;
|
|
ret = err;
|
|
goto out;
|
|
goto out;
|