Commit 1e0e9d57 authored by Boris Burkov's avatar Boris Burkov Committed by David Sterba
Browse files

btrfs: add helper for recording simple quota deltas



Rather than re-computing shared/exclusive ownership based on backrefs
and walking roots for implicit backrefs, simple quotas does an increment
when creating an extent and a decrement when deleting it. Add the API
for the extent item code to use to track those events.

Signed-off-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 6ed05643
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -4586,3 +4586,49 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
	}
	*root = RB_ROOT;
}

int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,
			      struct btrfs_squota_delta *delta)
{
	int ret;
	struct btrfs_qgroup *qgroup;
	struct btrfs_qgroup *qg;
	LIST_HEAD(qgroup_list);
	u64 root = delta->root;
	u64 num_bytes = delta->num_bytes;
	const int sign = (delta->is_inc ? 1 : -1);

	if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_SIMPLE)
		return 0;

	if (!is_fstree(root))
		return 0;

	spin_lock(&fs_info->qgroup_lock);
	qgroup = find_qgroup_rb(fs_info, root);
	if (!qgroup) {
		ret = -ENOENT;
		goto out;
	}

	ret = 0;
	qgroup_iterator_add(&qgroup_list, qgroup);
	list_for_each_entry(qg, &qgroup_list, iterator) {
		struct btrfs_qgroup_list *glist;

		qg->excl += num_bytes * sign;
		qg->rfer += num_bytes * sign;
		qgroup_dirty(fs_info, qg);

		list_for_each_entry(glist, &qg->groups, next_group)
			qgroup_iterator_add(&qgroup_list, glist->group);
	}
	qgroup_iterator_clean(&qgroup_list);

out:
	spin_unlock(&fs_info->qgroup_lock);
	if (!ret && delta->rsv_bytes)
		btrfs_qgroup_free_refroot(fs_info, root, delta->rsv_bytes,
					  BTRFS_QGROUP_RSV_DATA);
	return ret;
}
+15 −0
Original line number Diff line number Diff line
@@ -269,6 +269,19 @@ struct btrfs_qgroup {
	struct kobject kobj;
};

struct btrfs_squota_delta {
	/* The fstree root this delta counts against. */
	u64 root;
	/* The number of bytes in the extent being counted. */
	u64 num_bytes;
	/* The number of bytes reserved for this extent. */
	u64 rsv_bytes;
	/* Whether we are using or freeing the extent. */
	bool is_inc;
	/* Whether the extent is data or metadata. */
	bool is_data;
};

static inline u64 btrfs_qgroup_subvolid(u64 qgroupid)
{
	return (qgroupid & ((1ULL << BTRFS_QGROUP_LEVEL_SHIFT) - 1));
@@ -407,5 +420,7 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
		struct btrfs_root *root, struct extent_buffer *eb);
void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info);
int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,
			      struct btrfs_squota_delta *delta);

#endif