18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2011 STRATO.  All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/sched.h>
78c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
88c2ecf20Sopenharmony_ci#include <linux/writeback.h>
98c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
108c2ecf20Sopenharmony_ci#include <linux/rbtree.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
138c2ecf20Sopenharmony_ci#include <linux/btrfs.h>
148c2ecf20Sopenharmony_ci#include <linux/sched/mm.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "ctree.h"
178c2ecf20Sopenharmony_ci#include "transaction.h"
188c2ecf20Sopenharmony_ci#include "disk-io.h"
198c2ecf20Sopenharmony_ci#include "locking.h"
208c2ecf20Sopenharmony_ci#include "ulist.h"
218c2ecf20Sopenharmony_ci#include "backref.h"
228c2ecf20Sopenharmony_ci#include "extent_io.h"
238c2ecf20Sopenharmony_ci#include "qgroup.h"
248c2ecf20Sopenharmony_ci#include "block-group.h"
258c2ecf20Sopenharmony_ci#include "sysfs.h"
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* TODO XXX FIXME
288c2ecf20Sopenharmony_ci *  - subvol delete -> delete when ref goes to 0? delete limits also?
298c2ecf20Sopenharmony_ci *  - reorganize keys
308c2ecf20Sopenharmony_ci *  - compressed
318c2ecf20Sopenharmony_ci *  - sync
328c2ecf20Sopenharmony_ci *  - copy also limits on subvol creation
338c2ecf20Sopenharmony_ci *  - limit
348c2ecf20Sopenharmony_ci *  - caches for ulists
358c2ecf20Sopenharmony_ci *  - performance benchmarks
368c2ecf20Sopenharmony_ci *  - check all ioctl parameters
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * Helpers to access qgroup reservation
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * Callers should ensure the lock context and type are valid
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic u64 qgroup_rsv_total(const struct btrfs_qgroup *qgroup)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	u64 ret = 0;
488c2ecf20Sopenharmony_ci	int i;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
518c2ecf20Sopenharmony_ci		ret += qgroup->rsv.values[i];
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	return ret;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
578c2ecf20Sopenharmony_cistatic const char *qgroup_rsv_type_str(enum btrfs_qgroup_rsv_type type)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	if (type == BTRFS_QGROUP_RSV_DATA)
608c2ecf20Sopenharmony_ci		return "data";
618c2ecf20Sopenharmony_ci	if (type == BTRFS_QGROUP_RSV_META_PERTRANS)
628c2ecf20Sopenharmony_ci		return "meta_pertrans";
638c2ecf20Sopenharmony_ci	if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
648c2ecf20Sopenharmony_ci		return "meta_prealloc";
658c2ecf20Sopenharmony_ci	return NULL;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci#endif
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void qgroup_rsv_add(struct btrfs_fs_info *fs_info,
708c2ecf20Sopenharmony_ci			   struct btrfs_qgroup *qgroup, u64 num_bytes,
718c2ecf20Sopenharmony_ci			   enum btrfs_qgroup_rsv_type type)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	trace_qgroup_update_reserve(fs_info, qgroup, num_bytes, type);
748c2ecf20Sopenharmony_ci	qgroup->rsv.values[type] += num_bytes;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic void qgroup_rsv_release(struct btrfs_fs_info *fs_info,
788c2ecf20Sopenharmony_ci			       struct btrfs_qgroup *qgroup, u64 num_bytes,
798c2ecf20Sopenharmony_ci			       enum btrfs_qgroup_rsv_type type)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes, type);
828c2ecf20Sopenharmony_ci	if (qgroup->rsv.values[type] >= num_bytes) {
838c2ecf20Sopenharmony_ci		qgroup->rsv.values[type] -= num_bytes;
848c2ecf20Sopenharmony_ci		return;
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
878c2ecf20Sopenharmony_ci	WARN_RATELIMIT(1,
888c2ecf20Sopenharmony_ci		"qgroup %llu %s reserved space underflow, have %llu to free %llu",
898c2ecf20Sopenharmony_ci		qgroup->qgroupid, qgroup_rsv_type_str(type),
908c2ecf20Sopenharmony_ci		qgroup->rsv.values[type], num_bytes);
918c2ecf20Sopenharmony_ci#endif
928c2ecf20Sopenharmony_ci	qgroup->rsv.values[type] = 0;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic void qgroup_rsv_add_by_qgroup(struct btrfs_fs_info *fs_info,
968c2ecf20Sopenharmony_ci				     struct btrfs_qgroup *dest,
978c2ecf20Sopenharmony_ci				     struct btrfs_qgroup *src)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	int i;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
1028c2ecf20Sopenharmony_ci		qgroup_rsv_add(fs_info, dest, src->rsv.values[i], i);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic void qgroup_rsv_release_by_qgroup(struct btrfs_fs_info *fs_info,
1068c2ecf20Sopenharmony_ci					 struct btrfs_qgroup *dest,
1078c2ecf20Sopenharmony_ci					  struct btrfs_qgroup *src)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	int i;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++)
1128c2ecf20Sopenharmony_ci		qgroup_rsv_release(fs_info, dest, src->rsv.values[i], i);
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
1168c2ecf20Sopenharmony_ci					   int mod)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	if (qg->old_refcnt < seq)
1198c2ecf20Sopenharmony_ci		qg->old_refcnt = seq;
1208c2ecf20Sopenharmony_ci	qg->old_refcnt += mod;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic void btrfs_qgroup_update_new_refcnt(struct btrfs_qgroup *qg, u64 seq,
1248c2ecf20Sopenharmony_ci					   int mod)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	if (qg->new_refcnt < seq)
1278c2ecf20Sopenharmony_ci		qg->new_refcnt = seq;
1288c2ecf20Sopenharmony_ci	qg->new_refcnt += mod;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic inline u64 btrfs_qgroup_get_old_refcnt(struct btrfs_qgroup *qg, u64 seq)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	if (qg->old_refcnt < seq)
1348c2ecf20Sopenharmony_ci		return 0;
1358c2ecf20Sopenharmony_ci	return qg->old_refcnt - seq;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic inline u64 btrfs_qgroup_get_new_refcnt(struct btrfs_qgroup *qg, u64 seq)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	if (qg->new_refcnt < seq)
1418c2ecf20Sopenharmony_ci		return 0;
1428c2ecf20Sopenharmony_ci	return qg->new_refcnt - seq;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/*
1468c2ecf20Sopenharmony_ci * glue structure to represent the relations between qgroups.
1478c2ecf20Sopenharmony_ci */
1488c2ecf20Sopenharmony_cistruct btrfs_qgroup_list {
1498c2ecf20Sopenharmony_ci	struct list_head next_group;
1508c2ecf20Sopenharmony_ci	struct list_head next_member;
1518c2ecf20Sopenharmony_ci	struct btrfs_qgroup *group;
1528c2ecf20Sopenharmony_ci	struct btrfs_qgroup *member;
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic inline u64 qgroup_to_aux(struct btrfs_qgroup *qg)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	return (u64)(uintptr_t)qg;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic inline struct btrfs_qgroup* unode_aux_to_qgroup(struct ulist_node *n)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return (struct btrfs_qgroup *)(uintptr_t)n->aux;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic int
1668c2ecf20Sopenharmony_ciqgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
1678c2ecf20Sopenharmony_ci		   int init_flags);
1688c2ecf20Sopenharmony_cistatic void qgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* must be called with qgroup_ioctl_lock held */
1718c2ecf20Sopenharmony_cistatic struct btrfs_qgroup *find_qgroup_rb(struct btrfs_fs_info *fs_info,
1728c2ecf20Sopenharmony_ci					   u64 qgroupid)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct rb_node *n = fs_info->qgroup_tree.rb_node;
1758c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	while (n) {
1788c2ecf20Sopenharmony_ci		qgroup = rb_entry(n, struct btrfs_qgroup, node);
1798c2ecf20Sopenharmony_ci		if (qgroup->qgroupid < qgroupid)
1808c2ecf20Sopenharmony_ci			n = n->rb_left;
1818c2ecf20Sopenharmony_ci		else if (qgroup->qgroupid > qgroupid)
1828c2ecf20Sopenharmony_ci			n = n->rb_right;
1838c2ecf20Sopenharmony_ci		else
1848c2ecf20Sopenharmony_ci			return qgroup;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci	return NULL;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci/* must be called with qgroup_lock held */
1908c2ecf20Sopenharmony_cistatic struct btrfs_qgroup *add_qgroup_rb(struct btrfs_fs_info *fs_info,
1918c2ecf20Sopenharmony_ci					  u64 qgroupid)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct rb_node **p = &fs_info->qgroup_tree.rb_node;
1948c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
1958c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	while (*p) {
1988c2ecf20Sopenharmony_ci		parent = *p;
1998c2ecf20Sopenharmony_ci		qgroup = rb_entry(parent, struct btrfs_qgroup, node);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		if (qgroup->qgroupid < qgroupid)
2028c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
2038c2ecf20Sopenharmony_ci		else if (qgroup->qgroupid > qgroupid)
2048c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
2058c2ecf20Sopenharmony_ci		else
2068c2ecf20Sopenharmony_ci			return qgroup;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	qgroup = kzalloc(sizeof(*qgroup), GFP_ATOMIC);
2108c2ecf20Sopenharmony_ci	if (!qgroup)
2118c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	qgroup->qgroupid = qgroupid;
2148c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qgroup->groups);
2158c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qgroup->members);
2168c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&qgroup->dirty);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	rb_link_node(&qgroup->node, parent, p);
2198c2ecf20Sopenharmony_ci	rb_insert_color(&qgroup->node, &fs_info->qgroup_tree);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	return qgroup;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic void __del_qgroup_rb(struct btrfs_fs_info *fs_info,
2258c2ecf20Sopenharmony_ci			    struct btrfs_qgroup *qgroup)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	list_del(&qgroup->dirty);
2308c2ecf20Sopenharmony_ci	while (!list_empty(&qgroup->groups)) {
2318c2ecf20Sopenharmony_ci		list = list_first_entry(&qgroup->groups,
2328c2ecf20Sopenharmony_ci					struct btrfs_qgroup_list, next_group);
2338c2ecf20Sopenharmony_ci		list_del(&list->next_group);
2348c2ecf20Sopenharmony_ci		list_del(&list->next_member);
2358c2ecf20Sopenharmony_ci		kfree(list);
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	while (!list_empty(&qgroup->members)) {
2398c2ecf20Sopenharmony_ci		list = list_first_entry(&qgroup->members,
2408c2ecf20Sopenharmony_ci					struct btrfs_qgroup_list, next_member);
2418c2ecf20Sopenharmony_ci		list_del(&list->next_group);
2428c2ecf20Sopenharmony_ci		list_del(&list->next_member);
2438c2ecf20Sopenharmony_ci		kfree(list);
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci/* must be called with qgroup_lock held */
2488c2ecf20Sopenharmony_cistatic int del_qgroup_rb(struct btrfs_fs_info *fs_info, u64 qgroupid)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup = find_qgroup_rb(fs_info, qgroupid);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	if (!qgroup)
2538c2ecf20Sopenharmony_ci		return -ENOENT;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	rb_erase(&qgroup->node, &fs_info->qgroup_tree);
2568c2ecf20Sopenharmony_ci	__del_qgroup_rb(fs_info, qgroup);
2578c2ecf20Sopenharmony_ci	return 0;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci/* must be called with qgroup_lock held */
2618c2ecf20Sopenharmony_cistatic int add_relation_rb(struct btrfs_fs_info *fs_info,
2628c2ecf20Sopenharmony_ci			   u64 memberid, u64 parentid)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	struct btrfs_qgroup *member;
2658c2ecf20Sopenharmony_ci	struct btrfs_qgroup *parent;
2668c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	member = find_qgroup_rb(fs_info, memberid);
2698c2ecf20Sopenharmony_ci	parent = find_qgroup_rb(fs_info, parentid);
2708c2ecf20Sopenharmony_ci	if (!member || !parent)
2718c2ecf20Sopenharmony_ci		return -ENOENT;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	list = kzalloc(sizeof(*list), GFP_ATOMIC);
2748c2ecf20Sopenharmony_ci	if (!list)
2758c2ecf20Sopenharmony_ci		return -ENOMEM;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	list->group = parent;
2788c2ecf20Sopenharmony_ci	list->member = member;
2798c2ecf20Sopenharmony_ci	list_add_tail(&list->next_group, &member->groups);
2808c2ecf20Sopenharmony_ci	list_add_tail(&list->next_member, &parent->members);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return 0;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/* must be called with qgroup_lock held */
2868c2ecf20Sopenharmony_cistatic int del_relation_rb(struct btrfs_fs_info *fs_info,
2878c2ecf20Sopenharmony_ci			   u64 memberid, u64 parentid)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	struct btrfs_qgroup *member;
2908c2ecf20Sopenharmony_ci	struct btrfs_qgroup *parent;
2918c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	member = find_qgroup_rb(fs_info, memberid);
2948c2ecf20Sopenharmony_ci	parent = find_qgroup_rb(fs_info, parentid);
2958c2ecf20Sopenharmony_ci	if (!member || !parent)
2968c2ecf20Sopenharmony_ci		return -ENOENT;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	list_for_each_entry(list, &member->groups, next_group) {
2998c2ecf20Sopenharmony_ci		if (list->group == parent) {
3008c2ecf20Sopenharmony_ci			list_del(&list->next_group);
3018c2ecf20Sopenharmony_ci			list_del(&list->next_member);
3028c2ecf20Sopenharmony_ci			kfree(list);
3038c2ecf20Sopenharmony_ci			return 0;
3048c2ecf20Sopenharmony_ci		}
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci	return -ENOENT;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
3108c2ecf20Sopenharmony_ciint btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
3118c2ecf20Sopenharmony_ci			       u64 rfer, u64 excl)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, qgroupid);
3168c2ecf20Sopenharmony_ci	if (!qgroup)
3178c2ecf20Sopenharmony_ci		return -EINVAL;
3188c2ecf20Sopenharmony_ci	if (qgroup->rfer != rfer || qgroup->excl != excl)
3198c2ecf20Sopenharmony_ci		return -EINVAL;
3208c2ecf20Sopenharmony_ci	return 0;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci#endif
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci/*
3258c2ecf20Sopenharmony_ci * The full config is read in one go, only called from open_ctree()
3268c2ecf20Sopenharmony_ci * It doesn't use any locking, as at this point we're still single-threaded
3278c2ecf20Sopenharmony_ci */
3288c2ecf20Sopenharmony_ciint btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	struct btrfs_key key;
3318c2ecf20Sopenharmony_ci	struct btrfs_key found_key;
3328c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = fs_info->quota_root;
3338c2ecf20Sopenharmony_ci	struct btrfs_path *path = NULL;
3348c2ecf20Sopenharmony_ci	struct extent_buffer *l;
3358c2ecf20Sopenharmony_ci	int slot;
3368c2ecf20Sopenharmony_ci	int ret = 0;
3378c2ecf20Sopenharmony_ci	u64 flags = 0;
3388c2ecf20Sopenharmony_ci	u64 rescan_progress = 0;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
3418c2ecf20Sopenharmony_ci		return 0;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
3448c2ecf20Sopenharmony_ci	if (!fs_info->qgroup_ulist) {
3458c2ecf20Sopenharmony_ci		ret = -ENOMEM;
3468c2ecf20Sopenharmony_ci		goto out;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
3508c2ecf20Sopenharmony_ci	if (!path) {
3518c2ecf20Sopenharmony_ci		ret = -ENOMEM;
3528c2ecf20Sopenharmony_ci		goto out;
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	ret = btrfs_sysfs_add_qgroups(fs_info);
3568c2ecf20Sopenharmony_ci	if (ret < 0)
3578c2ecf20Sopenharmony_ci		goto out;
3588c2ecf20Sopenharmony_ci	/* default this to quota off, in case no status key is found */
3598c2ecf20Sopenharmony_ci	fs_info->qgroup_flags = 0;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/*
3628c2ecf20Sopenharmony_ci	 * pass 1: read status, all qgroup infos and limits
3638c2ecf20Sopenharmony_ci	 */
3648c2ecf20Sopenharmony_ci	key.objectid = 0;
3658c2ecf20Sopenharmony_ci	key.type = 0;
3668c2ecf20Sopenharmony_ci	key.offset = 0;
3678c2ecf20Sopenharmony_ci	ret = btrfs_search_slot_for_read(quota_root, &key, path, 1, 1);
3688c2ecf20Sopenharmony_ci	if (ret)
3698c2ecf20Sopenharmony_ci		goto out;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	while (1) {
3728c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qgroup;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci		slot = path->slots[0];
3758c2ecf20Sopenharmony_ci		l = path->nodes[0];
3768c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(l, &found_key, slot);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		if (found_key.type == BTRFS_QGROUP_STATUS_KEY) {
3798c2ecf20Sopenharmony_ci			struct btrfs_qgroup_status_item *ptr;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci			ptr = btrfs_item_ptr(l, slot,
3828c2ecf20Sopenharmony_ci					     struct btrfs_qgroup_status_item);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci			if (btrfs_qgroup_status_version(l, ptr) !=
3858c2ecf20Sopenharmony_ci			    BTRFS_QGROUP_STATUS_VERSION) {
3868c2ecf20Sopenharmony_ci				btrfs_err(fs_info,
3878c2ecf20Sopenharmony_ci				 "old qgroup version, quota disabled");
3888c2ecf20Sopenharmony_ci				goto out;
3898c2ecf20Sopenharmony_ci			}
3908c2ecf20Sopenharmony_ci			if (btrfs_qgroup_status_generation(l, ptr) !=
3918c2ecf20Sopenharmony_ci			    fs_info->generation) {
3928c2ecf20Sopenharmony_ci				flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
3938c2ecf20Sopenharmony_ci				btrfs_err(fs_info,
3948c2ecf20Sopenharmony_ci					"qgroup generation mismatch, marked as inconsistent");
3958c2ecf20Sopenharmony_ci			}
3968c2ecf20Sopenharmony_ci			fs_info->qgroup_flags = btrfs_qgroup_status_flags(l,
3978c2ecf20Sopenharmony_ci									  ptr);
3988c2ecf20Sopenharmony_ci			rescan_progress = btrfs_qgroup_status_rescan(l, ptr);
3998c2ecf20Sopenharmony_ci			goto next1;
4008c2ecf20Sopenharmony_ci		}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci		if (found_key.type != BTRFS_QGROUP_INFO_KEY &&
4038c2ecf20Sopenharmony_ci		    found_key.type != BTRFS_QGROUP_LIMIT_KEY)
4048c2ecf20Sopenharmony_ci			goto next1;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci		qgroup = find_qgroup_rb(fs_info, found_key.offset);
4078c2ecf20Sopenharmony_ci		if ((qgroup && found_key.type == BTRFS_QGROUP_INFO_KEY) ||
4088c2ecf20Sopenharmony_ci		    (!qgroup && found_key.type == BTRFS_QGROUP_LIMIT_KEY)) {
4098c2ecf20Sopenharmony_ci			btrfs_err(fs_info, "inconsistent qgroup config");
4108c2ecf20Sopenharmony_ci			flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
4118c2ecf20Sopenharmony_ci		}
4128c2ecf20Sopenharmony_ci		if (!qgroup) {
4138c2ecf20Sopenharmony_ci			qgroup = add_qgroup_rb(fs_info, found_key.offset);
4148c2ecf20Sopenharmony_ci			if (IS_ERR(qgroup)) {
4158c2ecf20Sopenharmony_ci				ret = PTR_ERR(qgroup);
4168c2ecf20Sopenharmony_ci				goto out;
4178c2ecf20Sopenharmony_ci			}
4188c2ecf20Sopenharmony_ci		}
4198c2ecf20Sopenharmony_ci		ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
4208c2ecf20Sopenharmony_ci		if (ret < 0)
4218c2ecf20Sopenharmony_ci			goto out;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci		switch (found_key.type) {
4248c2ecf20Sopenharmony_ci		case BTRFS_QGROUP_INFO_KEY: {
4258c2ecf20Sopenharmony_ci			struct btrfs_qgroup_info_item *ptr;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci			ptr = btrfs_item_ptr(l, slot,
4288c2ecf20Sopenharmony_ci					     struct btrfs_qgroup_info_item);
4298c2ecf20Sopenharmony_ci			qgroup->rfer = btrfs_qgroup_info_rfer(l, ptr);
4308c2ecf20Sopenharmony_ci			qgroup->rfer_cmpr = btrfs_qgroup_info_rfer_cmpr(l, ptr);
4318c2ecf20Sopenharmony_ci			qgroup->excl = btrfs_qgroup_info_excl(l, ptr);
4328c2ecf20Sopenharmony_ci			qgroup->excl_cmpr = btrfs_qgroup_info_excl_cmpr(l, ptr);
4338c2ecf20Sopenharmony_ci			/* generation currently unused */
4348c2ecf20Sopenharmony_ci			break;
4358c2ecf20Sopenharmony_ci		}
4368c2ecf20Sopenharmony_ci		case BTRFS_QGROUP_LIMIT_KEY: {
4378c2ecf20Sopenharmony_ci			struct btrfs_qgroup_limit_item *ptr;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci			ptr = btrfs_item_ptr(l, slot,
4408c2ecf20Sopenharmony_ci					     struct btrfs_qgroup_limit_item);
4418c2ecf20Sopenharmony_ci			qgroup->lim_flags = btrfs_qgroup_limit_flags(l, ptr);
4428c2ecf20Sopenharmony_ci			qgroup->max_rfer = btrfs_qgroup_limit_max_rfer(l, ptr);
4438c2ecf20Sopenharmony_ci			qgroup->max_excl = btrfs_qgroup_limit_max_excl(l, ptr);
4448c2ecf20Sopenharmony_ci			qgroup->rsv_rfer = btrfs_qgroup_limit_rsv_rfer(l, ptr);
4458c2ecf20Sopenharmony_ci			qgroup->rsv_excl = btrfs_qgroup_limit_rsv_excl(l, ptr);
4468c2ecf20Sopenharmony_ci			break;
4478c2ecf20Sopenharmony_ci		}
4488c2ecf20Sopenharmony_ci		}
4498c2ecf20Sopenharmony_cinext1:
4508c2ecf20Sopenharmony_ci		ret = btrfs_next_item(quota_root, path);
4518c2ecf20Sopenharmony_ci		if (ret < 0)
4528c2ecf20Sopenharmony_ci			goto out;
4538c2ecf20Sopenharmony_ci		if (ret)
4548c2ecf20Sopenharmony_ci			break;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci	btrfs_release_path(path);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	/*
4598c2ecf20Sopenharmony_ci	 * pass 2: read all qgroup relations
4608c2ecf20Sopenharmony_ci	 */
4618c2ecf20Sopenharmony_ci	key.objectid = 0;
4628c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_RELATION_KEY;
4638c2ecf20Sopenharmony_ci	key.offset = 0;
4648c2ecf20Sopenharmony_ci	ret = btrfs_search_slot_for_read(quota_root, &key, path, 1, 0);
4658c2ecf20Sopenharmony_ci	if (ret)
4668c2ecf20Sopenharmony_ci		goto out;
4678c2ecf20Sopenharmony_ci	while (1) {
4688c2ecf20Sopenharmony_ci		slot = path->slots[0];
4698c2ecf20Sopenharmony_ci		l = path->nodes[0];
4708c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(l, &found_key, slot);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		if (found_key.type != BTRFS_QGROUP_RELATION_KEY)
4738c2ecf20Sopenharmony_ci			goto next2;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		if (found_key.objectid > found_key.offset) {
4768c2ecf20Sopenharmony_ci			/* parent <- member, not needed to build config */
4778c2ecf20Sopenharmony_ci			/* FIXME should we omit the key completely? */
4788c2ecf20Sopenharmony_ci			goto next2;
4798c2ecf20Sopenharmony_ci		}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci		ret = add_relation_rb(fs_info, found_key.objectid,
4828c2ecf20Sopenharmony_ci				      found_key.offset);
4838c2ecf20Sopenharmony_ci		if (ret == -ENOENT) {
4848c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
4858c2ecf20Sopenharmony_ci				"orphan qgroup relation 0x%llx->0x%llx",
4868c2ecf20Sopenharmony_ci				found_key.objectid, found_key.offset);
4878c2ecf20Sopenharmony_ci			ret = 0;	/* ignore the error */
4888c2ecf20Sopenharmony_ci		}
4898c2ecf20Sopenharmony_ci		if (ret)
4908c2ecf20Sopenharmony_ci			goto out;
4918c2ecf20Sopenharmony_cinext2:
4928c2ecf20Sopenharmony_ci		ret = btrfs_next_item(quota_root, path);
4938c2ecf20Sopenharmony_ci		if (ret < 0)
4948c2ecf20Sopenharmony_ci			goto out;
4958c2ecf20Sopenharmony_ci		if (ret)
4968c2ecf20Sopenharmony_ci			break;
4978c2ecf20Sopenharmony_ci	}
4988c2ecf20Sopenharmony_ciout:
4998c2ecf20Sopenharmony_ci	btrfs_free_path(path);
5008c2ecf20Sopenharmony_ci	fs_info->qgroup_flags |= flags;
5018c2ecf20Sopenharmony_ci	if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON))
5028c2ecf20Sopenharmony_ci		clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
5038c2ecf20Sopenharmony_ci	else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN &&
5048c2ecf20Sopenharmony_ci		 ret >= 0)
5058c2ecf20Sopenharmony_ci		ret = qgroup_rescan_init(fs_info, rescan_progress, 0);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	if (ret < 0) {
5088c2ecf20Sopenharmony_ci		ulist_free(fs_info->qgroup_ulist);
5098c2ecf20Sopenharmony_ci		fs_info->qgroup_ulist = NULL;
5108c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
5118c2ecf20Sopenharmony_ci		btrfs_sysfs_del_qgroups(fs_info);
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	return ret < 0 ? ret : 0;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci/*
5188c2ecf20Sopenharmony_ci * Called in close_ctree() when quota is still enabled.  This verifies we don't
5198c2ecf20Sopenharmony_ci * leak some reserved space.
5208c2ecf20Sopenharmony_ci *
5218c2ecf20Sopenharmony_ci * Return false if no reserved space is left.
5228c2ecf20Sopenharmony_ci * Return true if some reserved space is leaked.
5238c2ecf20Sopenharmony_ci */
5248c2ecf20Sopenharmony_cibool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	struct rb_node *node;
5278c2ecf20Sopenharmony_ci	bool ret = false;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
5308c2ecf20Sopenharmony_ci		return ret;
5318c2ecf20Sopenharmony_ci	/*
5328c2ecf20Sopenharmony_ci	 * Since we're unmounting, there is no race and no need to grab qgroup
5338c2ecf20Sopenharmony_ci	 * lock.  And here we don't go post-order to provide a more user
5348c2ecf20Sopenharmony_ci	 * friendly sorted result.
5358c2ecf20Sopenharmony_ci	 */
5368c2ecf20Sopenharmony_ci	for (node = rb_first(&fs_info->qgroup_tree); node; node = rb_next(node)) {
5378c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qgroup;
5388c2ecf20Sopenharmony_ci		int i;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		qgroup = rb_entry(node, struct btrfs_qgroup, node);
5418c2ecf20Sopenharmony_ci		for (i = 0; i < BTRFS_QGROUP_RSV_LAST; i++) {
5428c2ecf20Sopenharmony_ci			if (qgroup->rsv.values[i]) {
5438c2ecf20Sopenharmony_ci				ret = true;
5448c2ecf20Sopenharmony_ci				btrfs_warn(fs_info,
5458c2ecf20Sopenharmony_ci		"qgroup %hu/%llu has unreleased space, type %d rsv %llu",
5468c2ecf20Sopenharmony_ci				   btrfs_qgroup_level(qgroup->qgroupid),
5478c2ecf20Sopenharmony_ci				   btrfs_qgroup_subvolid(qgroup->qgroupid),
5488c2ecf20Sopenharmony_ci				   i, qgroup->rsv.values[i]);
5498c2ecf20Sopenharmony_ci			}
5508c2ecf20Sopenharmony_ci		}
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci	return ret;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/*
5568c2ecf20Sopenharmony_ci * This is called from close_ctree() or open_ctree() or btrfs_quota_disable(),
5578c2ecf20Sopenharmony_ci * first two are in single-threaded paths.And for the third one, we have set
5588c2ecf20Sopenharmony_ci * quota_root to be null with qgroup_lock held before, so it is safe to clean
5598c2ecf20Sopenharmony_ci * up the in-memory structures without qgroup_lock held.
5608c2ecf20Sopenharmony_ci */
5618c2ecf20Sopenharmony_civoid btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct rb_node *n;
5648c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	while ((n = rb_first(&fs_info->qgroup_tree))) {
5678c2ecf20Sopenharmony_ci		qgroup = rb_entry(n, struct btrfs_qgroup, node);
5688c2ecf20Sopenharmony_ci		rb_erase(n, &fs_info->qgroup_tree);
5698c2ecf20Sopenharmony_ci		__del_qgroup_rb(fs_info, qgroup);
5708c2ecf20Sopenharmony_ci		btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
5718c2ecf20Sopenharmony_ci		kfree(qgroup);
5728c2ecf20Sopenharmony_ci	}
5738c2ecf20Sopenharmony_ci	/*
5748c2ecf20Sopenharmony_ci	 * We call btrfs_free_qgroup_config() when unmounting
5758c2ecf20Sopenharmony_ci	 * filesystem and disabling quota, so we set qgroup_ulist
5768c2ecf20Sopenharmony_ci	 * to be null here to avoid double free.
5778c2ecf20Sopenharmony_ci	 */
5788c2ecf20Sopenharmony_ci	ulist_free(fs_info->qgroup_ulist);
5798c2ecf20Sopenharmony_ci	fs_info->qgroup_ulist = NULL;
5808c2ecf20Sopenharmony_ci	btrfs_sysfs_del_qgroups(fs_info);
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic int add_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
5848c2ecf20Sopenharmony_ci				    u64 dst)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	int ret;
5878c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = trans->fs_info->quota_root;
5888c2ecf20Sopenharmony_ci	struct btrfs_path *path;
5898c2ecf20Sopenharmony_ci	struct btrfs_key key;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
5928c2ecf20Sopenharmony_ci	if (!path)
5938c2ecf20Sopenharmony_ci		return -ENOMEM;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	key.objectid = src;
5968c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_RELATION_KEY;
5978c2ecf20Sopenharmony_ci	key.offset = dst;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	ret = btrfs_insert_empty_item(trans, quota_root, path, &key, 0);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(path->nodes[0]);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	btrfs_free_path(path);
6048c2ecf20Sopenharmony_ci	return ret;
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_cistatic int del_qgroup_relation_item(struct btrfs_trans_handle *trans, u64 src,
6088c2ecf20Sopenharmony_ci				    u64 dst)
6098c2ecf20Sopenharmony_ci{
6108c2ecf20Sopenharmony_ci	int ret;
6118c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = trans->fs_info->quota_root;
6128c2ecf20Sopenharmony_ci	struct btrfs_path *path;
6138c2ecf20Sopenharmony_ci	struct btrfs_key key;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
6168c2ecf20Sopenharmony_ci	if (!path)
6178c2ecf20Sopenharmony_ci		return -ENOMEM;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	key.objectid = src;
6208c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_RELATION_KEY;
6218c2ecf20Sopenharmony_ci	key.offset = dst;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
6248c2ecf20Sopenharmony_ci	if (ret < 0)
6258c2ecf20Sopenharmony_ci		goto out;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	if (ret > 0) {
6288c2ecf20Sopenharmony_ci		ret = -ENOENT;
6298c2ecf20Sopenharmony_ci		goto out;
6308c2ecf20Sopenharmony_ci	}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	ret = btrfs_del_item(trans, quota_root, path);
6338c2ecf20Sopenharmony_ciout:
6348c2ecf20Sopenharmony_ci	btrfs_free_path(path);
6358c2ecf20Sopenharmony_ci	return ret;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic int add_qgroup_item(struct btrfs_trans_handle *trans,
6398c2ecf20Sopenharmony_ci			   struct btrfs_root *quota_root, u64 qgroupid)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	int ret;
6428c2ecf20Sopenharmony_ci	struct btrfs_path *path;
6438c2ecf20Sopenharmony_ci	struct btrfs_qgroup_info_item *qgroup_info;
6448c2ecf20Sopenharmony_ci	struct btrfs_qgroup_limit_item *qgroup_limit;
6458c2ecf20Sopenharmony_ci	struct extent_buffer *leaf;
6468c2ecf20Sopenharmony_ci	struct btrfs_key key;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (btrfs_is_testing(quota_root->fs_info))
6498c2ecf20Sopenharmony_ci		return 0;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
6528c2ecf20Sopenharmony_ci	if (!path)
6538c2ecf20Sopenharmony_ci		return -ENOMEM;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	key.objectid = 0;
6568c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_INFO_KEY;
6578c2ecf20Sopenharmony_ci	key.offset = qgroupid;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	/*
6608c2ecf20Sopenharmony_ci	 * Avoid a transaction abort by catching -EEXIST here. In that
6618c2ecf20Sopenharmony_ci	 * case, we proceed by re-initializing the existing structure
6628c2ecf20Sopenharmony_ci	 * on disk.
6638c2ecf20Sopenharmony_ci	 */
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
6668c2ecf20Sopenharmony_ci				      sizeof(*qgroup_info));
6678c2ecf20Sopenharmony_ci	if (ret && ret != -EEXIST)
6688c2ecf20Sopenharmony_ci		goto out;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	leaf = path->nodes[0];
6718c2ecf20Sopenharmony_ci	qgroup_info = btrfs_item_ptr(leaf, path->slots[0],
6728c2ecf20Sopenharmony_ci				 struct btrfs_qgroup_info_item);
6738c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_generation(leaf, qgroup_info, trans->transid);
6748c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_rfer(leaf, qgroup_info, 0);
6758c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_rfer_cmpr(leaf, qgroup_info, 0);
6768c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_excl(leaf, qgroup_info, 0);
6778c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_excl_cmpr(leaf, qgroup_info, 0);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(leaf);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	btrfs_release_path(path);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_LIMIT_KEY;
6848c2ecf20Sopenharmony_ci	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
6858c2ecf20Sopenharmony_ci				      sizeof(*qgroup_limit));
6868c2ecf20Sopenharmony_ci	if (ret && ret != -EEXIST)
6878c2ecf20Sopenharmony_ci		goto out;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	leaf = path->nodes[0];
6908c2ecf20Sopenharmony_ci	qgroup_limit = btrfs_item_ptr(leaf, path->slots[0],
6918c2ecf20Sopenharmony_ci				  struct btrfs_qgroup_limit_item);
6928c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_flags(leaf, qgroup_limit, 0);
6938c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_max_rfer(leaf, qgroup_limit, 0);
6948c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_max_excl(leaf, qgroup_limit, 0);
6958c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_rsv_rfer(leaf, qgroup_limit, 0);
6968c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_rsv_excl(leaf, qgroup_limit, 0);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(leaf);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	ret = 0;
7018c2ecf20Sopenharmony_ciout:
7028c2ecf20Sopenharmony_ci	btrfs_free_path(path);
7038c2ecf20Sopenharmony_ci	return ret;
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_cistatic int del_qgroup_item(struct btrfs_trans_handle *trans, u64 qgroupid)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	int ret;
7098c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = trans->fs_info->quota_root;
7108c2ecf20Sopenharmony_ci	struct btrfs_path *path;
7118c2ecf20Sopenharmony_ci	struct btrfs_key key;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
7148c2ecf20Sopenharmony_ci	if (!path)
7158c2ecf20Sopenharmony_ci		return -ENOMEM;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	key.objectid = 0;
7188c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_INFO_KEY;
7198c2ecf20Sopenharmony_ci	key.offset = qgroupid;
7208c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
7218c2ecf20Sopenharmony_ci	if (ret < 0)
7228c2ecf20Sopenharmony_ci		goto out;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	if (ret > 0) {
7258c2ecf20Sopenharmony_ci		ret = -ENOENT;
7268c2ecf20Sopenharmony_ci		goto out;
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	ret = btrfs_del_item(trans, quota_root, path);
7308c2ecf20Sopenharmony_ci	if (ret)
7318c2ecf20Sopenharmony_ci		goto out;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	btrfs_release_path(path);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_LIMIT_KEY;
7368c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, -1, 1);
7378c2ecf20Sopenharmony_ci	if (ret < 0)
7388c2ecf20Sopenharmony_ci		goto out;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	if (ret > 0) {
7418c2ecf20Sopenharmony_ci		ret = -ENOENT;
7428c2ecf20Sopenharmony_ci		goto out;
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	ret = btrfs_del_item(trans, quota_root, path);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ciout:
7488c2ecf20Sopenharmony_ci	btrfs_free_path(path);
7498c2ecf20Sopenharmony_ci	return ret;
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_cistatic int update_qgroup_limit_item(struct btrfs_trans_handle *trans,
7538c2ecf20Sopenharmony_ci				    struct btrfs_qgroup *qgroup)
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = trans->fs_info->quota_root;
7568c2ecf20Sopenharmony_ci	struct btrfs_path *path;
7578c2ecf20Sopenharmony_ci	struct btrfs_key key;
7588c2ecf20Sopenharmony_ci	struct extent_buffer *l;
7598c2ecf20Sopenharmony_ci	struct btrfs_qgroup_limit_item *qgroup_limit;
7608c2ecf20Sopenharmony_ci	int ret;
7618c2ecf20Sopenharmony_ci	int slot;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	key.objectid = 0;
7648c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_LIMIT_KEY;
7658c2ecf20Sopenharmony_ci	key.offset = qgroup->qgroupid;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
7688c2ecf20Sopenharmony_ci	if (!path)
7698c2ecf20Sopenharmony_ci		return -ENOMEM;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
7728c2ecf20Sopenharmony_ci	if (ret > 0)
7738c2ecf20Sopenharmony_ci		ret = -ENOENT;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	if (ret)
7768c2ecf20Sopenharmony_ci		goto out;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	l = path->nodes[0];
7798c2ecf20Sopenharmony_ci	slot = path->slots[0];
7808c2ecf20Sopenharmony_ci	qgroup_limit = btrfs_item_ptr(l, slot, struct btrfs_qgroup_limit_item);
7818c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_flags(l, qgroup_limit, qgroup->lim_flags);
7828c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_max_rfer(l, qgroup_limit, qgroup->max_rfer);
7838c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_max_excl(l, qgroup_limit, qgroup->max_excl);
7848c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_rsv_rfer(l, qgroup_limit, qgroup->rsv_rfer);
7858c2ecf20Sopenharmony_ci	btrfs_set_qgroup_limit_rsv_excl(l, qgroup_limit, qgroup->rsv_excl);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(l);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ciout:
7908c2ecf20Sopenharmony_ci	btrfs_free_path(path);
7918c2ecf20Sopenharmony_ci	return ret;
7928c2ecf20Sopenharmony_ci}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic int update_qgroup_info_item(struct btrfs_trans_handle *trans,
7958c2ecf20Sopenharmony_ci				   struct btrfs_qgroup *qgroup)
7968c2ecf20Sopenharmony_ci{
7978c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
7988c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = fs_info->quota_root;
7998c2ecf20Sopenharmony_ci	struct btrfs_path *path;
8008c2ecf20Sopenharmony_ci	struct btrfs_key key;
8018c2ecf20Sopenharmony_ci	struct extent_buffer *l;
8028c2ecf20Sopenharmony_ci	struct btrfs_qgroup_info_item *qgroup_info;
8038c2ecf20Sopenharmony_ci	int ret;
8048c2ecf20Sopenharmony_ci	int slot;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	if (btrfs_is_testing(fs_info))
8078c2ecf20Sopenharmony_ci		return 0;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	key.objectid = 0;
8108c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_INFO_KEY;
8118c2ecf20Sopenharmony_ci	key.offset = qgroup->qgroupid;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
8148c2ecf20Sopenharmony_ci	if (!path)
8158c2ecf20Sopenharmony_ci		return -ENOMEM;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
8188c2ecf20Sopenharmony_ci	if (ret > 0)
8198c2ecf20Sopenharmony_ci		ret = -ENOENT;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	if (ret)
8228c2ecf20Sopenharmony_ci		goto out;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	l = path->nodes[0];
8258c2ecf20Sopenharmony_ci	slot = path->slots[0];
8268c2ecf20Sopenharmony_ci	qgroup_info = btrfs_item_ptr(l, slot, struct btrfs_qgroup_info_item);
8278c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_generation(l, qgroup_info, trans->transid);
8288c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_rfer(l, qgroup_info, qgroup->rfer);
8298c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_rfer_cmpr(l, qgroup_info, qgroup->rfer_cmpr);
8308c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_excl(l, qgroup_info, qgroup->excl);
8318c2ecf20Sopenharmony_ci	btrfs_set_qgroup_info_excl_cmpr(l, qgroup_info, qgroup->excl_cmpr);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(l);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ciout:
8368c2ecf20Sopenharmony_ci	btrfs_free_path(path);
8378c2ecf20Sopenharmony_ci	return ret;
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic int update_qgroup_status_item(struct btrfs_trans_handle *trans)
8418c2ecf20Sopenharmony_ci{
8428c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
8438c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = fs_info->quota_root;
8448c2ecf20Sopenharmony_ci	struct btrfs_path *path;
8458c2ecf20Sopenharmony_ci	struct btrfs_key key;
8468c2ecf20Sopenharmony_ci	struct extent_buffer *l;
8478c2ecf20Sopenharmony_ci	struct btrfs_qgroup_status_item *ptr;
8488c2ecf20Sopenharmony_ci	int ret;
8498c2ecf20Sopenharmony_ci	int slot;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	key.objectid = 0;
8528c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_STATUS_KEY;
8538c2ecf20Sopenharmony_ci	key.offset = 0;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
8568c2ecf20Sopenharmony_ci	if (!path)
8578c2ecf20Sopenharmony_ci		return -ENOMEM;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	ret = btrfs_search_slot(trans, quota_root, &key, path, 0, 1);
8608c2ecf20Sopenharmony_ci	if (ret > 0)
8618c2ecf20Sopenharmony_ci		ret = -ENOENT;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	if (ret)
8648c2ecf20Sopenharmony_ci		goto out;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	l = path->nodes[0];
8678c2ecf20Sopenharmony_ci	slot = path->slots[0];
8688c2ecf20Sopenharmony_ci	ptr = btrfs_item_ptr(l, slot, struct btrfs_qgroup_status_item);
8698c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_flags(l, ptr, fs_info->qgroup_flags);
8708c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_generation(l, ptr, trans->transid);
8718c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_rescan(l, ptr,
8728c2ecf20Sopenharmony_ci				fs_info->qgroup_rescan_progress.objectid);
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(l);
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ciout:
8778c2ecf20Sopenharmony_ci	btrfs_free_path(path);
8788c2ecf20Sopenharmony_ci	return ret;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci/*
8828c2ecf20Sopenharmony_ci * called with qgroup_lock held
8838c2ecf20Sopenharmony_ci */
8848c2ecf20Sopenharmony_cistatic int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
8858c2ecf20Sopenharmony_ci				  struct btrfs_root *root)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	struct btrfs_path *path;
8888c2ecf20Sopenharmony_ci	struct btrfs_key key;
8898c2ecf20Sopenharmony_ci	struct extent_buffer *leaf = NULL;
8908c2ecf20Sopenharmony_ci	int ret;
8918c2ecf20Sopenharmony_ci	int nr = 0;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
8948c2ecf20Sopenharmony_ci	if (!path)
8958c2ecf20Sopenharmony_ci		return -ENOMEM;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	path->leave_spinning = 1;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	key.objectid = 0;
9008c2ecf20Sopenharmony_ci	key.offset = 0;
9018c2ecf20Sopenharmony_ci	key.type = 0;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	while (1) {
9048c2ecf20Sopenharmony_ci		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
9058c2ecf20Sopenharmony_ci		if (ret < 0)
9068c2ecf20Sopenharmony_ci			goto out;
9078c2ecf20Sopenharmony_ci		leaf = path->nodes[0];
9088c2ecf20Sopenharmony_ci		nr = btrfs_header_nritems(leaf);
9098c2ecf20Sopenharmony_ci		if (!nr)
9108c2ecf20Sopenharmony_ci			break;
9118c2ecf20Sopenharmony_ci		/*
9128c2ecf20Sopenharmony_ci		 * delete the leaf one by one
9138c2ecf20Sopenharmony_ci		 * since the whole tree is going
9148c2ecf20Sopenharmony_ci		 * to be deleted.
9158c2ecf20Sopenharmony_ci		 */
9168c2ecf20Sopenharmony_ci		path->slots[0] = 0;
9178c2ecf20Sopenharmony_ci		ret = btrfs_del_items(trans, root, path, 0, nr);
9188c2ecf20Sopenharmony_ci		if (ret)
9198c2ecf20Sopenharmony_ci			goto out;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci		btrfs_release_path(path);
9228c2ecf20Sopenharmony_ci	}
9238c2ecf20Sopenharmony_ci	ret = 0;
9248c2ecf20Sopenharmony_ciout:
9258c2ecf20Sopenharmony_ci	btrfs_free_path(path);
9268c2ecf20Sopenharmony_ci	return ret;
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ciint btrfs_quota_enable(struct btrfs_fs_info *fs_info)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root;
9328c2ecf20Sopenharmony_ci	struct btrfs_root *tree_root = fs_info->tree_root;
9338c2ecf20Sopenharmony_ci	struct btrfs_path *path = NULL;
9348c2ecf20Sopenharmony_ci	struct btrfs_qgroup_status_item *ptr;
9358c2ecf20Sopenharmony_ci	struct extent_buffer *leaf;
9368c2ecf20Sopenharmony_ci	struct btrfs_key key;
9378c2ecf20Sopenharmony_ci	struct btrfs_key found_key;
9388c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup = NULL;
9398c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans = NULL;
9408c2ecf20Sopenharmony_ci	struct ulist *ulist = NULL;
9418c2ecf20Sopenharmony_ci	int ret = 0;
9428c2ecf20Sopenharmony_ci	int slot;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	/*
9458c2ecf20Sopenharmony_ci	 * We need to have subvol_sem write locked, to prevent races between
9468c2ecf20Sopenharmony_ci	 * concurrent tasks trying to enable quotas, because we will unlock
9478c2ecf20Sopenharmony_ci	 * and relock qgroup_ioctl_lock before setting fs_info->quota_root
9488c2ecf20Sopenharmony_ci	 * and before setting BTRFS_FS_QUOTA_ENABLED.
9498c2ecf20Sopenharmony_ci	 */
9508c2ecf20Sopenharmony_ci	lockdep_assert_held_write(&fs_info->subvol_sem);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
9538c2ecf20Sopenharmony_ci	if (fs_info->quota_root)
9548c2ecf20Sopenharmony_ci		goto out;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	ulist = ulist_alloc(GFP_KERNEL);
9578c2ecf20Sopenharmony_ci	if (!ulist) {
9588c2ecf20Sopenharmony_ci		ret = -ENOMEM;
9598c2ecf20Sopenharmony_ci		goto out;
9608c2ecf20Sopenharmony_ci	}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	ret = btrfs_sysfs_add_qgroups(fs_info);
9638c2ecf20Sopenharmony_ci	if (ret < 0)
9648c2ecf20Sopenharmony_ci		goto out;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	/*
9678c2ecf20Sopenharmony_ci	 * Unlock qgroup_ioctl_lock before starting the transaction. This is to
9688c2ecf20Sopenharmony_ci	 * avoid lock acquisition inversion problems (reported by lockdep) between
9698c2ecf20Sopenharmony_ci	 * qgroup_ioctl_lock and the vfs freeze semaphores, acquired when we
9708c2ecf20Sopenharmony_ci	 * start a transaction.
9718c2ecf20Sopenharmony_ci	 * After we started the transaction lock qgroup_ioctl_lock again and
9728c2ecf20Sopenharmony_ci	 * check if someone else created the quota root in the meanwhile. If so,
9738c2ecf20Sopenharmony_ci	 * just return success and release the transaction handle.
9748c2ecf20Sopenharmony_ci	 *
9758c2ecf20Sopenharmony_ci	 * Also we don't need to worry about someone else calling
9768c2ecf20Sopenharmony_ci	 * btrfs_sysfs_add_qgroups() after we unlock and getting an error because
9778c2ecf20Sopenharmony_ci	 * that function returns 0 (success) when the sysfs entries already exist.
9788c2ecf20Sopenharmony_ci	 */
9798c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	/*
9828c2ecf20Sopenharmony_ci	 * 1 for quota root item
9838c2ecf20Sopenharmony_ci	 * 1 for BTRFS_QGROUP_STATUS item
9848c2ecf20Sopenharmony_ci	 *
9858c2ecf20Sopenharmony_ci	 * Yet we also need 2*n items for a QGROUP_INFO/QGROUP_LIMIT items
9868c2ecf20Sopenharmony_ci	 * per subvolume. However those are not currently reserved since it
9878c2ecf20Sopenharmony_ci	 * would be a lot of overkill.
9888c2ecf20Sopenharmony_ci	 */
9898c2ecf20Sopenharmony_ci	trans = btrfs_start_transaction(tree_root, 2);
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
9928c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
9938c2ecf20Sopenharmony_ci		ret = PTR_ERR(trans);
9948c2ecf20Sopenharmony_ci		trans = NULL;
9958c2ecf20Sopenharmony_ci		goto out;
9968c2ecf20Sopenharmony_ci	}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	if (fs_info->quota_root)
9998c2ecf20Sopenharmony_ci		goto out;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	fs_info->qgroup_ulist = ulist;
10028c2ecf20Sopenharmony_ci	ulist = NULL;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	/*
10058c2ecf20Sopenharmony_ci	 * initially create the quota tree
10068c2ecf20Sopenharmony_ci	 */
10078c2ecf20Sopenharmony_ci	quota_root = btrfs_create_tree(trans, BTRFS_QUOTA_TREE_OBJECTID);
10088c2ecf20Sopenharmony_ci	if (IS_ERR(quota_root)) {
10098c2ecf20Sopenharmony_ci		ret =  PTR_ERR(quota_root);
10108c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
10118c2ecf20Sopenharmony_ci		goto out;
10128c2ecf20Sopenharmony_ci	}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
10158c2ecf20Sopenharmony_ci	if (!path) {
10168c2ecf20Sopenharmony_ci		ret = -ENOMEM;
10178c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
10188c2ecf20Sopenharmony_ci		goto out_free_root;
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	key.objectid = 0;
10228c2ecf20Sopenharmony_ci	key.type = BTRFS_QGROUP_STATUS_KEY;
10238c2ecf20Sopenharmony_ci	key.offset = 0;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
10268c2ecf20Sopenharmony_ci				      sizeof(*ptr));
10278c2ecf20Sopenharmony_ci	if (ret) {
10288c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
10298c2ecf20Sopenharmony_ci		goto out_free_path;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	leaf = path->nodes[0];
10338c2ecf20Sopenharmony_ci	ptr = btrfs_item_ptr(leaf, path->slots[0],
10348c2ecf20Sopenharmony_ci				 struct btrfs_qgroup_status_item);
10358c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_generation(leaf, ptr, trans->transid);
10368c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_version(leaf, ptr, BTRFS_QGROUP_STATUS_VERSION);
10378c2ecf20Sopenharmony_ci	fs_info->qgroup_flags = BTRFS_QGROUP_STATUS_FLAG_ON |
10388c2ecf20Sopenharmony_ci				BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
10398c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_flags(leaf, ptr, fs_info->qgroup_flags);
10408c2ecf20Sopenharmony_ci	btrfs_set_qgroup_status_rescan(leaf, ptr, 0);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	btrfs_mark_buffer_dirty(leaf);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	key.objectid = 0;
10458c2ecf20Sopenharmony_ci	key.type = BTRFS_ROOT_REF_KEY;
10468c2ecf20Sopenharmony_ci	key.offset = 0;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	btrfs_release_path(path);
10498c2ecf20Sopenharmony_ci	ret = btrfs_search_slot_for_read(tree_root, &key, path, 1, 0);
10508c2ecf20Sopenharmony_ci	if (ret > 0)
10518c2ecf20Sopenharmony_ci		goto out_add_root;
10528c2ecf20Sopenharmony_ci	if (ret < 0) {
10538c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
10548c2ecf20Sopenharmony_ci		goto out_free_path;
10558c2ecf20Sopenharmony_ci	}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	while (1) {
10588c2ecf20Sopenharmony_ci		slot = path->slots[0];
10598c2ecf20Sopenharmony_ci		leaf = path->nodes[0];
10608c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(leaf, &found_key, slot);
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci		if (found_key.type == BTRFS_ROOT_REF_KEY) {
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci			/* Release locks on tree_root before we access quota_root */
10658c2ecf20Sopenharmony_ci			btrfs_release_path(path);
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci			ret = add_qgroup_item(trans, quota_root,
10688c2ecf20Sopenharmony_ci					      found_key.offset);
10698c2ecf20Sopenharmony_ci			if (ret) {
10708c2ecf20Sopenharmony_ci				btrfs_abort_transaction(trans, ret);
10718c2ecf20Sopenharmony_ci				goto out_free_path;
10728c2ecf20Sopenharmony_ci			}
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci			qgroup = add_qgroup_rb(fs_info, found_key.offset);
10758c2ecf20Sopenharmony_ci			if (IS_ERR(qgroup)) {
10768c2ecf20Sopenharmony_ci				ret = PTR_ERR(qgroup);
10778c2ecf20Sopenharmony_ci				btrfs_abort_transaction(trans, ret);
10788c2ecf20Sopenharmony_ci				goto out_free_path;
10798c2ecf20Sopenharmony_ci			}
10808c2ecf20Sopenharmony_ci			ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
10818c2ecf20Sopenharmony_ci			if (ret < 0) {
10828c2ecf20Sopenharmony_ci				btrfs_abort_transaction(trans, ret);
10838c2ecf20Sopenharmony_ci				goto out_free_path;
10848c2ecf20Sopenharmony_ci			}
10858c2ecf20Sopenharmony_ci			ret = btrfs_search_slot_for_read(tree_root, &found_key,
10868c2ecf20Sopenharmony_ci							 path, 1, 0);
10878c2ecf20Sopenharmony_ci			if (ret < 0) {
10888c2ecf20Sopenharmony_ci				btrfs_abort_transaction(trans, ret);
10898c2ecf20Sopenharmony_ci				goto out_free_path;
10908c2ecf20Sopenharmony_ci			}
10918c2ecf20Sopenharmony_ci			if (ret > 0) {
10928c2ecf20Sopenharmony_ci				/*
10938c2ecf20Sopenharmony_ci				 * Shouldn't happen, but in case it does we
10948c2ecf20Sopenharmony_ci				 * don't need to do the btrfs_next_item, just
10958c2ecf20Sopenharmony_ci				 * continue.
10968c2ecf20Sopenharmony_ci				 */
10978c2ecf20Sopenharmony_ci				continue;
10988c2ecf20Sopenharmony_ci			}
10998c2ecf20Sopenharmony_ci		}
11008c2ecf20Sopenharmony_ci		ret = btrfs_next_item(tree_root, path);
11018c2ecf20Sopenharmony_ci		if (ret < 0) {
11028c2ecf20Sopenharmony_ci			btrfs_abort_transaction(trans, ret);
11038c2ecf20Sopenharmony_ci			goto out_free_path;
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci		if (ret)
11068c2ecf20Sopenharmony_ci			break;
11078c2ecf20Sopenharmony_ci	}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ciout_add_root:
11108c2ecf20Sopenharmony_ci	btrfs_release_path(path);
11118c2ecf20Sopenharmony_ci	ret = add_qgroup_item(trans, quota_root, BTRFS_FS_TREE_OBJECTID);
11128c2ecf20Sopenharmony_ci	if (ret) {
11138c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
11148c2ecf20Sopenharmony_ci		goto out_free_path;
11158c2ecf20Sopenharmony_ci	}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	qgroup = add_qgroup_rb(fs_info, BTRFS_FS_TREE_OBJECTID);
11188c2ecf20Sopenharmony_ci	if (IS_ERR(qgroup)) {
11198c2ecf20Sopenharmony_ci		ret = PTR_ERR(qgroup);
11208c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
11218c2ecf20Sopenharmony_ci		goto out_free_path;
11228c2ecf20Sopenharmony_ci	}
11238c2ecf20Sopenharmony_ci	ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
11248c2ecf20Sopenharmony_ci	if (ret < 0) {
11258c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
11268c2ecf20Sopenharmony_ci		goto out_free_path;
11278c2ecf20Sopenharmony_ci	}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
11308c2ecf20Sopenharmony_ci	/*
11318c2ecf20Sopenharmony_ci	 * Commit the transaction while not holding qgroup_ioctl_lock, to avoid
11328c2ecf20Sopenharmony_ci	 * a deadlock with tasks concurrently doing other qgroup operations, such
11338c2ecf20Sopenharmony_ci	 * adding/removing qgroups or adding/deleting qgroup relations for example,
11348c2ecf20Sopenharmony_ci	 * because all qgroup operations first start or join a transaction and then
11358c2ecf20Sopenharmony_ci	 * lock the qgroup_ioctl_lock mutex.
11368c2ecf20Sopenharmony_ci	 * We are safe from a concurrent task trying to enable quotas, by calling
11378c2ecf20Sopenharmony_ci	 * this function, since we are serialized by fs_info->subvol_sem.
11388c2ecf20Sopenharmony_ci	 */
11398c2ecf20Sopenharmony_ci	ret = btrfs_commit_transaction(trans);
11408c2ecf20Sopenharmony_ci	trans = NULL;
11418c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
11428c2ecf20Sopenharmony_ci	if (ret)
11438c2ecf20Sopenharmony_ci		goto out_free_path;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	/*
11468c2ecf20Sopenharmony_ci	 * Set quota enabled flag after committing the transaction, to avoid
11478c2ecf20Sopenharmony_ci	 * deadlocks on fs_info->qgroup_ioctl_lock with concurrent snapshot
11488c2ecf20Sopenharmony_ci	 * creation.
11498c2ecf20Sopenharmony_ci	 */
11508c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
11518c2ecf20Sopenharmony_ci	fs_info->quota_root = quota_root;
11528c2ecf20Sopenharmony_ci	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
11538c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	ret = qgroup_rescan_init(fs_info, 0, 1);
11568c2ecf20Sopenharmony_ci	if (!ret) {
11578c2ecf20Sopenharmony_ci	        qgroup_rescan_zero_tracking(fs_info);
11588c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_running = true;
11598c2ecf20Sopenharmony_ci	        btrfs_queue_work(fs_info->qgroup_rescan_workers,
11608c2ecf20Sopenharmony_ci	                         &fs_info->qgroup_rescan_work);
11618c2ecf20Sopenharmony_ci	} else {
11628c2ecf20Sopenharmony_ci		/*
11638c2ecf20Sopenharmony_ci		 * We have set both BTRFS_FS_QUOTA_ENABLED and
11648c2ecf20Sopenharmony_ci		 * BTRFS_QGROUP_STATUS_FLAG_ON, so we can only fail with
11658c2ecf20Sopenharmony_ci		 * -EINPROGRESS. That can happen because someone started the
11668c2ecf20Sopenharmony_ci		 * rescan worker by calling quota rescan ioctl before we
11678c2ecf20Sopenharmony_ci		 * attempted to initialize the rescan worker. Failure due to
11688c2ecf20Sopenharmony_ci		 * quotas disabled in the meanwhile is not possible, because
11698c2ecf20Sopenharmony_ci		 * we are holding a write lock on fs_info->subvol_sem, which
11708c2ecf20Sopenharmony_ci		 * is also acquired when disabling quotas.
11718c2ecf20Sopenharmony_ci		 * Ignore such error, and any other error would need to undo
11728c2ecf20Sopenharmony_ci		 * everything we did in the transaction we just committed.
11738c2ecf20Sopenharmony_ci		 */
11748c2ecf20Sopenharmony_ci		ASSERT(ret == -EINPROGRESS);
11758c2ecf20Sopenharmony_ci		ret = 0;
11768c2ecf20Sopenharmony_ci	}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ciout_free_path:
11798c2ecf20Sopenharmony_ci	btrfs_free_path(path);
11808c2ecf20Sopenharmony_ciout_free_root:
11818c2ecf20Sopenharmony_ci	if (ret)
11828c2ecf20Sopenharmony_ci		btrfs_put_root(quota_root);
11838c2ecf20Sopenharmony_ciout:
11848c2ecf20Sopenharmony_ci	if (ret) {
11858c2ecf20Sopenharmony_ci		ulist_free(fs_info->qgroup_ulist);
11868c2ecf20Sopenharmony_ci		fs_info->qgroup_ulist = NULL;
11878c2ecf20Sopenharmony_ci		btrfs_sysfs_del_qgroups(fs_info);
11888c2ecf20Sopenharmony_ci	}
11898c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
11908c2ecf20Sopenharmony_ci	if (ret && trans)
11918c2ecf20Sopenharmony_ci		btrfs_end_transaction(trans);
11928c2ecf20Sopenharmony_ci	else if (trans)
11938c2ecf20Sopenharmony_ci		ret = btrfs_end_transaction(trans);
11948c2ecf20Sopenharmony_ci	ulist_free(ulist);
11958c2ecf20Sopenharmony_ci	return ret;
11968c2ecf20Sopenharmony_ci}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ciint btrfs_quota_disable(struct btrfs_fs_info *fs_info)
11998c2ecf20Sopenharmony_ci{
12008c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root = NULL;
12018c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans = NULL;
12028c2ecf20Sopenharmony_ci	int ret = 0;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	/*
12058c2ecf20Sopenharmony_ci	 * We need to have subvol_sem write locked to prevent races with
12068c2ecf20Sopenharmony_ci	 * snapshot creation.
12078c2ecf20Sopenharmony_ci	 */
12088c2ecf20Sopenharmony_ci	lockdep_assert_held_write(&fs_info->subvol_sem);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	/*
12118c2ecf20Sopenharmony_ci	 * Lock the cleaner mutex to prevent races with concurrent relocation,
12128c2ecf20Sopenharmony_ci	 * because relocation may be building backrefs for blocks of the quota
12138c2ecf20Sopenharmony_ci	 * root while we are deleting the root. This is like dropping fs roots
12148c2ecf20Sopenharmony_ci	 * of deleted snapshots/subvolumes, we need the same protection.
12158c2ecf20Sopenharmony_ci	 *
12168c2ecf20Sopenharmony_ci	 * This also prevents races between concurrent tasks trying to disable
12178c2ecf20Sopenharmony_ci	 * quotas, because we will unlock and relock qgroup_ioctl_lock across
12188c2ecf20Sopenharmony_ci	 * BTRFS_FS_QUOTA_ENABLED changes.
12198c2ecf20Sopenharmony_ci	 */
12208c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->cleaner_mutex);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
12238c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
12248c2ecf20Sopenharmony_ci		goto out;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	/*
12278c2ecf20Sopenharmony_ci	 * Unlock the qgroup_ioctl_lock mutex before waiting for the rescan worker to
12288c2ecf20Sopenharmony_ci	 * complete. Otherwise we can deadlock because btrfs_remove_qgroup() needs
12298c2ecf20Sopenharmony_ci	 * to lock that mutex while holding a transaction handle and the rescan
12308c2ecf20Sopenharmony_ci	 * worker needs to commit a transaction.
12318c2ecf20Sopenharmony_ci	 */
12328c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	/*
12358c2ecf20Sopenharmony_ci	 * Request qgroup rescan worker to complete and wait for it. This wait
12368c2ecf20Sopenharmony_ci	 * must be done before transaction start for quota disable since it may
12378c2ecf20Sopenharmony_ci	 * deadlock with transaction by the qgroup rescan worker.
12388c2ecf20Sopenharmony_ci	 */
12398c2ecf20Sopenharmony_ci	clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
12408c2ecf20Sopenharmony_ci	btrfs_qgroup_wait_for_completion(fs_info, false);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	/*
12438c2ecf20Sopenharmony_ci	 * 1 For the root item
12448c2ecf20Sopenharmony_ci	 *
12458c2ecf20Sopenharmony_ci	 * We should also reserve enough items for the quota tree deletion in
12468c2ecf20Sopenharmony_ci	 * btrfs_clean_quota_tree but this is not done.
12478c2ecf20Sopenharmony_ci	 *
12488c2ecf20Sopenharmony_ci	 * Also, we must always start a transaction without holding the mutex
12498c2ecf20Sopenharmony_ci	 * qgroup_ioctl_lock, see btrfs_quota_enable().
12508c2ecf20Sopenharmony_ci	 */
12518c2ecf20Sopenharmony_ci	trans = btrfs_start_transaction(fs_info->tree_root, 1);
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
12548c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
12558c2ecf20Sopenharmony_ci		ret = PTR_ERR(trans);
12568c2ecf20Sopenharmony_ci		trans = NULL;
12578c2ecf20Sopenharmony_ci		set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
12588c2ecf20Sopenharmony_ci		goto out;
12598c2ecf20Sopenharmony_ci	}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
12628c2ecf20Sopenharmony_ci		goto out;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
12658c2ecf20Sopenharmony_ci	quota_root = fs_info->quota_root;
12668c2ecf20Sopenharmony_ci	fs_info->quota_root = NULL;
12678c2ecf20Sopenharmony_ci	fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
12688c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	btrfs_free_qgroup_config(fs_info);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	ret = btrfs_clean_quota_tree(trans, quota_root);
12738c2ecf20Sopenharmony_ci	if (ret) {
12748c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
12758c2ecf20Sopenharmony_ci		goto out;
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	ret = btrfs_del_root(trans, &quota_root->root_key);
12798c2ecf20Sopenharmony_ci	if (ret) {
12808c2ecf20Sopenharmony_ci		btrfs_abort_transaction(trans, ret);
12818c2ecf20Sopenharmony_ci		goto out;
12828c2ecf20Sopenharmony_ci	}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	spin_lock(&fs_info->trans_lock);
12858c2ecf20Sopenharmony_ci	list_del(&quota_root->dirty_list);
12868c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->trans_lock);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	btrfs_tree_lock(quota_root->node);
12898c2ecf20Sopenharmony_ci	btrfs_clean_tree_block(quota_root->node);
12908c2ecf20Sopenharmony_ci	btrfs_tree_unlock(quota_root->node);
12918c2ecf20Sopenharmony_ci	btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ciout:
12958c2ecf20Sopenharmony_ci	btrfs_put_root(quota_root);
12968c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
12978c2ecf20Sopenharmony_ci	if (ret && trans)
12988c2ecf20Sopenharmony_ci		btrfs_end_transaction(trans);
12998c2ecf20Sopenharmony_ci	else if (trans)
13008c2ecf20Sopenharmony_ci		ret = btrfs_end_transaction(trans);
13018c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->cleaner_mutex);
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	return ret;
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic void qgroup_dirty(struct btrfs_fs_info *fs_info,
13078c2ecf20Sopenharmony_ci			 struct btrfs_qgroup *qgroup)
13088c2ecf20Sopenharmony_ci{
13098c2ecf20Sopenharmony_ci	if (list_empty(&qgroup->dirty))
13108c2ecf20Sopenharmony_ci		list_add(&qgroup->dirty, &fs_info->dirty_qgroups);
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/*
13148c2ecf20Sopenharmony_ci * The easy accounting, we're updating qgroup relationship whose child qgroup
13158c2ecf20Sopenharmony_ci * only has exclusive extents.
13168c2ecf20Sopenharmony_ci *
13178c2ecf20Sopenharmony_ci * In this case, all exclusive extents will also be exclusive for parent, so
13188c2ecf20Sopenharmony_ci * excl/rfer just get added/removed.
13198c2ecf20Sopenharmony_ci *
13208c2ecf20Sopenharmony_ci * So is qgroup reservation space, which should also be added/removed to
13218c2ecf20Sopenharmony_ci * parent.
13228c2ecf20Sopenharmony_ci * Or when child tries to release reservation space, parent will underflow its
13238c2ecf20Sopenharmony_ci * reservation (for relationship adding case).
13248c2ecf20Sopenharmony_ci *
13258c2ecf20Sopenharmony_ci * Caller should hold fs_info->qgroup_lock.
13268c2ecf20Sopenharmony_ci */
13278c2ecf20Sopenharmony_cistatic int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
13288c2ecf20Sopenharmony_ci				    struct ulist *tmp, u64 ref_root,
13298c2ecf20Sopenharmony_ci				    struct btrfs_qgroup *src, int sign)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
13328c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *glist;
13338c2ecf20Sopenharmony_ci	struct ulist_node *unode;
13348c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
13358c2ecf20Sopenharmony_ci	u64 num_bytes = src->excl;
13368c2ecf20Sopenharmony_ci	int ret = 0;
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, ref_root);
13398c2ecf20Sopenharmony_ci	if (!qgroup)
13408c2ecf20Sopenharmony_ci		goto out;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	qgroup->rfer += sign * num_bytes;
13438c2ecf20Sopenharmony_ci	qgroup->rfer_cmpr += sign * num_bytes;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	WARN_ON(sign < 0 && qgroup->excl < num_bytes);
13468c2ecf20Sopenharmony_ci	qgroup->excl += sign * num_bytes;
13478c2ecf20Sopenharmony_ci	qgroup->excl_cmpr += sign * num_bytes;
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	if (sign > 0)
13508c2ecf20Sopenharmony_ci		qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
13518c2ecf20Sopenharmony_ci	else
13528c2ecf20Sopenharmony_ci		qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	qgroup_dirty(fs_info, qgroup);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	/* Get all of the parent groups that contain this qgroup */
13578c2ecf20Sopenharmony_ci	list_for_each_entry(glist, &qgroup->groups, next_group) {
13588c2ecf20Sopenharmony_ci		ret = ulist_add(tmp, glist->group->qgroupid,
13598c2ecf20Sopenharmony_ci				qgroup_to_aux(glist->group), GFP_ATOMIC);
13608c2ecf20Sopenharmony_ci		if (ret < 0)
13618c2ecf20Sopenharmony_ci			goto out;
13628c2ecf20Sopenharmony_ci	}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	/* Iterate all of the parents and adjust their reference counts */
13658c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
13668c2ecf20Sopenharmony_ci	while ((unode = ulist_next(tmp, &uiter))) {
13678c2ecf20Sopenharmony_ci		qgroup = unode_aux_to_qgroup(unode);
13688c2ecf20Sopenharmony_ci		qgroup->rfer += sign * num_bytes;
13698c2ecf20Sopenharmony_ci		qgroup->rfer_cmpr += sign * num_bytes;
13708c2ecf20Sopenharmony_ci		WARN_ON(sign < 0 && qgroup->excl < num_bytes);
13718c2ecf20Sopenharmony_ci		qgroup->excl += sign * num_bytes;
13728c2ecf20Sopenharmony_ci		if (sign > 0)
13738c2ecf20Sopenharmony_ci			qgroup_rsv_add_by_qgroup(fs_info, qgroup, src);
13748c2ecf20Sopenharmony_ci		else
13758c2ecf20Sopenharmony_ci			qgroup_rsv_release_by_qgroup(fs_info, qgroup, src);
13768c2ecf20Sopenharmony_ci		qgroup->excl_cmpr += sign * num_bytes;
13778c2ecf20Sopenharmony_ci		qgroup_dirty(fs_info, qgroup);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci		/* Add any parents of the parents */
13808c2ecf20Sopenharmony_ci		list_for_each_entry(glist, &qgroup->groups, next_group) {
13818c2ecf20Sopenharmony_ci			ret = ulist_add(tmp, glist->group->qgroupid,
13828c2ecf20Sopenharmony_ci					qgroup_to_aux(glist->group), GFP_ATOMIC);
13838c2ecf20Sopenharmony_ci			if (ret < 0)
13848c2ecf20Sopenharmony_ci				goto out;
13858c2ecf20Sopenharmony_ci		}
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci	ret = 0;
13888c2ecf20Sopenharmony_ciout:
13898c2ecf20Sopenharmony_ci	return ret;
13908c2ecf20Sopenharmony_ci}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci/*
13948c2ecf20Sopenharmony_ci * Quick path for updating qgroup with only excl refs.
13958c2ecf20Sopenharmony_ci *
13968c2ecf20Sopenharmony_ci * In that case, just update all parent will be enough.
13978c2ecf20Sopenharmony_ci * Or we needs to do a full rescan.
13988c2ecf20Sopenharmony_ci * Caller should also hold fs_info->qgroup_lock.
13998c2ecf20Sopenharmony_ci *
14008c2ecf20Sopenharmony_ci * Return 0 for quick update, return >0 for need to full rescan
14018c2ecf20Sopenharmony_ci * and mark INCONSISTENT flag.
14028c2ecf20Sopenharmony_ci * Return < 0 for other error.
14038c2ecf20Sopenharmony_ci */
14048c2ecf20Sopenharmony_cistatic int quick_update_accounting(struct btrfs_fs_info *fs_info,
14058c2ecf20Sopenharmony_ci				   struct ulist *tmp, u64 src, u64 dst,
14068c2ecf20Sopenharmony_ci				   int sign)
14078c2ecf20Sopenharmony_ci{
14088c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
14098c2ecf20Sopenharmony_ci	int ret = 1;
14108c2ecf20Sopenharmony_ci	int err = 0;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, src);
14138c2ecf20Sopenharmony_ci	if (!qgroup)
14148c2ecf20Sopenharmony_ci		goto out;
14158c2ecf20Sopenharmony_ci	if (qgroup->excl == qgroup->rfer) {
14168c2ecf20Sopenharmony_ci		ret = 0;
14178c2ecf20Sopenharmony_ci		err = __qgroup_excl_accounting(fs_info, tmp, dst,
14188c2ecf20Sopenharmony_ci					       qgroup, sign);
14198c2ecf20Sopenharmony_ci		if (err < 0) {
14208c2ecf20Sopenharmony_ci			ret = err;
14218c2ecf20Sopenharmony_ci			goto out;
14228c2ecf20Sopenharmony_ci		}
14238c2ecf20Sopenharmony_ci	}
14248c2ecf20Sopenharmony_ciout:
14258c2ecf20Sopenharmony_ci	if (ret)
14268c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
14278c2ecf20Sopenharmony_ci	return ret;
14288c2ecf20Sopenharmony_ci}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ciint btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
14318c2ecf20Sopenharmony_ci			      u64 dst)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
14348c2ecf20Sopenharmony_ci	struct btrfs_qgroup *parent;
14358c2ecf20Sopenharmony_ci	struct btrfs_qgroup *member;
14368c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
14378c2ecf20Sopenharmony_ci	struct ulist *tmp;
14388c2ecf20Sopenharmony_ci	unsigned int nofs_flag;
14398c2ecf20Sopenharmony_ci	int ret = 0;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	/* Check the level of src and dst first */
14428c2ecf20Sopenharmony_ci	if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst))
14438c2ecf20Sopenharmony_ci		return -EINVAL;
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	/* We hold a transaction handle open, must do a NOFS allocation. */
14468c2ecf20Sopenharmony_ci	nofs_flag = memalloc_nofs_save();
14478c2ecf20Sopenharmony_ci	tmp = ulist_alloc(GFP_KERNEL);
14488c2ecf20Sopenharmony_ci	memalloc_nofs_restore(nofs_flag);
14498c2ecf20Sopenharmony_ci	if (!tmp)
14508c2ecf20Sopenharmony_ci		return -ENOMEM;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
14538c2ecf20Sopenharmony_ci	if (!fs_info->quota_root) {
14548c2ecf20Sopenharmony_ci		ret = -ENOTCONN;
14558c2ecf20Sopenharmony_ci		goto out;
14568c2ecf20Sopenharmony_ci	}
14578c2ecf20Sopenharmony_ci	member = find_qgroup_rb(fs_info, src);
14588c2ecf20Sopenharmony_ci	parent = find_qgroup_rb(fs_info, dst);
14598c2ecf20Sopenharmony_ci	if (!member || !parent) {
14608c2ecf20Sopenharmony_ci		ret = -EINVAL;
14618c2ecf20Sopenharmony_ci		goto out;
14628c2ecf20Sopenharmony_ci	}
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	/* check if such qgroup relation exist firstly */
14658c2ecf20Sopenharmony_ci	list_for_each_entry(list, &member->groups, next_group) {
14668c2ecf20Sopenharmony_ci		if (list->group == parent) {
14678c2ecf20Sopenharmony_ci			ret = -EEXIST;
14688c2ecf20Sopenharmony_ci			goto out;
14698c2ecf20Sopenharmony_ci		}
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	ret = add_qgroup_relation_item(trans, src, dst);
14738c2ecf20Sopenharmony_ci	if (ret)
14748c2ecf20Sopenharmony_ci		goto out;
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci	ret = add_qgroup_relation_item(trans, dst, src);
14778c2ecf20Sopenharmony_ci	if (ret) {
14788c2ecf20Sopenharmony_ci		del_qgroup_relation_item(trans, src, dst);
14798c2ecf20Sopenharmony_ci		goto out;
14808c2ecf20Sopenharmony_ci	}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
14838c2ecf20Sopenharmony_ci	ret = add_relation_rb(fs_info, src, dst);
14848c2ecf20Sopenharmony_ci	if (ret < 0) {
14858c2ecf20Sopenharmony_ci		spin_unlock(&fs_info->qgroup_lock);
14868c2ecf20Sopenharmony_ci		goto out;
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci	ret = quick_update_accounting(fs_info, tmp, src, dst, 1);
14898c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
14908c2ecf20Sopenharmony_ciout:
14918c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
14928c2ecf20Sopenharmony_ci	ulist_free(tmp);
14938c2ecf20Sopenharmony_ci	return ret;
14948c2ecf20Sopenharmony_ci}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_cistatic int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
14978c2ecf20Sopenharmony_ci				 u64 dst)
14988c2ecf20Sopenharmony_ci{
14998c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
15008c2ecf20Sopenharmony_ci	struct btrfs_qgroup *parent;
15018c2ecf20Sopenharmony_ci	struct btrfs_qgroup *member;
15028c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
15038c2ecf20Sopenharmony_ci	struct ulist *tmp;
15048c2ecf20Sopenharmony_ci	bool found = false;
15058c2ecf20Sopenharmony_ci	unsigned int nofs_flag;
15068c2ecf20Sopenharmony_ci	int ret = 0;
15078c2ecf20Sopenharmony_ci	int ret2;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	/* We hold a transaction handle open, must do a NOFS allocation. */
15108c2ecf20Sopenharmony_ci	nofs_flag = memalloc_nofs_save();
15118c2ecf20Sopenharmony_ci	tmp = ulist_alloc(GFP_KERNEL);
15128c2ecf20Sopenharmony_ci	memalloc_nofs_restore(nofs_flag);
15138c2ecf20Sopenharmony_ci	if (!tmp)
15148c2ecf20Sopenharmony_ci		return -ENOMEM;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	if (!fs_info->quota_root) {
15178c2ecf20Sopenharmony_ci		ret = -ENOTCONN;
15188c2ecf20Sopenharmony_ci		goto out;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	member = find_qgroup_rb(fs_info, src);
15228c2ecf20Sopenharmony_ci	parent = find_qgroup_rb(fs_info, dst);
15238c2ecf20Sopenharmony_ci	/*
15248c2ecf20Sopenharmony_ci	 * The parent/member pair doesn't exist, then try to delete the dead
15258c2ecf20Sopenharmony_ci	 * relation items only.
15268c2ecf20Sopenharmony_ci	 */
15278c2ecf20Sopenharmony_ci	if (!member || !parent)
15288c2ecf20Sopenharmony_ci		goto delete_item;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	/* check if such qgroup relation exist firstly */
15318c2ecf20Sopenharmony_ci	list_for_each_entry(list, &member->groups, next_group) {
15328c2ecf20Sopenharmony_ci		if (list->group == parent) {
15338c2ecf20Sopenharmony_ci			found = true;
15348c2ecf20Sopenharmony_ci			break;
15358c2ecf20Sopenharmony_ci		}
15368c2ecf20Sopenharmony_ci	}
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_cidelete_item:
15398c2ecf20Sopenharmony_ci	ret = del_qgroup_relation_item(trans, src, dst);
15408c2ecf20Sopenharmony_ci	if (ret < 0 && ret != -ENOENT)
15418c2ecf20Sopenharmony_ci		goto out;
15428c2ecf20Sopenharmony_ci	ret2 = del_qgroup_relation_item(trans, dst, src);
15438c2ecf20Sopenharmony_ci	if (ret2 < 0 && ret2 != -ENOENT)
15448c2ecf20Sopenharmony_ci		goto out;
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	/* At least one deletion succeeded, return 0 */
15478c2ecf20Sopenharmony_ci	if (!ret || !ret2)
15488c2ecf20Sopenharmony_ci		ret = 0;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	if (found) {
15518c2ecf20Sopenharmony_ci		spin_lock(&fs_info->qgroup_lock);
15528c2ecf20Sopenharmony_ci		del_relation_rb(fs_info, src, dst);
15538c2ecf20Sopenharmony_ci		ret = quick_update_accounting(fs_info, tmp, src, dst, -1);
15548c2ecf20Sopenharmony_ci		spin_unlock(&fs_info->qgroup_lock);
15558c2ecf20Sopenharmony_ci	}
15568c2ecf20Sopenharmony_ciout:
15578c2ecf20Sopenharmony_ci	ulist_free(tmp);
15588c2ecf20Sopenharmony_ci	return ret;
15598c2ecf20Sopenharmony_ci}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ciint btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src,
15628c2ecf20Sopenharmony_ci			      u64 dst)
15638c2ecf20Sopenharmony_ci{
15648c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
15658c2ecf20Sopenharmony_ci	int ret = 0;
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
15688c2ecf20Sopenharmony_ci	ret = __del_qgroup_relation(trans, src, dst);
15698c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	return ret;
15728c2ecf20Sopenharmony_ci}
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ciint btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
15758c2ecf20Sopenharmony_ci{
15768c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
15778c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root;
15788c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
15798c2ecf20Sopenharmony_ci	int ret = 0;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
15828c2ecf20Sopenharmony_ci	if (!fs_info->quota_root) {
15838c2ecf20Sopenharmony_ci		ret = -ENOTCONN;
15848c2ecf20Sopenharmony_ci		goto out;
15858c2ecf20Sopenharmony_ci	}
15868c2ecf20Sopenharmony_ci	quota_root = fs_info->quota_root;
15878c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, qgroupid);
15888c2ecf20Sopenharmony_ci	if (qgroup) {
15898c2ecf20Sopenharmony_ci		ret = -EEXIST;
15908c2ecf20Sopenharmony_ci		goto out;
15918c2ecf20Sopenharmony_ci	}
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	ret = add_qgroup_item(trans, quota_root, qgroupid);
15948c2ecf20Sopenharmony_ci	if (ret)
15958c2ecf20Sopenharmony_ci		goto out;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
15988c2ecf20Sopenharmony_ci	qgroup = add_qgroup_rb(fs_info, qgroupid);
15998c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	if (IS_ERR(qgroup)) {
16028c2ecf20Sopenharmony_ci		ret = PTR_ERR(qgroup);
16038c2ecf20Sopenharmony_ci		goto out;
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci	ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
16068c2ecf20Sopenharmony_ciout:
16078c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
16088c2ecf20Sopenharmony_ci	return ret;
16098c2ecf20Sopenharmony_ci}
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cistatic bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
16148c2ecf20Sopenharmony_ci		qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
16158c2ecf20Sopenharmony_ci		qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
16168c2ecf20Sopenharmony_ci		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
16178c2ecf20Sopenharmony_ci		qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ciint btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
16218c2ecf20Sopenharmony_ci{
16228c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
16238c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
16248c2ecf20Sopenharmony_ci	struct btrfs_qgroup_list *list;
16258c2ecf20Sopenharmony_ci	int ret = 0;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
16288c2ecf20Sopenharmony_ci	if (!fs_info->quota_root) {
16298c2ecf20Sopenharmony_ci		ret = -ENOTCONN;
16308c2ecf20Sopenharmony_ci		goto out;
16318c2ecf20Sopenharmony_ci	}
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, qgroupid);
16348c2ecf20Sopenharmony_ci	if (!qgroup) {
16358c2ecf20Sopenharmony_ci		ret = -ENOENT;
16368c2ecf20Sopenharmony_ci		goto out;
16378c2ecf20Sopenharmony_ci	}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
16408c2ecf20Sopenharmony_ci		ret = -EBUSY;
16418c2ecf20Sopenharmony_ci		goto out;
16428c2ecf20Sopenharmony_ci	}
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	/* Check if there are no children of this qgroup */
16458c2ecf20Sopenharmony_ci	if (!list_empty(&qgroup->members)) {
16468c2ecf20Sopenharmony_ci		ret = -EBUSY;
16478c2ecf20Sopenharmony_ci		goto out;
16488c2ecf20Sopenharmony_ci	}
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	ret = del_qgroup_item(trans, qgroupid);
16518c2ecf20Sopenharmony_ci	if (ret && ret != -ENOENT)
16528c2ecf20Sopenharmony_ci		goto out;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	while (!list_empty(&qgroup->groups)) {
16558c2ecf20Sopenharmony_ci		list = list_first_entry(&qgroup->groups,
16568c2ecf20Sopenharmony_ci					struct btrfs_qgroup_list, next_group);
16578c2ecf20Sopenharmony_ci		ret = __del_qgroup_relation(trans, qgroupid,
16588c2ecf20Sopenharmony_ci					    list->group->qgroupid);
16598c2ecf20Sopenharmony_ci		if (ret)
16608c2ecf20Sopenharmony_ci			goto out;
16618c2ecf20Sopenharmony_ci	}
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
16648c2ecf20Sopenharmony_ci	del_qgroup_rb(fs_info, qgroupid);
16658c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	/*
16688c2ecf20Sopenharmony_ci	 * Remove the qgroup from sysfs now without holding the qgroup_lock
16698c2ecf20Sopenharmony_ci	 * spinlock, since the sysfs_remove_group() function needs to take
16708c2ecf20Sopenharmony_ci	 * the mutex kernfs_mutex through kernfs_remove_by_name_ns().
16718c2ecf20Sopenharmony_ci	 */
16728c2ecf20Sopenharmony_ci	btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
16738c2ecf20Sopenharmony_ci	kfree(qgroup);
16748c2ecf20Sopenharmony_ciout:
16758c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
16768c2ecf20Sopenharmony_ci	return ret;
16778c2ecf20Sopenharmony_ci}
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ciint btrfs_limit_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid,
16808c2ecf20Sopenharmony_ci		       struct btrfs_qgroup_limit *limit)
16818c2ecf20Sopenharmony_ci{
16828c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
16838c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
16848c2ecf20Sopenharmony_ci	int ret = 0;
16858c2ecf20Sopenharmony_ci	/* Sometimes we would want to clear the limit on this qgroup.
16868c2ecf20Sopenharmony_ci	 * To meet this requirement, we treat the -1 as a special value
16878c2ecf20Sopenharmony_ci	 * which tell kernel to clear the limit on this qgroup.
16888c2ecf20Sopenharmony_ci	 */
16898c2ecf20Sopenharmony_ci	const u64 CLEAR_VALUE = -1;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_ioctl_lock);
16928c2ecf20Sopenharmony_ci	if (!fs_info->quota_root) {
16938c2ecf20Sopenharmony_ci		ret = -ENOTCONN;
16948c2ecf20Sopenharmony_ci		goto out;
16958c2ecf20Sopenharmony_ci	}
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, qgroupid);
16988c2ecf20Sopenharmony_ci	if (!qgroup) {
16998c2ecf20Sopenharmony_ci		ret = -ENOENT;
17008c2ecf20Sopenharmony_ci		goto out;
17018c2ecf20Sopenharmony_ci	}
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
17048c2ecf20Sopenharmony_ci	if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) {
17058c2ecf20Sopenharmony_ci		if (limit->max_rfer == CLEAR_VALUE) {
17068c2ecf20Sopenharmony_ci			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER;
17078c2ecf20Sopenharmony_ci			limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER;
17088c2ecf20Sopenharmony_ci			qgroup->max_rfer = 0;
17098c2ecf20Sopenharmony_ci		} else {
17108c2ecf20Sopenharmony_ci			qgroup->max_rfer = limit->max_rfer;
17118c2ecf20Sopenharmony_ci		}
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci	if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) {
17148c2ecf20Sopenharmony_ci		if (limit->max_excl == CLEAR_VALUE) {
17158c2ecf20Sopenharmony_ci			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL;
17168c2ecf20Sopenharmony_ci			limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL;
17178c2ecf20Sopenharmony_ci			qgroup->max_excl = 0;
17188c2ecf20Sopenharmony_ci		} else {
17198c2ecf20Sopenharmony_ci			qgroup->max_excl = limit->max_excl;
17208c2ecf20Sopenharmony_ci		}
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci	if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) {
17238c2ecf20Sopenharmony_ci		if (limit->rsv_rfer == CLEAR_VALUE) {
17248c2ecf20Sopenharmony_ci			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER;
17258c2ecf20Sopenharmony_ci			limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER;
17268c2ecf20Sopenharmony_ci			qgroup->rsv_rfer = 0;
17278c2ecf20Sopenharmony_ci		} else {
17288c2ecf20Sopenharmony_ci			qgroup->rsv_rfer = limit->rsv_rfer;
17298c2ecf20Sopenharmony_ci		}
17308c2ecf20Sopenharmony_ci	}
17318c2ecf20Sopenharmony_ci	if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) {
17328c2ecf20Sopenharmony_ci		if (limit->rsv_excl == CLEAR_VALUE) {
17338c2ecf20Sopenharmony_ci			qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL;
17348c2ecf20Sopenharmony_ci			limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL;
17358c2ecf20Sopenharmony_ci			qgroup->rsv_excl = 0;
17368c2ecf20Sopenharmony_ci		} else {
17378c2ecf20Sopenharmony_ci			qgroup->rsv_excl = limit->rsv_excl;
17388c2ecf20Sopenharmony_ci		}
17398c2ecf20Sopenharmony_ci	}
17408c2ecf20Sopenharmony_ci	qgroup->lim_flags |= limit->flags;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	ret = update_qgroup_limit_item(trans, qgroup);
17458c2ecf20Sopenharmony_ci	if (ret) {
17468c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
17478c2ecf20Sopenharmony_ci		btrfs_info(fs_info, "unable to update quota limit for %llu",
17488c2ecf20Sopenharmony_ci		       qgroupid);
17498c2ecf20Sopenharmony_ci	}
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ciout:
17528c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_ioctl_lock);
17538c2ecf20Sopenharmony_ci	return ret;
17548c2ecf20Sopenharmony_ci}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
17578c2ecf20Sopenharmony_ci				struct btrfs_delayed_ref_root *delayed_refs,
17588c2ecf20Sopenharmony_ci				struct btrfs_qgroup_extent_record *record)
17598c2ecf20Sopenharmony_ci{
17608c2ecf20Sopenharmony_ci	struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
17618c2ecf20Sopenharmony_ci	struct rb_node *parent_node = NULL;
17628c2ecf20Sopenharmony_ci	struct btrfs_qgroup_extent_record *entry;
17638c2ecf20Sopenharmony_ci	u64 bytenr = record->bytenr;
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	lockdep_assert_held(&delayed_refs->lock);
17668c2ecf20Sopenharmony_ci	trace_btrfs_qgroup_trace_extent(fs_info, record);
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	while (*p) {
17698c2ecf20Sopenharmony_ci		parent_node = *p;
17708c2ecf20Sopenharmony_ci		entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,
17718c2ecf20Sopenharmony_ci				 node);
17728c2ecf20Sopenharmony_ci		if (bytenr < entry->bytenr) {
17738c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
17748c2ecf20Sopenharmony_ci		} else if (bytenr > entry->bytenr) {
17758c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
17768c2ecf20Sopenharmony_ci		} else {
17778c2ecf20Sopenharmony_ci			if (record->data_rsv && !entry->data_rsv) {
17788c2ecf20Sopenharmony_ci				entry->data_rsv = record->data_rsv;
17798c2ecf20Sopenharmony_ci				entry->data_rsv_refroot =
17808c2ecf20Sopenharmony_ci					record->data_rsv_refroot;
17818c2ecf20Sopenharmony_ci			}
17828c2ecf20Sopenharmony_ci			return 1;
17838c2ecf20Sopenharmony_ci		}
17848c2ecf20Sopenharmony_ci	}
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci	rb_link_node(&record->node, parent_node, p);
17878c2ecf20Sopenharmony_ci	rb_insert_color(&record->node, &delayed_refs->dirty_extent_root);
17888c2ecf20Sopenharmony_ci	return 0;
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_extent_post(struct btrfs_fs_info *fs_info,
17928c2ecf20Sopenharmony_ci				   struct btrfs_qgroup_extent_record *qrecord)
17938c2ecf20Sopenharmony_ci{
17948c2ecf20Sopenharmony_ci	struct ulist *old_root;
17958c2ecf20Sopenharmony_ci	u64 bytenr = qrecord->bytenr;
17968c2ecf20Sopenharmony_ci	int ret;
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	ret = btrfs_find_all_roots(NULL, fs_info, bytenr, 0, &old_root, false);
17998c2ecf20Sopenharmony_ci	if (ret < 0) {
18008c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
18018c2ecf20Sopenharmony_ci		btrfs_warn(fs_info,
18028c2ecf20Sopenharmony_ci"error accounting new delayed refs extent (err code: %d), quota inconsistent",
18038c2ecf20Sopenharmony_ci			ret);
18048c2ecf20Sopenharmony_ci		return 0;
18058c2ecf20Sopenharmony_ci	}
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	/*
18088c2ecf20Sopenharmony_ci	 * Here we don't need to get the lock of
18098c2ecf20Sopenharmony_ci	 * trans->transaction->delayed_refs, since inserted qrecord won't
18108c2ecf20Sopenharmony_ci	 * be deleted, only qrecord->node may be modified (new qrecord insert)
18118c2ecf20Sopenharmony_ci	 *
18128c2ecf20Sopenharmony_ci	 * So modifying qrecord->old_roots is safe here
18138c2ecf20Sopenharmony_ci	 */
18148c2ecf20Sopenharmony_ci	qrecord->old_roots = old_root;
18158c2ecf20Sopenharmony_ci	return 0;
18168c2ecf20Sopenharmony_ci}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
18198c2ecf20Sopenharmony_ci			      u64 num_bytes, gfp_t gfp_flag)
18208c2ecf20Sopenharmony_ci{
18218c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
18228c2ecf20Sopenharmony_ci	struct btrfs_qgroup_extent_record *record;
18238c2ecf20Sopenharmony_ci	struct btrfs_delayed_ref_root *delayed_refs;
18248c2ecf20Sopenharmony_ci	int ret;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)
18278c2ecf20Sopenharmony_ci	    || bytenr == 0 || num_bytes == 0)
18288c2ecf20Sopenharmony_ci		return 0;
18298c2ecf20Sopenharmony_ci	record = kzalloc(sizeof(*record), gfp_flag);
18308c2ecf20Sopenharmony_ci	if (!record)
18318c2ecf20Sopenharmony_ci		return -ENOMEM;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	delayed_refs = &trans->transaction->delayed_refs;
18348c2ecf20Sopenharmony_ci	record->bytenr = bytenr;
18358c2ecf20Sopenharmony_ci	record->num_bytes = num_bytes;
18368c2ecf20Sopenharmony_ci	record->old_roots = NULL;
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	spin_lock(&delayed_refs->lock);
18398c2ecf20Sopenharmony_ci	ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, record);
18408c2ecf20Sopenharmony_ci	spin_unlock(&delayed_refs->lock);
18418c2ecf20Sopenharmony_ci	if (ret > 0) {
18428c2ecf20Sopenharmony_ci		kfree(record);
18438c2ecf20Sopenharmony_ci		return 0;
18448c2ecf20Sopenharmony_ci	}
18458c2ecf20Sopenharmony_ci	return btrfs_qgroup_trace_extent_post(fs_info, record);
18468c2ecf20Sopenharmony_ci}
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_leaf_items(struct btrfs_trans_handle *trans,
18498c2ecf20Sopenharmony_ci				  struct extent_buffer *eb)
18508c2ecf20Sopenharmony_ci{
18518c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
18528c2ecf20Sopenharmony_ci	int nr = btrfs_header_nritems(eb);
18538c2ecf20Sopenharmony_ci	int i, extent_type, ret;
18548c2ecf20Sopenharmony_ci	struct btrfs_key key;
18558c2ecf20Sopenharmony_ci	struct btrfs_file_extent_item *fi;
18568c2ecf20Sopenharmony_ci	u64 bytenr, num_bytes;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	/* We can be called directly from walk_up_proc() */
18598c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
18608c2ecf20Sopenharmony_ci		return 0;
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	for (i = 0; i < nr; i++) {
18638c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(eb, &key, i);
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci		if (key.type != BTRFS_EXTENT_DATA_KEY)
18668c2ecf20Sopenharmony_ci			continue;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci		fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item);
18698c2ecf20Sopenharmony_ci		/* filter out non qgroup-accountable extents  */
18708c2ecf20Sopenharmony_ci		extent_type = btrfs_file_extent_type(eb, fi);
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci		if (extent_type == BTRFS_FILE_EXTENT_INLINE)
18738c2ecf20Sopenharmony_ci			continue;
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci		bytenr = btrfs_file_extent_disk_bytenr(eb, fi);
18768c2ecf20Sopenharmony_ci		if (!bytenr)
18778c2ecf20Sopenharmony_ci			continue;
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci		num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci		ret = btrfs_qgroup_trace_extent(trans, bytenr, num_bytes,
18828c2ecf20Sopenharmony_ci						GFP_NOFS);
18838c2ecf20Sopenharmony_ci		if (ret)
18848c2ecf20Sopenharmony_ci			return ret;
18858c2ecf20Sopenharmony_ci	}
18868c2ecf20Sopenharmony_ci	cond_resched();
18878c2ecf20Sopenharmony_ci	return 0;
18888c2ecf20Sopenharmony_ci}
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci/*
18918c2ecf20Sopenharmony_ci * Walk up the tree from the bottom, freeing leaves and any interior
18928c2ecf20Sopenharmony_ci * nodes which have had all slots visited. If a node (leaf or
18938c2ecf20Sopenharmony_ci * interior) is freed, the node above it will have it's slot
18948c2ecf20Sopenharmony_ci * incremented. The root node will never be freed.
18958c2ecf20Sopenharmony_ci *
18968c2ecf20Sopenharmony_ci * At the end of this function, we should have a path which has all
18978c2ecf20Sopenharmony_ci * slots incremented to the next position for a search. If we need to
18988c2ecf20Sopenharmony_ci * read a new node it will be NULL and the node above it will have the
18998c2ecf20Sopenharmony_ci * correct slot selected for a later read.
19008c2ecf20Sopenharmony_ci *
19018c2ecf20Sopenharmony_ci * If we increment the root nodes slot counter past the number of
19028c2ecf20Sopenharmony_ci * elements, 1 is returned to signal completion of the search.
19038c2ecf20Sopenharmony_ci */
19048c2ecf20Sopenharmony_cistatic int adjust_slots_upwards(struct btrfs_path *path, int root_level)
19058c2ecf20Sopenharmony_ci{
19068c2ecf20Sopenharmony_ci	int level = 0;
19078c2ecf20Sopenharmony_ci	int nr, slot;
19088c2ecf20Sopenharmony_ci	struct extent_buffer *eb;
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ci	if (root_level == 0)
19118c2ecf20Sopenharmony_ci		return 1;
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	while (level <= root_level) {
19148c2ecf20Sopenharmony_ci		eb = path->nodes[level];
19158c2ecf20Sopenharmony_ci		nr = btrfs_header_nritems(eb);
19168c2ecf20Sopenharmony_ci		path->slots[level]++;
19178c2ecf20Sopenharmony_ci		slot = path->slots[level];
19188c2ecf20Sopenharmony_ci		if (slot >= nr || level == 0) {
19198c2ecf20Sopenharmony_ci			/*
19208c2ecf20Sopenharmony_ci			 * Don't free the root -  we will detect this
19218c2ecf20Sopenharmony_ci			 * condition after our loop and return a
19228c2ecf20Sopenharmony_ci			 * positive value for caller to stop walking the tree.
19238c2ecf20Sopenharmony_ci			 */
19248c2ecf20Sopenharmony_ci			if (level != root_level) {
19258c2ecf20Sopenharmony_ci				btrfs_tree_unlock_rw(eb, path->locks[level]);
19268c2ecf20Sopenharmony_ci				path->locks[level] = 0;
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci				free_extent_buffer(eb);
19298c2ecf20Sopenharmony_ci				path->nodes[level] = NULL;
19308c2ecf20Sopenharmony_ci				path->slots[level] = 0;
19318c2ecf20Sopenharmony_ci			}
19328c2ecf20Sopenharmony_ci		} else {
19338c2ecf20Sopenharmony_ci			/*
19348c2ecf20Sopenharmony_ci			 * We have a valid slot to walk back down
19358c2ecf20Sopenharmony_ci			 * from. Stop here so caller can process these
19368c2ecf20Sopenharmony_ci			 * new nodes.
19378c2ecf20Sopenharmony_ci			 */
19388c2ecf20Sopenharmony_ci			break;
19398c2ecf20Sopenharmony_ci		}
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci		level++;
19428c2ecf20Sopenharmony_ci	}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	eb = path->nodes[root_level];
19458c2ecf20Sopenharmony_ci	if (path->slots[root_level] >= btrfs_header_nritems(eb))
19468c2ecf20Sopenharmony_ci		return 1;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	return 0;
19498c2ecf20Sopenharmony_ci}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci/*
19528c2ecf20Sopenharmony_ci * Helper function to trace a subtree tree block swap.
19538c2ecf20Sopenharmony_ci *
19548c2ecf20Sopenharmony_ci * The swap will happen in highest tree block, but there may be a lot of
19558c2ecf20Sopenharmony_ci * tree blocks involved.
19568c2ecf20Sopenharmony_ci *
19578c2ecf20Sopenharmony_ci * For example:
19588c2ecf20Sopenharmony_ci *  OO = Old tree blocks
19598c2ecf20Sopenharmony_ci *  NN = New tree blocks allocated during balance
19608c2ecf20Sopenharmony_ci *
19618c2ecf20Sopenharmony_ci *           File tree (257)                  Reloc tree for 257
19628c2ecf20Sopenharmony_ci * L2              OO                                NN
19638c2ecf20Sopenharmony_ci *               /    \                            /    \
19648c2ecf20Sopenharmony_ci * L1          OO      OO (a)                    OO      NN (a)
19658c2ecf20Sopenharmony_ci *            / \     / \                       / \     / \
19668c2ecf20Sopenharmony_ci * L0       OO   OO OO   OO                   OO   OO NN   NN
19678c2ecf20Sopenharmony_ci *                  (b)  (c)                          (b)  (c)
19688c2ecf20Sopenharmony_ci *
19698c2ecf20Sopenharmony_ci * When calling qgroup_trace_extent_swap(), we will pass:
19708c2ecf20Sopenharmony_ci * @src_eb = OO(a)
19718c2ecf20Sopenharmony_ci * @dst_path = [ nodes[1] = NN(a), nodes[0] = NN(c) ]
19728c2ecf20Sopenharmony_ci * @dst_level = 0
19738c2ecf20Sopenharmony_ci * @root_level = 1
19748c2ecf20Sopenharmony_ci *
19758c2ecf20Sopenharmony_ci * In that case, qgroup_trace_extent_swap() will search from OO(a) to
19768c2ecf20Sopenharmony_ci * reach OO(c), then mark both OO(c) and NN(c) as qgroup dirty.
19778c2ecf20Sopenharmony_ci *
19788c2ecf20Sopenharmony_ci * The main work of qgroup_trace_extent_swap() can be split into 3 parts:
19798c2ecf20Sopenharmony_ci *
19808c2ecf20Sopenharmony_ci * 1) Tree search from @src_eb
19818c2ecf20Sopenharmony_ci *    It should acts as a simplified btrfs_search_slot().
19828c2ecf20Sopenharmony_ci *    The key for search can be extracted from @dst_path->nodes[dst_level]
19838c2ecf20Sopenharmony_ci *    (first key).
19848c2ecf20Sopenharmony_ci *
19858c2ecf20Sopenharmony_ci * 2) Mark the final tree blocks in @src_path and @dst_path qgroup dirty
19868c2ecf20Sopenharmony_ci *    NOTE: In above case, OO(a) and NN(a) won't be marked qgroup dirty.
19878c2ecf20Sopenharmony_ci *    They should be marked during previous (@dst_level = 1) iteration.
19888c2ecf20Sopenharmony_ci *
19898c2ecf20Sopenharmony_ci * 3) Mark file extents in leaves dirty
19908c2ecf20Sopenharmony_ci *    We don't have good way to pick out new file extents only.
19918c2ecf20Sopenharmony_ci *    So we still follow the old method by scanning all file extents in
19928c2ecf20Sopenharmony_ci *    the leave.
19938c2ecf20Sopenharmony_ci *
19948c2ecf20Sopenharmony_ci * This function can free us from keeping two paths, thus later we only need
19958c2ecf20Sopenharmony_ci * to care about how to iterate all new tree blocks in reloc tree.
19968c2ecf20Sopenharmony_ci */
19978c2ecf20Sopenharmony_cistatic int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
19988c2ecf20Sopenharmony_ci				    struct extent_buffer *src_eb,
19998c2ecf20Sopenharmony_ci				    struct btrfs_path *dst_path,
20008c2ecf20Sopenharmony_ci				    int dst_level, int root_level,
20018c2ecf20Sopenharmony_ci				    bool trace_leaf)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	struct btrfs_key key;
20048c2ecf20Sopenharmony_ci	struct btrfs_path *src_path;
20058c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
20068c2ecf20Sopenharmony_ci	u32 nodesize = fs_info->nodesize;
20078c2ecf20Sopenharmony_ci	int cur_level = root_level;
20088c2ecf20Sopenharmony_ci	int ret;
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci	BUG_ON(dst_level > root_level);
20118c2ecf20Sopenharmony_ci	/* Level mismatch */
20128c2ecf20Sopenharmony_ci	if (btrfs_header_level(src_eb) != root_level)
20138c2ecf20Sopenharmony_ci		return -EINVAL;
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci	src_path = btrfs_alloc_path();
20168c2ecf20Sopenharmony_ci	if (!src_path) {
20178c2ecf20Sopenharmony_ci		ret = -ENOMEM;
20188c2ecf20Sopenharmony_ci		goto out;
20198c2ecf20Sopenharmony_ci	}
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	if (dst_level)
20228c2ecf20Sopenharmony_ci		btrfs_node_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
20238c2ecf20Sopenharmony_ci	else
20248c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci	/* For src_path */
20278c2ecf20Sopenharmony_ci	atomic_inc(&src_eb->refs);
20288c2ecf20Sopenharmony_ci	src_path->nodes[root_level] = src_eb;
20298c2ecf20Sopenharmony_ci	src_path->slots[root_level] = dst_path->slots[root_level];
20308c2ecf20Sopenharmony_ci	src_path->locks[root_level] = 0;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	/* A simplified version of btrfs_search_slot() */
20338c2ecf20Sopenharmony_ci	while (cur_level >= dst_level) {
20348c2ecf20Sopenharmony_ci		struct btrfs_key src_key;
20358c2ecf20Sopenharmony_ci		struct btrfs_key dst_key;
20368c2ecf20Sopenharmony_ci
20378c2ecf20Sopenharmony_ci		if (src_path->nodes[cur_level] == NULL) {
20388c2ecf20Sopenharmony_ci			struct btrfs_key first_key;
20398c2ecf20Sopenharmony_ci			struct extent_buffer *eb;
20408c2ecf20Sopenharmony_ci			int parent_slot;
20418c2ecf20Sopenharmony_ci			u64 child_gen;
20428c2ecf20Sopenharmony_ci			u64 child_bytenr;
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci			eb = src_path->nodes[cur_level + 1];
20458c2ecf20Sopenharmony_ci			parent_slot = src_path->slots[cur_level + 1];
20468c2ecf20Sopenharmony_ci			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
20478c2ecf20Sopenharmony_ci			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
20488c2ecf20Sopenharmony_ci			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci			eb = read_tree_block(fs_info, child_bytenr, child_gen,
20518c2ecf20Sopenharmony_ci					     cur_level, &first_key);
20528c2ecf20Sopenharmony_ci			if (IS_ERR(eb)) {
20538c2ecf20Sopenharmony_ci				ret = PTR_ERR(eb);
20548c2ecf20Sopenharmony_ci				goto out;
20558c2ecf20Sopenharmony_ci			} else if (!extent_buffer_uptodate(eb)) {
20568c2ecf20Sopenharmony_ci				free_extent_buffer(eb);
20578c2ecf20Sopenharmony_ci				ret = -EIO;
20588c2ecf20Sopenharmony_ci				goto out;
20598c2ecf20Sopenharmony_ci			}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci			src_path->nodes[cur_level] = eb;
20628c2ecf20Sopenharmony_ci
20638c2ecf20Sopenharmony_ci			btrfs_tree_read_lock(eb);
20648c2ecf20Sopenharmony_ci			btrfs_set_lock_blocking_read(eb);
20658c2ecf20Sopenharmony_ci			src_path->locks[cur_level] = BTRFS_READ_LOCK_BLOCKING;
20668c2ecf20Sopenharmony_ci		}
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci		src_path->slots[cur_level] = dst_path->slots[cur_level];
20698c2ecf20Sopenharmony_ci		if (cur_level) {
20708c2ecf20Sopenharmony_ci			btrfs_node_key_to_cpu(dst_path->nodes[cur_level],
20718c2ecf20Sopenharmony_ci					&dst_key, dst_path->slots[cur_level]);
20728c2ecf20Sopenharmony_ci			btrfs_node_key_to_cpu(src_path->nodes[cur_level],
20738c2ecf20Sopenharmony_ci					&src_key, src_path->slots[cur_level]);
20748c2ecf20Sopenharmony_ci		} else {
20758c2ecf20Sopenharmony_ci			btrfs_item_key_to_cpu(dst_path->nodes[cur_level],
20768c2ecf20Sopenharmony_ci					&dst_key, dst_path->slots[cur_level]);
20778c2ecf20Sopenharmony_ci			btrfs_item_key_to_cpu(src_path->nodes[cur_level],
20788c2ecf20Sopenharmony_ci					&src_key, src_path->slots[cur_level]);
20798c2ecf20Sopenharmony_ci		}
20808c2ecf20Sopenharmony_ci		/* Content mismatch, something went wrong */
20818c2ecf20Sopenharmony_ci		if (btrfs_comp_cpu_keys(&dst_key, &src_key)) {
20828c2ecf20Sopenharmony_ci			ret = -ENOENT;
20838c2ecf20Sopenharmony_ci			goto out;
20848c2ecf20Sopenharmony_ci		}
20858c2ecf20Sopenharmony_ci		cur_level--;
20868c2ecf20Sopenharmony_ci	}
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci	/*
20898c2ecf20Sopenharmony_ci	 * Now both @dst_path and @src_path have been populated, record the tree
20908c2ecf20Sopenharmony_ci	 * blocks for qgroup accounting.
20918c2ecf20Sopenharmony_ci	 */
20928c2ecf20Sopenharmony_ci	ret = btrfs_qgroup_trace_extent(trans, src_path->nodes[dst_level]->start,
20938c2ecf20Sopenharmony_ci			nodesize, GFP_NOFS);
20948c2ecf20Sopenharmony_ci	if (ret < 0)
20958c2ecf20Sopenharmony_ci		goto out;
20968c2ecf20Sopenharmony_ci	ret = btrfs_qgroup_trace_extent(trans,
20978c2ecf20Sopenharmony_ci			dst_path->nodes[dst_level]->start,
20988c2ecf20Sopenharmony_ci			nodesize, GFP_NOFS);
20998c2ecf20Sopenharmony_ci	if (ret < 0)
21008c2ecf20Sopenharmony_ci		goto out;
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	/* Record leaf file extents */
21038c2ecf20Sopenharmony_ci	if (dst_level == 0 && trace_leaf) {
21048c2ecf20Sopenharmony_ci		ret = btrfs_qgroup_trace_leaf_items(trans, src_path->nodes[0]);
21058c2ecf20Sopenharmony_ci		if (ret < 0)
21068c2ecf20Sopenharmony_ci			goto out;
21078c2ecf20Sopenharmony_ci		ret = btrfs_qgroup_trace_leaf_items(trans, dst_path->nodes[0]);
21088c2ecf20Sopenharmony_ci	}
21098c2ecf20Sopenharmony_ciout:
21108c2ecf20Sopenharmony_ci	btrfs_free_path(src_path);
21118c2ecf20Sopenharmony_ci	return ret;
21128c2ecf20Sopenharmony_ci}
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci/*
21158c2ecf20Sopenharmony_ci * Helper function to do recursive generation-aware depth-first search, to
21168c2ecf20Sopenharmony_ci * locate all new tree blocks in a subtree of reloc tree.
21178c2ecf20Sopenharmony_ci *
21188c2ecf20Sopenharmony_ci * E.g. (OO = Old tree blocks, NN = New tree blocks, whose gen == last_snapshot)
21198c2ecf20Sopenharmony_ci *         reloc tree
21208c2ecf20Sopenharmony_ci * L2         NN (a)
21218c2ecf20Sopenharmony_ci *          /    \
21228c2ecf20Sopenharmony_ci * L1    OO        NN (b)
21238c2ecf20Sopenharmony_ci *      /  \      /  \
21248c2ecf20Sopenharmony_ci * L0  OO  OO    OO  NN
21258c2ecf20Sopenharmony_ci *               (c) (d)
21268c2ecf20Sopenharmony_ci * If we pass:
21278c2ecf20Sopenharmony_ci * @dst_path = [ nodes[1] = NN(b), nodes[0] = NULL ],
21288c2ecf20Sopenharmony_ci * @cur_level = 1
21298c2ecf20Sopenharmony_ci * @root_level = 1
21308c2ecf20Sopenharmony_ci *
21318c2ecf20Sopenharmony_ci * We will iterate through tree blocks NN(b), NN(d) and info qgroup to trace
21328c2ecf20Sopenharmony_ci * above tree blocks along with their counter parts in file tree.
21338c2ecf20Sopenharmony_ci * While during search, old tree blocks OO(c) will be skipped as tree block swap
21348c2ecf20Sopenharmony_ci * won't affect OO(c).
21358c2ecf20Sopenharmony_ci */
21368c2ecf20Sopenharmony_cistatic int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
21378c2ecf20Sopenharmony_ci					   struct extent_buffer *src_eb,
21388c2ecf20Sopenharmony_ci					   struct btrfs_path *dst_path,
21398c2ecf20Sopenharmony_ci					   int cur_level, int root_level,
21408c2ecf20Sopenharmony_ci					   u64 last_snapshot, bool trace_leaf)
21418c2ecf20Sopenharmony_ci{
21428c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
21438c2ecf20Sopenharmony_ci	struct extent_buffer *eb;
21448c2ecf20Sopenharmony_ci	bool need_cleanup = false;
21458c2ecf20Sopenharmony_ci	int ret = 0;
21468c2ecf20Sopenharmony_ci	int i;
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	/* Level sanity check */
21498c2ecf20Sopenharmony_ci	if (cur_level < 0 || cur_level >= BTRFS_MAX_LEVEL - 1 ||
21508c2ecf20Sopenharmony_ci	    root_level < 0 || root_level >= BTRFS_MAX_LEVEL - 1 ||
21518c2ecf20Sopenharmony_ci	    root_level < cur_level) {
21528c2ecf20Sopenharmony_ci		btrfs_err_rl(fs_info,
21538c2ecf20Sopenharmony_ci			"%s: bad levels, cur_level=%d root_level=%d",
21548c2ecf20Sopenharmony_ci			__func__, cur_level, root_level);
21558c2ecf20Sopenharmony_ci		return -EUCLEAN;
21568c2ecf20Sopenharmony_ci	}
21578c2ecf20Sopenharmony_ci
21588c2ecf20Sopenharmony_ci	/* Read the tree block if needed */
21598c2ecf20Sopenharmony_ci	if (dst_path->nodes[cur_level] == NULL) {
21608c2ecf20Sopenharmony_ci		struct btrfs_key first_key;
21618c2ecf20Sopenharmony_ci		int parent_slot;
21628c2ecf20Sopenharmony_ci		u64 child_gen;
21638c2ecf20Sopenharmony_ci		u64 child_bytenr;
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci		/*
21668c2ecf20Sopenharmony_ci		 * dst_path->nodes[root_level] must be initialized before
21678c2ecf20Sopenharmony_ci		 * calling this function.
21688c2ecf20Sopenharmony_ci		 */
21698c2ecf20Sopenharmony_ci		if (cur_level == root_level) {
21708c2ecf20Sopenharmony_ci			btrfs_err_rl(fs_info,
21718c2ecf20Sopenharmony_ci	"%s: dst_path->nodes[%d] not initialized, root_level=%d cur_level=%d",
21728c2ecf20Sopenharmony_ci				__func__, root_level, root_level, cur_level);
21738c2ecf20Sopenharmony_ci			return -EUCLEAN;
21748c2ecf20Sopenharmony_ci		}
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci		/*
21778c2ecf20Sopenharmony_ci		 * We need to get child blockptr/gen from parent before we can
21788c2ecf20Sopenharmony_ci		 * read it.
21798c2ecf20Sopenharmony_ci		  */
21808c2ecf20Sopenharmony_ci		eb = dst_path->nodes[cur_level + 1];
21818c2ecf20Sopenharmony_ci		parent_slot = dst_path->slots[cur_level + 1];
21828c2ecf20Sopenharmony_ci		child_bytenr = btrfs_node_blockptr(eb, parent_slot);
21838c2ecf20Sopenharmony_ci		child_gen = btrfs_node_ptr_generation(eb, parent_slot);
21848c2ecf20Sopenharmony_ci		btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci		/* This node is old, no need to trace */
21878c2ecf20Sopenharmony_ci		if (child_gen < last_snapshot)
21888c2ecf20Sopenharmony_ci			goto out;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci		eb = read_tree_block(fs_info, child_bytenr, child_gen,
21918c2ecf20Sopenharmony_ci				     cur_level, &first_key);
21928c2ecf20Sopenharmony_ci		if (IS_ERR(eb)) {
21938c2ecf20Sopenharmony_ci			ret = PTR_ERR(eb);
21948c2ecf20Sopenharmony_ci			goto out;
21958c2ecf20Sopenharmony_ci		} else if (!extent_buffer_uptodate(eb)) {
21968c2ecf20Sopenharmony_ci			free_extent_buffer(eb);
21978c2ecf20Sopenharmony_ci			ret = -EIO;
21988c2ecf20Sopenharmony_ci			goto out;
21998c2ecf20Sopenharmony_ci		}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci		dst_path->nodes[cur_level] = eb;
22028c2ecf20Sopenharmony_ci		dst_path->slots[cur_level] = 0;
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci		btrfs_tree_read_lock(eb);
22058c2ecf20Sopenharmony_ci		btrfs_set_lock_blocking_read(eb);
22068c2ecf20Sopenharmony_ci		dst_path->locks[cur_level] = BTRFS_READ_LOCK_BLOCKING;
22078c2ecf20Sopenharmony_ci		need_cleanup = true;
22088c2ecf20Sopenharmony_ci	}
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	/* Now record this tree block and its counter part for qgroups */
22118c2ecf20Sopenharmony_ci	ret = qgroup_trace_extent_swap(trans, src_eb, dst_path, cur_level,
22128c2ecf20Sopenharmony_ci				       root_level, trace_leaf);
22138c2ecf20Sopenharmony_ci	if (ret < 0)
22148c2ecf20Sopenharmony_ci		goto cleanup;
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci	eb = dst_path->nodes[cur_level];
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_ci	if (cur_level > 0) {
22198c2ecf20Sopenharmony_ci		/* Iterate all child tree blocks */
22208c2ecf20Sopenharmony_ci		for (i = 0; i < btrfs_header_nritems(eb); i++) {
22218c2ecf20Sopenharmony_ci			/* Skip old tree blocks as they won't be swapped */
22228c2ecf20Sopenharmony_ci			if (btrfs_node_ptr_generation(eb, i) < last_snapshot)
22238c2ecf20Sopenharmony_ci				continue;
22248c2ecf20Sopenharmony_ci			dst_path->slots[cur_level] = i;
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci			/* Recursive call (at most 7 times) */
22278c2ecf20Sopenharmony_ci			ret = qgroup_trace_new_subtree_blocks(trans, src_eb,
22288c2ecf20Sopenharmony_ci					dst_path, cur_level - 1, root_level,
22298c2ecf20Sopenharmony_ci					last_snapshot, trace_leaf);
22308c2ecf20Sopenharmony_ci			if (ret < 0)
22318c2ecf20Sopenharmony_ci				goto cleanup;
22328c2ecf20Sopenharmony_ci		}
22338c2ecf20Sopenharmony_ci	}
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_cicleanup:
22368c2ecf20Sopenharmony_ci	if (need_cleanup) {
22378c2ecf20Sopenharmony_ci		/* Clean up */
22388c2ecf20Sopenharmony_ci		btrfs_tree_unlock_rw(dst_path->nodes[cur_level],
22398c2ecf20Sopenharmony_ci				     dst_path->locks[cur_level]);
22408c2ecf20Sopenharmony_ci		free_extent_buffer(dst_path->nodes[cur_level]);
22418c2ecf20Sopenharmony_ci		dst_path->nodes[cur_level] = NULL;
22428c2ecf20Sopenharmony_ci		dst_path->slots[cur_level] = 0;
22438c2ecf20Sopenharmony_ci		dst_path->locks[cur_level] = 0;
22448c2ecf20Sopenharmony_ci	}
22458c2ecf20Sopenharmony_ciout:
22468c2ecf20Sopenharmony_ci	return ret;
22478c2ecf20Sopenharmony_ci}
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_cistatic int qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
22508c2ecf20Sopenharmony_ci				struct extent_buffer *src_eb,
22518c2ecf20Sopenharmony_ci				struct extent_buffer *dst_eb,
22528c2ecf20Sopenharmony_ci				u64 last_snapshot, bool trace_leaf)
22538c2ecf20Sopenharmony_ci{
22548c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
22558c2ecf20Sopenharmony_ci	struct btrfs_path *dst_path = NULL;
22568c2ecf20Sopenharmony_ci	int level;
22578c2ecf20Sopenharmony_ci	int ret;
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
22608c2ecf20Sopenharmony_ci		return 0;
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	/* Wrong parameter order */
22638c2ecf20Sopenharmony_ci	if (btrfs_header_generation(src_eb) > btrfs_header_generation(dst_eb)) {
22648c2ecf20Sopenharmony_ci		btrfs_err_rl(fs_info,
22658c2ecf20Sopenharmony_ci		"%s: bad parameter order, src_gen=%llu dst_gen=%llu", __func__,
22668c2ecf20Sopenharmony_ci			     btrfs_header_generation(src_eb),
22678c2ecf20Sopenharmony_ci			     btrfs_header_generation(dst_eb));
22688c2ecf20Sopenharmony_ci		return -EUCLEAN;
22698c2ecf20Sopenharmony_ci	}
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	if (!extent_buffer_uptodate(src_eb) || !extent_buffer_uptodate(dst_eb)) {
22728c2ecf20Sopenharmony_ci		ret = -EIO;
22738c2ecf20Sopenharmony_ci		goto out;
22748c2ecf20Sopenharmony_ci	}
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci	level = btrfs_header_level(dst_eb);
22778c2ecf20Sopenharmony_ci	dst_path = btrfs_alloc_path();
22788c2ecf20Sopenharmony_ci	if (!dst_path) {
22798c2ecf20Sopenharmony_ci		ret = -ENOMEM;
22808c2ecf20Sopenharmony_ci		goto out;
22818c2ecf20Sopenharmony_ci	}
22828c2ecf20Sopenharmony_ci	/* For dst_path */
22838c2ecf20Sopenharmony_ci	atomic_inc(&dst_eb->refs);
22848c2ecf20Sopenharmony_ci	dst_path->nodes[level] = dst_eb;
22858c2ecf20Sopenharmony_ci	dst_path->slots[level] = 0;
22868c2ecf20Sopenharmony_ci	dst_path->locks[level] = 0;
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci	/* Do the generation aware breadth-first search */
22898c2ecf20Sopenharmony_ci	ret = qgroup_trace_new_subtree_blocks(trans, src_eb, dst_path, level,
22908c2ecf20Sopenharmony_ci					      level, last_snapshot, trace_leaf);
22918c2ecf20Sopenharmony_ci	if (ret < 0)
22928c2ecf20Sopenharmony_ci		goto out;
22938c2ecf20Sopenharmony_ci	ret = 0;
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ciout:
22968c2ecf20Sopenharmony_ci	btrfs_free_path(dst_path);
22978c2ecf20Sopenharmony_ci	if (ret < 0)
22988c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
22998c2ecf20Sopenharmony_ci	return ret;
23008c2ecf20Sopenharmony_ci}
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
23038c2ecf20Sopenharmony_ci			       struct extent_buffer *root_eb,
23048c2ecf20Sopenharmony_ci			       u64 root_gen, int root_level)
23058c2ecf20Sopenharmony_ci{
23068c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
23078c2ecf20Sopenharmony_ci	int ret = 0;
23088c2ecf20Sopenharmony_ci	int level;
23098c2ecf20Sopenharmony_ci	struct extent_buffer *eb = root_eb;
23108c2ecf20Sopenharmony_ci	struct btrfs_path *path = NULL;
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_ci	BUG_ON(root_level < 0 || root_level >= BTRFS_MAX_LEVEL);
23138c2ecf20Sopenharmony_ci	BUG_ON(root_eb == NULL);
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
23168c2ecf20Sopenharmony_ci		return 0;
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci	if (!extent_buffer_uptodate(root_eb)) {
23198c2ecf20Sopenharmony_ci		ret = btrfs_read_buffer(root_eb, root_gen, root_level, NULL);
23208c2ecf20Sopenharmony_ci		if (ret)
23218c2ecf20Sopenharmony_ci			goto out;
23228c2ecf20Sopenharmony_ci	}
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	if (root_level == 0) {
23258c2ecf20Sopenharmony_ci		ret = btrfs_qgroup_trace_leaf_items(trans, root_eb);
23268c2ecf20Sopenharmony_ci		goto out;
23278c2ecf20Sopenharmony_ci	}
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
23308c2ecf20Sopenharmony_ci	if (!path)
23318c2ecf20Sopenharmony_ci		return -ENOMEM;
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci	/*
23348c2ecf20Sopenharmony_ci	 * Walk down the tree.  Missing extent blocks are filled in as
23358c2ecf20Sopenharmony_ci	 * we go. Metadata is accounted every time we read a new
23368c2ecf20Sopenharmony_ci	 * extent block.
23378c2ecf20Sopenharmony_ci	 *
23388c2ecf20Sopenharmony_ci	 * When we reach a leaf, we account for file extent items in it,
23398c2ecf20Sopenharmony_ci	 * walk back up the tree (adjusting slot pointers as we go)
23408c2ecf20Sopenharmony_ci	 * and restart the search process.
23418c2ecf20Sopenharmony_ci	 */
23428c2ecf20Sopenharmony_ci	atomic_inc(&root_eb->refs);	/* For path */
23438c2ecf20Sopenharmony_ci	path->nodes[root_level] = root_eb;
23448c2ecf20Sopenharmony_ci	path->slots[root_level] = 0;
23458c2ecf20Sopenharmony_ci	path->locks[root_level] = 0; /* so release_path doesn't try to unlock */
23468c2ecf20Sopenharmony_ciwalk_down:
23478c2ecf20Sopenharmony_ci	level = root_level;
23488c2ecf20Sopenharmony_ci	while (level >= 0) {
23498c2ecf20Sopenharmony_ci		if (path->nodes[level] == NULL) {
23508c2ecf20Sopenharmony_ci			struct btrfs_key first_key;
23518c2ecf20Sopenharmony_ci			int parent_slot;
23528c2ecf20Sopenharmony_ci			u64 child_gen;
23538c2ecf20Sopenharmony_ci			u64 child_bytenr;
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_ci			/*
23568c2ecf20Sopenharmony_ci			 * We need to get child blockptr/gen from parent before
23578c2ecf20Sopenharmony_ci			 * we can read it.
23588c2ecf20Sopenharmony_ci			  */
23598c2ecf20Sopenharmony_ci			eb = path->nodes[level + 1];
23608c2ecf20Sopenharmony_ci			parent_slot = path->slots[level + 1];
23618c2ecf20Sopenharmony_ci			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
23628c2ecf20Sopenharmony_ci			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
23638c2ecf20Sopenharmony_ci			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci			eb = read_tree_block(fs_info, child_bytenr, child_gen,
23668c2ecf20Sopenharmony_ci					     level, &first_key);
23678c2ecf20Sopenharmony_ci			if (IS_ERR(eb)) {
23688c2ecf20Sopenharmony_ci				ret = PTR_ERR(eb);
23698c2ecf20Sopenharmony_ci				goto out;
23708c2ecf20Sopenharmony_ci			} else if (!extent_buffer_uptodate(eb)) {
23718c2ecf20Sopenharmony_ci				free_extent_buffer(eb);
23728c2ecf20Sopenharmony_ci				ret = -EIO;
23738c2ecf20Sopenharmony_ci				goto out;
23748c2ecf20Sopenharmony_ci			}
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci			path->nodes[level] = eb;
23778c2ecf20Sopenharmony_ci			path->slots[level] = 0;
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci			btrfs_tree_read_lock(eb);
23808c2ecf20Sopenharmony_ci			btrfs_set_lock_blocking_read(eb);
23818c2ecf20Sopenharmony_ci			path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ci			ret = btrfs_qgroup_trace_extent(trans, child_bytenr,
23848c2ecf20Sopenharmony_ci							fs_info->nodesize,
23858c2ecf20Sopenharmony_ci							GFP_NOFS);
23868c2ecf20Sopenharmony_ci			if (ret)
23878c2ecf20Sopenharmony_ci				goto out;
23888c2ecf20Sopenharmony_ci		}
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci		if (level == 0) {
23918c2ecf20Sopenharmony_ci			ret = btrfs_qgroup_trace_leaf_items(trans,
23928c2ecf20Sopenharmony_ci							    path->nodes[level]);
23938c2ecf20Sopenharmony_ci			if (ret)
23948c2ecf20Sopenharmony_ci				goto out;
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci			/* Nonzero return here means we completed our search */
23978c2ecf20Sopenharmony_ci			ret = adjust_slots_upwards(path, root_level);
23988c2ecf20Sopenharmony_ci			if (ret)
23998c2ecf20Sopenharmony_ci				break;
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci			/* Restart search with new slots */
24028c2ecf20Sopenharmony_ci			goto walk_down;
24038c2ecf20Sopenharmony_ci		}
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci		level--;
24068c2ecf20Sopenharmony_ci	}
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	ret = 0;
24098c2ecf20Sopenharmony_ciout:
24108c2ecf20Sopenharmony_ci	btrfs_free_path(path);
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci	return ret;
24138c2ecf20Sopenharmony_ci}
24148c2ecf20Sopenharmony_ci
24158c2ecf20Sopenharmony_ci#define UPDATE_NEW	0
24168c2ecf20Sopenharmony_ci#define UPDATE_OLD	1
24178c2ecf20Sopenharmony_ci/*
24188c2ecf20Sopenharmony_ci * Walk all of the roots that points to the bytenr and adjust their refcnts.
24198c2ecf20Sopenharmony_ci */
24208c2ecf20Sopenharmony_cistatic int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
24218c2ecf20Sopenharmony_ci				struct ulist *roots, struct ulist *tmp,
24228c2ecf20Sopenharmony_ci				struct ulist *qgroups, u64 seq, int update_old)
24238c2ecf20Sopenharmony_ci{
24248c2ecf20Sopenharmony_ci	struct ulist_node *unode;
24258c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
24268c2ecf20Sopenharmony_ci	struct ulist_node *tmp_unode;
24278c2ecf20Sopenharmony_ci	struct ulist_iterator tmp_uiter;
24288c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qg;
24298c2ecf20Sopenharmony_ci	int ret = 0;
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci	if (!roots)
24328c2ecf20Sopenharmony_ci		return 0;
24338c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
24348c2ecf20Sopenharmony_ci	while ((unode = ulist_next(roots, &uiter))) {
24358c2ecf20Sopenharmony_ci		qg = find_qgroup_rb(fs_info, unode->val);
24368c2ecf20Sopenharmony_ci		if (!qg)
24378c2ecf20Sopenharmony_ci			continue;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci		ulist_reinit(tmp);
24408c2ecf20Sopenharmony_ci		ret = ulist_add(qgroups, qg->qgroupid, qgroup_to_aux(qg),
24418c2ecf20Sopenharmony_ci				GFP_ATOMIC);
24428c2ecf20Sopenharmony_ci		if (ret < 0)
24438c2ecf20Sopenharmony_ci			return ret;
24448c2ecf20Sopenharmony_ci		ret = ulist_add(tmp, qg->qgroupid, qgroup_to_aux(qg), GFP_ATOMIC);
24458c2ecf20Sopenharmony_ci		if (ret < 0)
24468c2ecf20Sopenharmony_ci			return ret;
24478c2ecf20Sopenharmony_ci		ULIST_ITER_INIT(&tmp_uiter);
24488c2ecf20Sopenharmony_ci		while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) {
24498c2ecf20Sopenharmony_ci			struct btrfs_qgroup_list *glist;
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci			qg = unode_aux_to_qgroup(tmp_unode);
24528c2ecf20Sopenharmony_ci			if (update_old)
24538c2ecf20Sopenharmony_ci				btrfs_qgroup_update_old_refcnt(qg, seq, 1);
24548c2ecf20Sopenharmony_ci			else
24558c2ecf20Sopenharmony_ci				btrfs_qgroup_update_new_refcnt(qg, seq, 1);
24568c2ecf20Sopenharmony_ci			list_for_each_entry(glist, &qg->groups, next_group) {
24578c2ecf20Sopenharmony_ci				ret = ulist_add(qgroups, glist->group->qgroupid,
24588c2ecf20Sopenharmony_ci						qgroup_to_aux(glist->group),
24598c2ecf20Sopenharmony_ci						GFP_ATOMIC);
24608c2ecf20Sopenharmony_ci				if (ret < 0)
24618c2ecf20Sopenharmony_ci					return ret;
24628c2ecf20Sopenharmony_ci				ret = ulist_add(tmp, glist->group->qgroupid,
24638c2ecf20Sopenharmony_ci						qgroup_to_aux(glist->group),
24648c2ecf20Sopenharmony_ci						GFP_ATOMIC);
24658c2ecf20Sopenharmony_ci				if (ret < 0)
24668c2ecf20Sopenharmony_ci					return ret;
24678c2ecf20Sopenharmony_ci			}
24688c2ecf20Sopenharmony_ci		}
24698c2ecf20Sopenharmony_ci	}
24708c2ecf20Sopenharmony_ci	return 0;
24718c2ecf20Sopenharmony_ci}
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci/*
24748c2ecf20Sopenharmony_ci * Update qgroup rfer/excl counters.
24758c2ecf20Sopenharmony_ci * Rfer update is easy, codes can explain themselves.
24768c2ecf20Sopenharmony_ci *
24778c2ecf20Sopenharmony_ci * Excl update is tricky, the update is split into 2 parts.
24788c2ecf20Sopenharmony_ci * Part 1: Possible exclusive <-> sharing detect:
24798c2ecf20Sopenharmony_ci *	|	A	|	!A	|
24808c2ecf20Sopenharmony_ci *  -------------------------------------
24818c2ecf20Sopenharmony_ci *  B	|	*	|	-	|
24828c2ecf20Sopenharmony_ci *  -------------------------------------
24838c2ecf20Sopenharmony_ci *  !B	|	+	|	**	|
24848c2ecf20Sopenharmony_ci *  -------------------------------------
24858c2ecf20Sopenharmony_ci *
24868c2ecf20Sopenharmony_ci * Conditions:
24878c2ecf20Sopenharmony_ci * A:	cur_old_roots < nr_old_roots	(not exclusive before)
24888c2ecf20Sopenharmony_ci * !A:	cur_old_roots == nr_old_roots	(possible exclusive before)
24898c2ecf20Sopenharmony_ci * B:	cur_new_roots < nr_new_roots	(not exclusive now)
24908c2ecf20Sopenharmony_ci * !B:	cur_new_roots == nr_new_roots	(possible exclusive now)
24918c2ecf20Sopenharmony_ci *
24928c2ecf20Sopenharmony_ci * Results:
24938c2ecf20Sopenharmony_ci * +: Possible sharing -> exclusive	-: Possible exclusive -> sharing
24948c2ecf20Sopenharmony_ci * *: Definitely not changed.		**: Possible unchanged.
24958c2ecf20Sopenharmony_ci *
24968c2ecf20Sopenharmony_ci * For !A and !B condition, the exception is cur_old/new_roots == 0 case.
24978c2ecf20Sopenharmony_ci *
24988c2ecf20Sopenharmony_ci * To make the logic clear, we first use condition A and B to split
24998c2ecf20Sopenharmony_ci * combination into 4 results.
25008c2ecf20Sopenharmony_ci *
25018c2ecf20Sopenharmony_ci * Then, for result "+" and "-", check old/new_roots == 0 case, as in them
25028c2ecf20Sopenharmony_ci * only on variant maybe 0.
25038c2ecf20Sopenharmony_ci *
25048c2ecf20Sopenharmony_ci * Lastly, check result **, since there are 2 variants maybe 0, split them
25058c2ecf20Sopenharmony_ci * again(2x2).
25068c2ecf20Sopenharmony_ci * But this time we don't need to consider other things, the codes and logic
25078c2ecf20Sopenharmony_ci * is easy to understand now.
25088c2ecf20Sopenharmony_ci */
25098c2ecf20Sopenharmony_cistatic int qgroup_update_counters(struct btrfs_fs_info *fs_info,
25108c2ecf20Sopenharmony_ci				  struct ulist *qgroups,
25118c2ecf20Sopenharmony_ci				  u64 nr_old_roots,
25128c2ecf20Sopenharmony_ci				  u64 nr_new_roots,
25138c2ecf20Sopenharmony_ci				  u64 num_bytes, u64 seq)
25148c2ecf20Sopenharmony_ci{
25158c2ecf20Sopenharmony_ci	struct ulist_node *unode;
25168c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
25178c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qg;
25188c2ecf20Sopenharmony_ci	u64 cur_new_count, cur_old_count;
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
25218c2ecf20Sopenharmony_ci	while ((unode = ulist_next(qgroups, &uiter))) {
25228c2ecf20Sopenharmony_ci		bool dirty = false;
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci		qg = unode_aux_to_qgroup(unode);
25258c2ecf20Sopenharmony_ci		cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
25268c2ecf20Sopenharmony_ci		cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci		trace_qgroup_update_counters(fs_info, qg, cur_old_count,
25298c2ecf20Sopenharmony_ci					     cur_new_count);
25308c2ecf20Sopenharmony_ci
25318c2ecf20Sopenharmony_ci		/* Rfer update part */
25328c2ecf20Sopenharmony_ci		if (cur_old_count == 0 && cur_new_count > 0) {
25338c2ecf20Sopenharmony_ci			qg->rfer += num_bytes;
25348c2ecf20Sopenharmony_ci			qg->rfer_cmpr += num_bytes;
25358c2ecf20Sopenharmony_ci			dirty = true;
25368c2ecf20Sopenharmony_ci		}
25378c2ecf20Sopenharmony_ci		if (cur_old_count > 0 && cur_new_count == 0) {
25388c2ecf20Sopenharmony_ci			qg->rfer -= num_bytes;
25398c2ecf20Sopenharmony_ci			qg->rfer_cmpr -= num_bytes;
25408c2ecf20Sopenharmony_ci			dirty = true;
25418c2ecf20Sopenharmony_ci		}
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_ci		/* Excl update part */
25448c2ecf20Sopenharmony_ci		/* Exclusive/none -> shared case */
25458c2ecf20Sopenharmony_ci		if (cur_old_count == nr_old_roots &&
25468c2ecf20Sopenharmony_ci		    cur_new_count < nr_new_roots) {
25478c2ecf20Sopenharmony_ci			/* Exclusive -> shared */
25488c2ecf20Sopenharmony_ci			if (cur_old_count != 0) {
25498c2ecf20Sopenharmony_ci				qg->excl -= num_bytes;
25508c2ecf20Sopenharmony_ci				qg->excl_cmpr -= num_bytes;
25518c2ecf20Sopenharmony_ci				dirty = true;
25528c2ecf20Sopenharmony_ci			}
25538c2ecf20Sopenharmony_ci		}
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci		/* Shared -> exclusive/none case */
25568c2ecf20Sopenharmony_ci		if (cur_old_count < nr_old_roots &&
25578c2ecf20Sopenharmony_ci		    cur_new_count == nr_new_roots) {
25588c2ecf20Sopenharmony_ci			/* Shared->exclusive */
25598c2ecf20Sopenharmony_ci			if (cur_new_count != 0) {
25608c2ecf20Sopenharmony_ci				qg->excl += num_bytes;
25618c2ecf20Sopenharmony_ci				qg->excl_cmpr += num_bytes;
25628c2ecf20Sopenharmony_ci				dirty = true;
25638c2ecf20Sopenharmony_ci			}
25648c2ecf20Sopenharmony_ci		}
25658c2ecf20Sopenharmony_ci
25668c2ecf20Sopenharmony_ci		/* Exclusive/none -> exclusive/none case */
25678c2ecf20Sopenharmony_ci		if (cur_old_count == nr_old_roots &&
25688c2ecf20Sopenharmony_ci		    cur_new_count == nr_new_roots) {
25698c2ecf20Sopenharmony_ci			if (cur_old_count == 0) {
25708c2ecf20Sopenharmony_ci				/* None -> exclusive/none */
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci				if (cur_new_count != 0) {
25738c2ecf20Sopenharmony_ci					/* None -> exclusive */
25748c2ecf20Sopenharmony_ci					qg->excl += num_bytes;
25758c2ecf20Sopenharmony_ci					qg->excl_cmpr += num_bytes;
25768c2ecf20Sopenharmony_ci					dirty = true;
25778c2ecf20Sopenharmony_ci				}
25788c2ecf20Sopenharmony_ci				/* None -> none, nothing changed */
25798c2ecf20Sopenharmony_ci			} else {
25808c2ecf20Sopenharmony_ci				/* Exclusive -> exclusive/none */
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci				if (cur_new_count == 0) {
25838c2ecf20Sopenharmony_ci					/* Exclusive -> none */
25848c2ecf20Sopenharmony_ci					qg->excl -= num_bytes;
25858c2ecf20Sopenharmony_ci					qg->excl_cmpr -= num_bytes;
25868c2ecf20Sopenharmony_ci					dirty = true;
25878c2ecf20Sopenharmony_ci				}
25888c2ecf20Sopenharmony_ci				/* Exclusive -> exclusive, nothing changed */
25898c2ecf20Sopenharmony_ci			}
25908c2ecf20Sopenharmony_ci		}
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci		if (dirty)
25938c2ecf20Sopenharmony_ci			qgroup_dirty(fs_info, qg);
25948c2ecf20Sopenharmony_ci	}
25958c2ecf20Sopenharmony_ci	return 0;
25968c2ecf20Sopenharmony_ci}
25978c2ecf20Sopenharmony_ci
25988c2ecf20Sopenharmony_ci/*
25998c2ecf20Sopenharmony_ci * Check if the @roots potentially is a list of fs tree roots
26008c2ecf20Sopenharmony_ci *
26018c2ecf20Sopenharmony_ci * Return 0 for definitely not a fs/subvol tree roots ulist
26028c2ecf20Sopenharmony_ci * Return 1 for possible fs/subvol tree roots in the list (considering an empty
26038c2ecf20Sopenharmony_ci *          one as well)
26048c2ecf20Sopenharmony_ci */
26058c2ecf20Sopenharmony_cistatic int maybe_fs_roots(struct ulist *roots)
26068c2ecf20Sopenharmony_ci{
26078c2ecf20Sopenharmony_ci	struct ulist_node *unode;
26088c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
26098c2ecf20Sopenharmony_ci
26108c2ecf20Sopenharmony_ci	/* Empty one, still possible for fs roots */
26118c2ecf20Sopenharmony_ci	if (!roots || roots->nnodes == 0)
26128c2ecf20Sopenharmony_ci		return 1;
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
26158c2ecf20Sopenharmony_ci	unode = ulist_next(roots, &uiter);
26168c2ecf20Sopenharmony_ci	if (!unode)
26178c2ecf20Sopenharmony_ci		return 1;
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci	/*
26208c2ecf20Sopenharmony_ci	 * If it contains fs tree roots, then it must belong to fs/subvol
26218c2ecf20Sopenharmony_ci	 * trees.
26228c2ecf20Sopenharmony_ci	 * If it contains a non-fs tree, it won't be shared with fs/subvol trees.
26238c2ecf20Sopenharmony_ci	 */
26248c2ecf20Sopenharmony_ci	return is_fstree(unode->val);
26258c2ecf20Sopenharmony_ci}
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ciint btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
26288c2ecf20Sopenharmony_ci				u64 num_bytes, struct ulist *old_roots,
26298c2ecf20Sopenharmony_ci				struct ulist *new_roots)
26308c2ecf20Sopenharmony_ci{
26318c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
26328c2ecf20Sopenharmony_ci	struct ulist *qgroups = NULL;
26338c2ecf20Sopenharmony_ci	struct ulist *tmp = NULL;
26348c2ecf20Sopenharmony_ci	u64 seq;
26358c2ecf20Sopenharmony_ci	u64 nr_new_roots = 0;
26368c2ecf20Sopenharmony_ci	u64 nr_old_roots = 0;
26378c2ecf20Sopenharmony_ci	int ret = 0;
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	/*
26408c2ecf20Sopenharmony_ci	 * If quotas get disabled meanwhile, the resouces need to be freed and
26418c2ecf20Sopenharmony_ci	 * we can't just exit here.
26428c2ecf20Sopenharmony_ci	 */
26438c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
26448c2ecf20Sopenharmony_ci		goto out_free;
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci	if (new_roots) {
26478c2ecf20Sopenharmony_ci		if (!maybe_fs_roots(new_roots))
26488c2ecf20Sopenharmony_ci			goto out_free;
26498c2ecf20Sopenharmony_ci		nr_new_roots = new_roots->nnodes;
26508c2ecf20Sopenharmony_ci	}
26518c2ecf20Sopenharmony_ci	if (old_roots) {
26528c2ecf20Sopenharmony_ci		if (!maybe_fs_roots(old_roots))
26538c2ecf20Sopenharmony_ci			goto out_free;
26548c2ecf20Sopenharmony_ci		nr_old_roots = old_roots->nnodes;
26558c2ecf20Sopenharmony_ci	}
26568c2ecf20Sopenharmony_ci
26578c2ecf20Sopenharmony_ci	/* Quick exit, either not fs tree roots, or won't affect any qgroup */
26588c2ecf20Sopenharmony_ci	if (nr_old_roots == 0 && nr_new_roots == 0)
26598c2ecf20Sopenharmony_ci		goto out_free;
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci	BUG_ON(!fs_info->quota_root);
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_ci	trace_btrfs_qgroup_account_extent(fs_info, trans->transid, bytenr,
26648c2ecf20Sopenharmony_ci					num_bytes, nr_old_roots, nr_new_roots);
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci	qgroups = ulist_alloc(GFP_NOFS);
26678c2ecf20Sopenharmony_ci	if (!qgroups) {
26688c2ecf20Sopenharmony_ci		ret = -ENOMEM;
26698c2ecf20Sopenharmony_ci		goto out_free;
26708c2ecf20Sopenharmony_ci	}
26718c2ecf20Sopenharmony_ci	tmp = ulist_alloc(GFP_NOFS);
26728c2ecf20Sopenharmony_ci	if (!tmp) {
26738c2ecf20Sopenharmony_ci		ret = -ENOMEM;
26748c2ecf20Sopenharmony_ci		goto out_free;
26758c2ecf20Sopenharmony_ci	}
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
26788c2ecf20Sopenharmony_ci	if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
26798c2ecf20Sopenharmony_ci		if (fs_info->qgroup_rescan_progress.objectid <= bytenr) {
26808c2ecf20Sopenharmony_ci			mutex_unlock(&fs_info->qgroup_rescan_lock);
26818c2ecf20Sopenharmony_ci			ret = 0;
26828c2ecf20Sopenharmony_ci			goto out_free;
26838c2ecf20Sopenharmony_ci		}
26848c2ecf20Sopenharmony_ci	}
26858c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
26888c2ecf20Sopenharmony_ci	seq = fs_info->qgroup_seq;
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci	/* Update old refcnts using old_roots */
26918c2ecf20Sopenharmony_ci	ret = qgroup_update_refcnt(fs_info, old_roots, tmp, qgroups, seq,
26928c2ecf20Sopenharmony_ci				   UPDATE_OLD);
26938c2ecf20Sopenharmony_ci	if (ret < 0)
26948c2ecf20Sopenharmony_ci		goto out;
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	/* Update new refcnts using new_roots */
26978c2ecf20Sopenharmony_ci	ret = qgroup_update_refcnt(fs_info, new_roots, tmp, qgroups, seq,
26988c2ecf20Sopenharmony_ci				   UPDATE_NEW);
26998c2ecf20Sopenharmony_ci	if (ret < 0)
27008c2ecf20Sopenharmony_ci		goto out;
27018c2ecf20Sopenharmony_ci
27028c2ecf20Sopenharmony_ci	qgroup_update_counters(fs_info, qgroups, nr_old_roots, nr_new_roots,
27038c2ecf20Sopenharmony_ci			       num_bytes, seq);
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_ci	/*
27068c2ecf20Sopenharmony_ci	 * Bump qgroup_seq to avoid seq overlap
27078c2ecf20Sopenharmony_ci	 */
27088c2ecf20Sopenharmony_ci	fs_info->qgroup_seq += max(nr_old_roots, nr_new_roots) + 1;
27098c2ecf20Sopenharmony_ciout:
27108c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
27118c2ecf20Sopenharmony_ciout_free:
27128c2ecf20Sopenharmony_ci	ulist_free(tmp);
27138c2ecf20Sopenharmony_ci	ulist_free(qgroups);
27148c2ecf20Sopenharmony_ci	ulist_free(old_roots);
27158c2ecf20Sopenharmony_ci	ulist_free(new_roots);
27168c2ecf20Sopenharmony_ci	return ret;
27178c2ecf20Sopenharmony_ci}
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ciint btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
27208c2ecf20Sopenharmony_ci{
27218c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
27228c2ecf20Sopenharmony_ci	struct btrfs_qgroup_extent_record *record;
27238c2ecf20Sopenharmony_ci	struct btrfs_delayed_ref_root *delayed_refs;
27248c2ecf20Sopenharmony_ci	struct ulist *new_roots = NULL;
27258c2ecf20Sopenharmony_ci	struct rb_node *node;
27268c2ecf20Sopenharmony_ci	u64 num_dirty_extents = 0;
27278c2ecf20Sopenharmony_ci	u64 qgroup_to_skip;
27288c2ecf20Sopenharmony_ci	int ret = 0;
27298c2ecf20Sopenharmony_ci
27308c2ecf20Sopenharmony_ci	delayed_refs = &trans->transaction->delayed_refs;
27318c2ecf20Sopenharmony_ci	qgroup_to_skip = delayed_refs->qgroup_to_skip;
27328c2ecf20Sopenharmony_ci	while ((node = rb_first(&delayed_refs->dirty_extent_root))) {
27338c2ecf20Sopenharmony_ci		record = rb_entry(node, struct btrfs_qgroup_extent_record,
27348c2ecf20Sopenharmony_ci				  node);
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci		num_dirty_extents++;
27378c2ecf20Sopenharmony_ci		trace_btrfs_qgroup_account_extents(fs_info, record);
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci		if (!ret) {
27408c2ecf20Sopenharmony_ci			/*
27418c2ecf20Sopenharmony_ci			 * Old roots should be searched when inserting qgroup
27428c2ecf20Sopenharmony_ci			 * extent record
27438c2ecf20Sopenharmony_ci			 */
27448c2ecf20Sopenharmony_ci			if (WARN_ON(!record->old_roots)) {
27458c2ecf20Sopenharmony_ci				/* Search commit root to find old_roots */
27468c2ecf20Sopenharmony_ci				ret = btrfs_find_all_roots(NULL, fs_info,
27478c2ecf20Sopenharmony_ci						record->bytenr, 0,
27488c2ecf20Sopenharmony_ci						&record->old_roots, false);
27498c2ecf20Sopenharmony_ci				if (ret < 0)
27508c2ecf20Sopenharmony_ci					goto cleanup;
27518c2ecf20Sopenharmony_ci			}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ci			/* Free the reserved data space */
27548c2ecf20Sopenharmony_ci			btrfs_qgroup_free_refroot(fs_info,
27558c2ecf20Sopenharmony_ci					record->data_rsv_refroot,
27568c2ecf20Sopenharmony_ci					record->data_rsv,
27578c2ecf20Sopenharmony_ci					BTRFS_QGROUP_RSV_DATA);
27588c2ecf20Sopenharmony_ci			/*
27598c2ecf20Sopenharmony_ci			 * Use SEQ_LAST as time_seq to do special search, which
27608c2ecf20Sopenharmony_ci			 * doesn't lock tree or delayed_refs and search current
27618c2ecf20Sopenharmony_ci			 * root. It's safe inside commit_transaction().
27628c2ecf20Sopenharmony_ci			 */
27638c2ecf20Sopenharmony_ci			ret = btrfs_find_all_roots(trans, fs_info,
27648c2ecf20Sopenharmony_ci				record->bytenr, SEQ_LAST, &new_roots, false);
27658c2ecf20Sopenharmony_ci			if (ret < 0)
27668c2ecf20Sopenharmony_ci				goto cleanup;
27678c2ecf20Sopenharmony_ci			if (qgroup_to_skip) {
27688c2ecf20Sopenharmony_ci				ulist_del(new_roots, qgroup_to_skip, 0);
27698c2ecf20Sopenharmony_ci				ulist_del(record->old_roots, qgroup_to_skip,
27708c2ecf20Sopenharmony_ci					  0);
27718c2ecf20Sopenharmony_ci			}
27728c2ecf20Sopenharmony_ci			ret = btrfs_qgroup_account_extent(trans, record->bytenr,
27738c2ecf20Sopenharmony_ci							  record->num_bytes,
27748c2ecf20Sopenharmony_ci							  record->old_roots,
27758c2ecf20Sopenharmony_ci							  new_roots);
27768c2ecf20Sopenharmony_ci			record->old_roots = NULL;
27778c2ecf20Sopenharmony_ci			new_roots = NULL;
27788c2ecf20Sopenharmony_ci		}
27798c2ecf20Sopenharmony_cicleanup:
27808c2ecf20Sopenharmony_ci		ulist_free(record->old_roots);
27818c2ecf20Sopenharmony_ci		ulist_free(new_roots);
27828c2ecf20Sopenharmony_ci		new_roots = NULL;
27838c2ecf20Sopenharmony_ci		rb_erase(node, &delayed_refs->dirty_extent_root);
27848c2ecf20Sopenharmony_ci		kfree(record);
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	}
27878c2ecf20Sopenharmony_ci	trace_qgroup_num_dirty_extents(fs_info, trans->transid,
27888c2ecf20Sopenharmony_ci				       num_dirty_extents);
27898c2ecf20Sopenharmony_ci	return ret;
27908c2ecf20Sopenharmony_ci}
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci/*
27938c2ecf20Sopenharmony_ci * Writes all changed qgroups to disk.
27948c2ecf20Sopenharmony_ci * Called by the transaction commit path and the qgroup assign ioctl.
27958c2ecf20Sopenharmony_ci */
27968c2ecf20Sopenharmony_ciint btrfs_run_qgroups(struct btrfs_trans_handle *trans)
27978c2ecf20Sopenharmony_ci{
27988c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
27998c2ecf20Sopenharmony_ci	int ret = 0;
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	/*
28028c2ecf20Sopenharmony_ci	 * In case we are called from the qgroup assign ioctl, assert that we
28038c2ecf20Sopenharmony_ci	 * are holding the qgroup_ioctl_lock, otherwise we can race with a quota
28048c2ecf20Sopenharmony_ci	 * disable operation (ioctl) and access a freed quota root.
28058c2ecf20Sopenharmony_ci	 */
28068c2ecf20Sopenharmony_ci	if (trans->transaction->state != TRANS_STATE_COMMIT_DOING)
28078c2ecf20Sopenharmony_ci		lockdep_assert_held(&fs_info->qgroup_ioctl_lock);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
28108c2ecf20Sopenharmony_ci		return ret;
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
28138c2ecf20Sopenharmony_ci	while (!list_empty(&fs_info->dirty_qgroups)) {
28148c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qgroup;
28158c2ecf20Sopenharmony_ci		qgroup = list_first_entry(&fs_info->dirty_qgroups,
28168c2ecf20Sopenharmony_ci					  struct btrfs_qgroup, dirty);
28178c2ecf20Sopenharmony_ci		list_del_init(&qgroup->dirty);
28188c2ecf20Sopenharmony_ci		spin_unlock(&fs_info->qgroup_lock);
28198c2ecf20Sopenharmony_ci		ret = update_qgroup_info_item(trans, qgroup);
28208c2ecf20Sopenharmony_ci		if (ret)
28218c2ecf20Sopenharmony_ci			fs_info->qgroup_flags |=
28228c2ecf20Sopenharmony_ci					BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
28238c2ecf20Sopenharmony_ci		ret = update_qgroup_limit_item(trans, qgroup);
28248c2ecf20Sopenharmony_ci		if (ret)
28258c2ecf20Sopenharmony_ci			fs_info->qgroup_flags |=
28268c2ecf20Sopenharmony_ci					BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
28278c2ecf20Sopenharmony_ci		spin_lock(&fs_info->qgroup_lock);
28288c2ecf20Sopenharmony_ci	}
28298c2ecf20Sopenharmony_ci	if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
28308c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_ON;
28318c2ecf20Sopenharmony_ci	else
28328c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
28338c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_ci	ret = update_qgroup_status_item(trans);
28368c2ecf20Sopenharmony_ci	if (ret)
28378c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	return ret;
28408c2ecf20Sopenharmony_ci}
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci/*
28438c2ecf20Sopenharmony_ci * Copy the accounting information between qgroups. This is necessary
28448c2ecf20Sopenharmony_ci * when a snapshot or a subvolume is created. Throwing an error will
28458c2ecf20Sopenharmony_ci * cause a transaction abort so we take extra care here to only error
28468c2ecf20Sopenharmony_ci * when a readonly fs is a reasonable outcome.
28478c2ecf20Sopenharmony_ci */
28488c2ecf20Sopenharmony_ciint btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
28498c2ecf20Sopenharmony_ci			 u64 objectid, struct btrfs_qgroup_inherit *inherit)
28508c2ecf20Sopenharmony_ci{
28518c2ecf20Sopenharmony_ci	int ret = 0;
28528c2ecf20Sopenharmony_ci	int i;
28538c2ecf20Sopenharmony_ci	u64 *i_qgroups;
28548c2ecf20Sopenharmony_ci	bool committing = false;
28558c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
28568c2ecf20Sopenharmony_ci	struct btrfs_root *quota_root;
28578c2ecf20Sopenharmony_ci	struct btrfs_qgroup *srcgroup;
28588c2ecf20Sopenharmony_ci	struct btrfs_qgroup *dstgroup;
28598c2ecf20Sopenharmony_ci	bool need_rescan = false;
28608c2ecf20Sopenharmony_ci	u32 level_size = 0;
28618c2ecf20Sopenharmony_ci	u64 nums;
28628c2ecf20Sopenharmony_ci
28638c2ecf20Sopenharmony_ci	/*
28648c2ecf20Sopenharmony_ci	 * There are only two callers of this function.
28658c2ecf20Sopenharmony_ci	 *
28668c2ecf20Sopenharmony_ci	 * One in create_subvol() in the ioctl context, which needs to hold
28678c2ecf20Sopenharmony_ci	 * the qgroup_ioctl_lock.
28688c2ecf20Sopenharmony_ci	 *
28698c2ecf20Sopenharmony_ci	 * The other one in create_pending_snapshot() where no other qgroup
28708c2ecf20Sopenharmony_ci	 * code can modify the fs as they all need to either start a new trans
28718c2ecf20Sopenharmony_ci	 * or hold a trans handler, thus we don't need to hold
28728c2ecf20Sopenharmony_ci	 * qgroup_ioctl_lock.
28738c2ecf20Sopenharmony_ci	 * This would avoid long and complex lock chain and make lockdep happy.
28748c2ecf20Sopenharmony_ci	 */
28758c2ecf20Sopenharmony_ci	spin_lock(&fs_info->trans_lock);
28768c2ecf20Sopenharmony_ci	if (trans->transaction->state == TRANS_STATE_COMMIT_DOING)
28778c2ecf20Sopenharmony_ci		committing = true;
28788c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->trans_lock);
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci	if (!committing)
28818c2ecf20Sopenharmony_ci		mutex_lock(&fs_info->qgroup_ioctl_lock);
28828c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
28838c2ecf20Sopenharmony_ci		goto out;
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci	quota_root = fs_info->quota_root;
28868c2ecf20Sopenharmony_ci	if (!quota_root) {
28878c2ecf20Sopenharmony_ci		ret = -EINVAL;
28888c2ecf20Sopenharmony_ci		goto out;
28898c2ecf20Sopenharmony_ci	}
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci	if (inherit) {
28928c2ecf20Sopenharmony_ci		i_qgroups = (u64 *)(inherit + 1);
28938c2ecf20Sopenharmony_ci		nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
28948c2ecf20Sopenharmony_ci		       2 * inherit->num_excl_copies;
28958c2ecf20Sopenharmony_ci		for (i = 0; i < nums; ++i) {
28968c2ecf20Sopenharmony_ci			srcgroup = find_qgroup_rb(fs_info, *i_qgroups);
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci			/*
28998c2ecf20Sopenharmony_ci			 * Zero out invalid groups so we can ignore
29008c2ecf20Sopenharmony_ci			 * them later.
29018c2ecf20Sopenharmony_ci			 */
29028c2ecf20Sopenharmony_ci			if (!srcgroup ||
29038c2ecf20Sopenharmony_ci			    ((srcgroup->qgroupid >> 48) <= (objectid >> 48)))
29048c2ecf20Sopenharmony_ci				*i_qgroups = 0ULL;
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci			++i_qgroups;
29078c2ecf20Sopenharmony_ci		}
29088c2ecf20Sopenharmony_ci	}
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	/*
29118c2ecf20Sopenharmony_ci	 * create a tracking group for the subvol itself
29128c2ecf20Sopenharmony_ci	 */
29138c2ecf20Sopenharmony_ci	ret = add_qgroup_item(trans, quota_root, objectid);
29148c2ecf20Sopenharmony_ci	if (ret)
29158c2ecf20Sopenharmony_ci		goto out;
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	/*
29188c2ecf20Sopenharmony_ci	 * add qgroup to all inherited groups
29198c2ecf20Sopenharmony_ci	 */
29208c2ecf20Sopenharmony_ci	if (inherit) {
29218c2ecf20Sopenharmony_ci		i_qgroups = (u64 *)(inherit + 1);
29228c2ecf20Sopenharmony_ci		for (i = 0; i < inherit->num_qgroups; ++i, ++i_qgroups) {
29238c2ecf20Sopenharmony_ci			if (*i_qgroups == 0)
29248c2ecf20Sopenharmony_ci				continue;
29258c2ecf20Sopenharmony_ci			ret = add_qgroup_relation_item(trans, objectid,
29268c2ecf20Sopenharmony_ci						       *i_qgroups);
29278c2ecf20Sopenharmony_ci			if (ret && ret != -EEXIST)
29288c2ecf20Sopenharmony_ci				goto out;
29298c2ecf20Sopenharmony_ci			ret = add_qgroup_relation_item(trans, *i_qgroups,
29308c2ecf20Sopenharmony_ci						       objectid);
29318c2ecf20Sopenharmony_ci			if (ret && ret != -EEXIST)
29328c2ecf20Sopenharmony_ci				goto out;
29338c2ecf20Sopenharmony_ci		}
29348c2ecf20Sopenharmony_ci		ret = 0;
29358c2ecf20Sopenharmony_ci	}
29368c2ecf20Sopenharmony_ci
29378c2ecf20Sopenharmony_ci
29388c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci	dstgroup = add_qgroup_rb(fs_info, objectid);
29418c2ecf20Sopenharmony_ci	if (IS_ERR(dstgroup)) {
29428c2ecf20Sopenharmony_ci		ret = PTR_ERR(dstgroup);
29438c2ecf20Sopenharmony_ci		goto unlock;
29448c2ecf20Sopenharmony_ci	}
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci	if (inherit && inherit->flags & BTRFS_QGROUP_INHERIT_SET_LIMITS) {
29478c2ecf20Sopenharmony_ci		dstgroup->lim_flags = inherit->lim.flags;
29488c2ecf20Sopenharmony_ci		dstgroup->max_rfer = inherit->lim.max_rfer;
29498c2ecf20Sopenharmony_ci		dstgroup->max_excl = inherit->lim.max_excl;
29508c2ecf20Sopenharmony_ci		dstgroup->rsv_rfer = inherit->lim.rsv_rfer;
29518c2ecf20Sopenharmony_ci		dstgroup->rsv_excl = inherit->lim.rsv_excl;
29528c2ecf20Sopenharmony_ci
29538c2ecf20Sopenharmony_ci		qgroup_dirty(fs_info, dstgroup);
29548c2ecf20Sopenharmony_ci	}
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	if (srcid) {
29578c2ecf20Sopenharmony_ci		srcgroup = find_qgroup_rb(fs_info, srcid);
29588c2ecf20Sopenharmony_ci		if (!srcgroup)
29598c2ecf20Sopenharmony_ci			goto unlock;
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci		/*
29628c2ecf20Sopenharmony_ci		 * We call inherit after we clone the root in order to make sure
29638c2ecf20Sopenharmony_ci		 * our counts don't go crazy, so at this point the only
29648c2ecf20Sopenharmony_ci		 * difference between the two roots should be the root node.
29658c2ecf20Sopenharmony_ci		 */
29668c2ecf20Sopenharmony_ci		level_size = fs_info->nodesize;
29678c2ecf20Sopenharmony_ci		dstgroup->rfer = srcgroup->rfer;
29688c2ecf20Sopenharmony_ci		dstgroup->rfer_cmpr = srcgroup->rfer_cmpr;
29698c2ecf20Sopenharmony_ci		dstgroup->excl = level_size;
29708c2ecf20Sopenharmony_ci		dstgroup->excl_cmpr = level_size;
29718c2ecf20Sopenharmony_ci		srcgroup->excl = level_size;
29728c2ecf20Sopenharmony_ci		srcgroup->excl_cmpr = level_size;
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci		/* inherit the limit info */
29758c2ecf20Sopenharmony_ci		dstgroup->lim_flags = srcgroup->lim_flags;
29768c2ecf20Sopenharmony_ci		dstgroup->max_rfer = srcgroup->max_rfer;
29778c2ecf20Sopenharmony_ci		dstgroup->max_excl = srcgroup->max_excl;
29788c2ecf20Sopenharmony_ci		dstgroup->rsv_rfer = srcgroup->rsv_rfer;
29798c2ecf20Sopenharmony_ci		dstgroup->rsv_excl = srcgroup->rsv_excl;
29808c2ecf20Sopenharmony_ci
29818c2ecf20Sopenharmony_ci		qgroup_dirty(fs_info, dstgroup);
29828c2ecf20Sopenharmony_ci		qgroup_dirty(fs_info, srcgroup);
29838c2ecf20Sopenharmony_ci	}
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci	if (!inherit)
29868c2ecf20Sopenharmony_ci		goto unlock;
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_ci	i_qgroups = (u64 *)(inherit + 1);
29898c2ecf20Sopenharmony_ci	for (i = 0; i < inherit->num_qgroups; ++i) {
29908c2ecf20Sopenharmony_ci		if (*i_qgroups) {
29918c2ecf20Sopenharmony_ci			ret = add_relation_rb(fs_info, objectid, *i_qgroups);
29928c2ecf20Sopenharmony_ci			if (ret)
29938c2ecf20Sopenharmony_ci				goto unlock;
29948c2ecf20Sopenharmony_ci		}
29958c2ecf20Sopenharmony_ci		++i_qgroups;
29968c2ecf20Sopenharmony_ci
29978c2ecf20Sopenharmony_ci		/*
29988c2ecf20Sopenharmony_ci		 * If we're doing a snapshot, and adding the snapshot to a new
29998c2ecf20Sopenharmony_ci		 * qgroup, the numbers are guaranteed to be incorrect.
30008c2ecf20Sopenharmony_ci		 */
30018c2ecf20Sopenharmony_ci		if (srcid)
30028c2ecf20Sopenharmony_ci			need_rescan = true;
30038c2ecf20Sopenharmony_ci	}
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_ci	for (i = 0; i <  inherit->num_ref_copies; ++i, i_qgroups += 2) {
30068c2ecf20Sopenharmony_ci		struct btrfs_qgroup *src;
30078c2ecf20Sopenharmony_ci		struct btrfs_qgroup *dst;
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci		if (!i_qgroups[0] || !i_qgroups[1])
30108c2ecf20Sopenharmony_ci			continue;
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_ci		src = find_qgroup_rb(fs_info, i_qgroups[0]);
30138c2ecf20Sopenharmony_ci		dst = find_qgroup_rb(fs_info, i_qgroups[1]);
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_ci		if (!src || !dst) {
30168c2ecf20Sopenharmony_ci			ret = -EINVAL;
30178c2ecf20Sopenharmony_ci			goto unlock;
30188c2ecf20Sopenharmony_ci		}
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci		dst->rfer = src->rfer - level_size;
30218c2ecf20Sopenharmony_ci		dst->rfer_cmpr = src->rfer_cmpr - level_size;
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci		/* Manually tweaking numbers certainly needs a rescan */
30248c2ecf20Sopenharmony_ci		need_rescan = true;
30258c2ecf20Sopenharmony_ci	}
30268c2ecf20Sopenharmony_ci	for (i = 0; i <  inherit->num_excl_copies; ++i, i_qgroups += 2) {
30278c2ecf20Sopenharmony_ci		struct btrfs_qgroup *src;
30288c2ecf20Sopenharmony_ci		struct btrfs_qgroup *dst;
30298c2ecf20Sopenharmony_ci
30308c2ecf20Sopenharmony_ci		if (!i_qgroups[0] || !i_qgroups[1])
30318c2ecf20Sopenharmony_ci			continue;
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_ci		src = find_qgroup_rb(fs_info, i_qgroups[0]);
30348c2ecf20Sopenharmony_ci		dst = find_qgroup_rb(fs_info, i_qgroups[1]);
30358c2ecf20Sopenharmony_ci
30368c2ecf20Sopenharmony_ci		if (!src || !dst) {
30378c2ecf20Sopenharmony_ci			ret = -EINVAL;
30388c2ecf20Sopenharmony_ci			goto unlock;
30398c2ecf20Sopenharmony_ci		}
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci		dst->excl = src->excl + level_size;
30428c2ecf20Sopenharmony_ci		dst->excl_cmpr = src->excl_cmpr + level_size;
30438c2ecf20Sopenharmony_ci		need_rescan = true;
30448c2ecf20Sopenharmony_ci	}
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_ciunlock:
30478c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
30488c2ecf20Sopenharmony_ci	if (!ret)
30498c2ecf20Sopenharmony_ci		ret = btrfs_sysfs_add_one_qgroup(fs_info, dstgroup);
30508c2ecf20Sopenharmony_ciout:
30518c2ecf20Sopenharmony_ci	if (!committing)
30528c2ecf20Sopenharmony_ci		mutex_unlock(&fs_info->qgroup_ioctl_lock);
30538c2ecf20Sopenharmony_ci	if (need_rescan)
30548c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
30558c2ecf20Sopenharmony_ci	return ret;
30568c2ecf20Sopenharmony_ci}
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_cistatic bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
30598c2ecf20Sopenharmony_ci{
30608c2ecf20Sopenharmony_ci	if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
30618c2ecf20Sopenharmony_ci	    qgroup_rsv_total(qg) + (s64)qg->rfer + num_bytes > qg->max_rfer)
30628c2ecf20Sopenharmony_ci		return false;
30638c2ecf20Sopenharmony_ci
30648c2ecf20Sopenharmony_ci	if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
30658c2ecf20Sopenharmony_ci	    qgroup_rsv_total(qg) + (s64)qg->excl + num_bytes > qg->max_excl)
30668c2ecf20Sopenharmony_ci		return false;
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci	return true;
30698c2ecf20Sopenharmony_ci}
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_cistatic int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce,
30728c2ecf20Sopenharmony_ci			  enum btrfs_qgroup_rsv_type type)
30738c2ecf20Sopenharmony_ci{
30748c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
30758c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
30768c2ecf20Sopenharmony_ci	u64 ref_root = root->root_key.objectid;
30778c2ecf20Sopenharmony_ci	int ret = 0;
30788c2ecf20Sopenharmony_ci	struct ulist_node *unode;
30798c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci	if (!is_fstree(ref_root))
30828c2ecf20Sopenharmony_ci		return 0;
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci	if (num_bytes == 0)
30858c2ecf20Sopenharmony_ci		return 0;
30868c2ecf20Sopenharmony_ci
30878c2ecf20Sopenharmony_ci	if (test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags) &&
30888c2ecf20Sopenharmony_ci	    capable(CAP_SYS_RESOURCE))
30898c2ecf20Sopenharmony_ci		enforce = false;
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
30928c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
30938c2ecf20Sopenharmony_ci		goto out;
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, ref_root);
30968c2ecf20Sopenharmony_ci	if (!qgroup)
30978c2ecf20Sopenharmony_ci		goto out;
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_ci	/*
31008c2ecf20Sopenharmony_ci	 * in a first step, we check all affected qgroups if any limits would
31018c2ecf20Sopenharmony_ci	 * be exceeded
31028c2ecf20Sopenharmony_ci	 */
31038c2ecf20Sopenharmony_ci	ulist_reinit(fs_info->qgroup_ulist);
31048c2ecf20Sopenharmony_ci	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
31058c2ecf20Sopenharmony_ci			qgroup_to_aux(qgroup), GFP_ATOMIC);
31068c2ecf20Sopenharmony_ci	if (ret < 0)
31078c2ecf20Sopenharmony_ci		goto out;
31088c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
31098c2ecf20Sopenharmony_ci	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
31108c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qg;
31118c2ecf20Sopenharmony_ci		struct btrfs_qgroup_list *glist;
31128c2ecf20Sopenharmony_ci
31138c2ecf20Sopenharmony_ci		qg = unode_aux_to_qgroup(unode);
31148c2ecf20Sopenharmony_ci
31158c2ecf20Sopenharmony_ci		if (enforce && !qgroup_check_limits(qg, num_bytes)) {
31168c2ecf20Sopenharmony_ci			ret = -EDQUOT;
31178c2ecf20Sopenharmony_ci			goto out;
31188c2ecf20Sopenharmony_ci		}
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci		list_for_each_entry(glist, &qg->groups, next_group) {
31218c2ecf20Sopenharmony_ci			ret = ulist_add(fs_info->qgroup_ulist,
31228c2ecf20Sopenharmony_ci					glist->group->qgroupid,
31238c2ecf20Sopenharmony_ci					qgroup_to_aux(glist->group), GFP_ATOMIC);
31248c2ecf20Sopenharmony_ci			if (ret < 0)
31258c2ecf20Sopenharmony_ci				goto out;
31268c2ecf20Sopenharmony_ci		}
31278c2ecf20Sopenharmony_ci	}
31288c2ecf20Sopenharmony_ci	ret = 0;
31298c2ecf20Sopenharmony_ci	/*
31308c2ecf20Sopenharmony_ci	 * no limits exceeded, now record the reservation into all qgroups
31318c2ecf20Sopenharmony_ci	 */
31328c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
31338c2ecf20Sopenharmony_ci	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
31348c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qg;
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_ci		qg = unode_aux_to_qgroup(unode);
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_ci		qgroup_rsv_add(fs_info, qg, num_bytes, type);
31398c2ecf20Sopenharmony_ci	}
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_ciout:
31428c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
31438c2ecf20Sopenharmony_ci	return ret;
31448c2ecf20Sopenharmony_ci}
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci/*
31478c2ecf20Sopenharmony_ci * Free @num_bytes of reserved space with @type for qgroup.  (Normally level 0
31488c2ecf20Sopenharmony_ci * qgroup).
31498c2ecf20Sopenharmony_ci *
31508c2ecf20Sopenharmony_ci * Will handle all higher level qgroup too.
31518c2ecf20Sopenharmony_ci *
31528c2ecf20Sopenharmony_ci * NOTE: If @num_bytes is (u64)-1, this means to free all bytes of this qgroup.
31538c2ecf20Sopenharmony_ci * This special case is only used for META_PERTRANS type.
31548c2ecf20Sopenharmony_ci */
31558c2ecf20Sopenharmony_civoid btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
31568c2ecf20Sopenharmony_ci			       u64 ref_root, u64 num_bytes,
31578c2ecf20Sopenharmony_ci			       enum btrfs_qgroup_rsv_type type)
31588c2ecf20Sopenharmony_ci{
31598c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
31608c2ecf20Sopenharmony_ci	struct ulist_node *unode;
31618c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
31628c2ecf20Sopenharmony_ci	int ret = 0;
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci	if (!is_fstree(ref_root))
31658c2ecf20Sopenharmony_ci		return;
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	if (num_bytes == 0)
31688c2ecf20Sopenharmony_ci		return;
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci	if (num_bytes == (u64)-1 && type != BTRFS_QGROUP_RSV_META_PERTRANS) {
31718c2ecf20Sopenharmony_ci		WARN(1, "%s: Invalid type to free", __func__);
31728c2ecf20Sopenharmony_ci		return;
31738c2ecf20Sopenharmony_ci	}
31748c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
31778c2ecf20Sopenharmony_ci		goto out;
31788c2ecf20Sopenharmony_ci
31798c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, ref_root);
31808c2ecf20Sopenharmony_ci	if (!qgroup)
31818c2ecf20Sopenharmony_ci		goto out;
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	if (num_bytes == (u64)-1)
31848c2ecf20Sopenharmony_ci		/*
31858c2ecf20Sopenharmony_ci		 * We're freeing all pertrans rsv, get reserved value from
31868c2ecf20Sopenharmony_ci		 * level 0 qgroup as real num_bytes to free.
31878c2ecf20Sopenharmony_ci		 */
31888c2ecf20Sopenharmony_ci		num_bytes = qgroup->rsv.values[type];
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	ulist_reinit(fs_info->qgroup_ulist);
31918c2ecf20Sopenharmony_ci	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
31928c2ecf20Sopenharmony_ci			qgroup_to_aux(qgroup), GFP_ATOMIC);
31938c2ecf20Sopenharmony_ci	if (ret < 0)
31948c2ecf20Sopenharmony_ci		goto out;
31958c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
31968c2ecf20Sopenharmony_ci	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
31978c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qg;
31988c2ecf20Sopenharmony_ci		struct btrfs_qgroup_list *glist;
31998c2ecf20Sopenharmony_ci
32008c2ecf20Sopenharmony_ci		qg = unode_aux_to_qgroup(unode);
32018c2ecf20Sopenharmony_ci
32028c2ecf20Sopenharmony_ci		qgroup_rsv_release(fs_info, qg, num_bytes, type);
32038c2ecf20Sopenharmony_ci
32048c2ecf20Sopenharmony_ci		list_for_each_entry(glist, &qg->groups, next_group) {
32058c2ecf20Sopenharmony_ci			ret = ulist_add(fs_info->qgroup_ulist,
32068c2ecf20Sopenharmony_ci					glist->group->qgroupid,
32078c2ecf20Sopenharmony_ci					qgroup_to_aux(glist->group), GFP_ATOMIC);
32088c2ecf20Sopenharmony_ci			if (ret < 0)
32098c2ecf20Sopenharmony_ci				goto out;
32108c2ecf20Sopenharmony_ci		}
32118c2ecf20Sopenharmony_ci	}
32128c2ecf20Sopenharmony_ci
32138c2ecf20Sopenharmony_ciout:
32148c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
32158c2ecf20Sopenharmony_ci}
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_ci/*
32188c2ecf20Sopenharmony_ci * Check if the leaf is the last leaf. Which means all node pointers
32198c2ecf20Sopenharmony_ci * are at their last position.
32208c2ecf20Sopenharmony_ci */
32218c2ecf20Sopenharmony_cistatic bool is_last_leaf(struct btrfs_path *path)
32228c2ecf20Sopenharmony_ci{
32238c2ecf20Sopenharmony_ci	int i;
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	for (i = 1; i < BTRFS_MAX_LEVEL && path->nodes[i]; i++) {
32268c2ecf20Sopenharmony_ci		if (path->slots[i] != btrfs_header_nritems(path->nodes[i]) - 1)
32278c2ecf20Sopenharmony_ci			return false;
32288c2ecf20Sopenharmony_ci	}
32298c2ecf20Sopenharmony_ci	return true;
32308c2ecf20Sopenharmony_ci}
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci/*
32338c2ecf20Sopenharmony_ci * returns < 0 on error, 0 when more leafs are to be scanned.
32348c2ecf20Sopenharmony_ci * returns 1 when done.
32358c2ecf20Sopenharmony_ci */
32368c2ecf20Sopenharmony_cistatic int qgroup_rescan_leaf(struct btrfs_trans_handle *trans,
32378c2ecf20Sopenharmony_ci			      struct btrfs_path *path)
32388c2ecf20Sopenharmony_ci{
32398c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
32408c2ecf20Sopenharmony_ci	struct btrfs_key found;
32418c2ecf20Sopenharmony_ci	struct extent_buffer *scratch_leaf = NULL;
32428c2ecf20Sopenharmony_ci	struct ulist *roots = NULL;
32438c2ecf20Sopenharmony_ci	u64 num_bytes;
32448c2ecf20Sopenharmony_ci	bool done;
32458c2ecf20Sopenharmony_ci	int slot;
32468c2ecf20Sopenharmony_ci	int ret;
32478c2ecf20Sopenharmony_ci
32488c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
32498c2ecf20Sopenharmony_ci	ret = btrfs_search_slot_for_read(fs_info->extent_root,
32508c2ecf20Sopenharmony_ci					 &fs_info->qgroup_rescan_progress,
32518c2ecf20Sopenharmony_ci					 path, 1, 0);
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_ci	btrfs_debug(fs_info,
32548c2ecf20Sopenharmony_ci		"current progress key (%llu %u %llu), search_slot ret %d",
32558c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_progress.objectid,
32568c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_progress.type,
32578c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_progress.offset, ret);
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ci	if (ret) {
32608c2ecf20Sopenharmony_ci		/*
32618c2ecf20Sopenharmony_ci		 * The rescan is about to end, we will not be scanning any
32628c2ecf20Sopenharmony_ci		 * further blocks. We cannot unset the RESCAN flag here, because
32638c2ecf20Sopenharmony_ci		 * we want to commit the transaction if everything went well.
32648c2ecf20Sopenharmony_ci		 * To make the live accounting work in this phase, we set our
32658c2ecf20Sopenharmony_ci		 * scan progress pointer such that every real extent objectid
32668c2ecf20Sopenharmony_ci		 * will be smaller.
32678c2ecf20Sopenharmony_ci		 */
32688c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_progress.objectid = (u64)-1;
32698c2ecf20Sopenharmony_ci		btrfs_release_path(path);
32708c2ecf20Sopenharmony_ci		mutex_unlock(&fs_info->qgroup_rescan_lock);
32718c2ecf20Sopenharmony_ci		return ret;
32728c2ecf20Sopenharmony_ci	}
32738c2ecf20Sopenharmony_ci	done = is_last_leaf(path);
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	btrfs_item_key_to_cpu(path->nodes[0], &found,
32768c2ecf20Sopenharmony_ci			      btrfs_header_nritems(path->nodes[0]) - 1);
32778c2ecf20Sopenharmony_ci	fs_info->qgroup_rescan_progress.objectid = found.objectid + 1;
32788c2ecf20Sopenharmony_ci
32798c2ecf20Sopenharmony_ci	scratch_leaf = btrfs_clone_extent_buffer(path->nodes[0]);
32808c2ecf20Sopenharmony_ci	if (!scratch_leaf) {
32818c2ecf20Sopenharmony_ci		ret = -ENOMEM;
32828c2ecf20Sopenharmony_ci		mutex_unlock(&fs_info->qgroup_rescan_lock);
32838c2ecf20Sopenharmony_ci		goto out;
32848c2ecf20Sopenharmony_ci	}
32858c2ecf20Sopenharmony_ci	slot = path->slots[0];
32868c2ecf20Sopenharmony_ci	btrfs_release_path(path);
32878c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	for (; slot < btrfs_header_nritems(scratch_leaf); ++slot) {
32908c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(scratch_leaf, &found, slot);
32918c2ecf20Sopenharmony_ci		if (found.type != BTRFS_EXTENT_ITEM_KEY &&
32928c2ecf20Sopenharmony_ci		    found.type != BTRFS_METADATA_ITEM_KEY)
32938c2ecf20Sopenharmony_ci			continue;
32948c2ecf20Sopenharmony_ci		if (found.type == BTRFS_METADATA_ITEM_KEY)
32958c2ecf20Sopenharmony_ci			num_bytes = fs_info->nodesize;
32968c2ecf20Sopenharmony_ci		else
32978c2ecf20Sopenharmony_ci			num_bytes = found.offset;
32988c2ecf20Sopenharmony_ci
32998c2ecf20Sopenharmony_ci		ret = btrfs_find_all_roots(NULL, fs_info, found.objectid, 0,
33008c2ecf20Sopenharmony_ci					   &roots, false);
33018c2ecf20Sopenharmony_ci		if (ret < 0)
33028c2ecf20Sopenharmony_ci			goto out;
33038c2ecf20Sopenharmony_ci		/* For rescan, just pass old_roots as NULL */
33048c2ecf20Sopenharmony_ci		ret = btrfs_qgroup_account_extent(trans, found.objectid,
33058c2ecf20Sopenharmony_ci						  num_bytes, NULL, roots);
33068c2ecf20Sopenharmony_ci		if (ret < 0)
33078c2ecf20Sopenharmony_ci			goto out;
33088c2ecf20Sopenharmony_ci	}
33098c2ecf20Sopenharmony_ciout:
33108c2ecf20Sopenharmony_ci	if (scratch_leaf)
33118c2ecf20Sopenharmony_ci		free_extent_buffer(scratch_leaf);
33128c2ecf20Sopenharmony_ci
33138c2ecf20Sopenharmony_ci	if (done && !ret) {
33148c2ecf20Sopenharmony_ci		ret = 1;
33158c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_progress.objectid = (u64)-1;
33168c2ecf20Sopenharmony_ci	}
33178c2ecf20Sopenharmony_ci	return ret;
33188c2ecf20Sopenharmony_ci}
33198c2ecf20Sopenharmony_ci
33208c2ecf20Sopenharmony_cistatic bool rescan_should_stop(struct btrfs_fs_info *fs_info)
33218c2ecf20Sopenharmony_ci{
33228c2ecf20Sopenharmony_ci	return btrfs_fs_closing(fs_info) ||
33238c2ecf20Sopenharmony_ci		test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state) ||
33248c2ecf20Sopenharmony_ci		!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
33258c2ecf20Sopenharmony_ci}
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_cistatic void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
33288c2ecf20Sopenharmony_ci{
33298c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = container_of(work, struct btrfs_fs_info,
33308c2ecf20Sopenharmony_ci						     qgroup_rescan_work);
33318c2ecf20Sopenharmony_ci	struct btrfs_path *path;
33328c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans = NULL;
33338c2ecf20Sopenharmony_ci	int err = -ENOMEM;
33348c2ecf20Sopenharmony_ci	int ret = 0;
33358c2ecf20Sopenharmony_ci	bool stopped = false;
33368c2ecf20Sopenharmony_ci	bool did_leaf_rescans = false;
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
33398c2ecf20Sopenharmony_ci	if (!path)
33408c2ecf20Sopenharmony_ci		goto out;
33418c2ecf20Sopenharmony_ci	/*
33428c2ecf20Sopenharmony_ci	 * Rescan should only search for commit root, and any later difference
33438c2ecf20Sopenharmony_ci	 * should be recorded by qgroup
33448c2ecf20Sopenharmony_ci	 */
33458c2ecf20Sopenharmony_ci	path->search_commit_root = 1;
33468c2ecf20Sopenharmony_ci	path->skip_locking = 1;
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	err = 0;
33498c2ecf20Sopenharmony_ci	while (!err && !(stopped = rescan_should_stop(fs_info))) {
33508c2ecf20Sopenharmony_ci		trans = btrfs_start_transaction(fs_info->fs_root, 0);
33518c2ecf20Sopenharmony_ci		if (IS_ERR(trans)) {
33528c2ecf20Sopenharmony_ci			err = PTR_ERR(trans);
33538c2ecf20Sopenharmony_ci			break;
33548c2ecf20Sopenharmony_ci		}
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci		err = qgroup_rescan_leaf(trans, path);
33578c2ecf20Sopenharmony_ci		did_leaf_rescans = true;
33588c2ecf20Sopenharmony_ci
33598c2ecf20Sopenharmony_ci		if (err > 0)
33608c2ecf20Sopenharmony_ci			btrfs_commit_transaction(trans);
33618c2ecf20Sopenharmony_ci		else
33628c2ecf20Sopenharmony_ci			btrfs_end_transaction(trans);
33638c2ecf20Sopenharmony_ci	}
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_ciout:
33668c2ecf20Sopenharmony_ci	btrfs_free_path(path);
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
33698c2ecf20Sopenharmony_ci	if (err > 0 &&
33708c2ecf20Sopenharmony_ci	    fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
33718c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
33728c2ecf20Sopenharmony_ci	} else if (err < 0 || stopped) {
33738c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
33748c2ecf20Sopenharmony_ci	}
33758c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	/*
33788c2ecf20Sopenharmony_ci	 * Only update status, since the previous part has already updated the
33798c2ecf20Sopenharmony_ci	 * qgroup info, and only if we did any actual work. This also prevents
33808c2ecf20Sopenharmony_ci	 * race with a concurrent quota disable, which has already set
33818c2ecf20Sopenharmony_ci	 * fs_info->quota_root to NULL and cleared BTRFS_FS_QUOTA_ENABLED at
33828c2ecf20Sopenharmony_ci	 * btrfs_quota_disable().
33838c2ecf20Sopenharmony_ci	 */
33848c2ecf20Sopenharmony_ci	if (did_leaf_rescans) {
33858c2ecf20Sopenharmony_ci		trans = btrfs_start_transaction(fs_info->quota_root, 1);
33868c2ecf20Sopenharmony_ci		if (IS_ERR(trans)) {
33878c2ecf20Sopenharmony_ci			err = PTR_ERR(trans);
33888c2ecf20Sopenharmony_ci			trans = NULL;
33898c2ecf20Sopenharmony_ci			btrfs_err(fs_info,
33908c2ecf20Sopenharmony_ci				  "fail to start transaction for status update: %d",
33918c2ecf20Sopenharmony_ci				  err);
33928c2ecf20Sopenharmony_ci		}
33938c2ecf20Sopenharmony_ci	} else {
33948c2ecf20Sopenharmony_ci		trans = NULL;
33958c2ecf20Sopenharmony_ci	}
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
33988c2ecf20Sopenharmony_ci	if (!stopped)
33998c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
34008c2ecf20Sopenharmony_ci	if (trans) {
34018c2ecf20Sopenharmony_ci		ret = update_qgroup_status_item(trans);
34028c2ecf20Sopenharmony_ci		if (ret < 0) {
34038c2ecf20Sopenharmony_ci			err = ret;
34048c2ecf20Sopenharmony_ci			btrfs_err(fs_info, "fail to update qgroup status: %d",
34058c2ecf20Sopenharmony_ci				  err);
34068c2ecf20Sopenharmony_ci		}
34078c2ecf20Sopenharmony_ci	}
34088c2ecf20Sopenharmony_ci	fs_info->qgroup_rescan_running = false;
34098c2ecf20Sopenharmony_ci	complete_all(&fs_info->qgroup_rescan_completion);
34108c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
34118c2ecf20Sopenharmony_ci
34128c2ecf20Sopenharmony_ci	if (!trans)
34138c2ecf20Sopenharmony_ci		return;
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ci	btrfs_end_transaction(trans);
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	if (stopped) {
34188c2ecf20Sopenharmony_ci		btrfs_info(fs_info, "qgroup scan paused");
34198c2ecf20Sopenharmony_ci	} else if (err >= 0) {
34208c2ecf20Sopenharmony_ci		btrfs_info(fs_info, "qgroup scan completed%s",
34218c2ecf20Sopenharmony_ci			err > 0 ? " (inconsistency flag cleared)" : "");
34228c2ecf20Sopenharmony_ci	} else {
34238c2ecf20Sopenharmony_ci		btrfs_err(fs_info, "qgroup scan failed with %d", err);
34248c2ecf20Sopenharmony_ci	}
34258c2ecf20Sopenharmony_ci}
34268c2ecf20Sopenharmony_ci
34278c2ecf20Sopenharmony_ci/*
34288c2ecf20Sopenharmony_ci * Checks that (a) no rescan is running and (b) quota is enabled. Allocates all
34298c2ecf20Sopenharmony_ci * memory required for the rescan context.
34308c2ecf20Sopenharmony_ci */
34318c2ecf20Sopenharmony_cistatic int
34328c2ecf20Sopenharmony_ciqgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
34338c2ecf20Sopenharmony_ci		   int init_flags)
34348c2ecf20Sopenharmony_ci{
34358c2ecf20Sopenharmony_ci	int ret = 0;
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_ci	if (!init_flags) {
34388c2ecf20Sopenharmony_ci		/* we're resuming qgroup rescan at mount time */
34398c2ecf20Sopenharmony_ci		if (!(fs_info->qgroup_flags &
34408c2ecf20Sopenharmony_ci		      BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
34418c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
34428c2ecf20Sopenharmony_ci			"qgroup rescan init failed, qgroup rescan is not queued");
34438c2ecf20Sopenharmony_ci			ret = -EINVAL;
34448c2ecf20Sopenharmony_ci		} else if (!(fs_info->qgroup_flags &
34458c2ecf20Sopenharmony_ci			     BTRFS_QGROUP_STATUS_FLAG_ON)) {
34468c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
34478c2ecf20Sopenharmony_ci			"qgroup rescan init failed, qgroup is not enabled");
34488c2ecf20Sopenharmony_ci			ret = -EINVAL;
34498c2ecf20Sopenharmony_ci		}
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_ci		if (ret)
34528c2ecf20Sopenharmony_ci			return ret;
34538c2ecf20Sopenharmony_ci	}
34548c2ecf20Sopenharmony_ci
34558c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
34568c2ecf20Sopenharmony_ci
34578c2ecf20Sopenharmony_ci	if (init_flags) {
34588c2ecf20Sopenharmony_ci		if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
34598c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
34608c2ecf20Sopenharmony_ci				   "qgroup rescan is already in progress");
34618c2ecf20Sopenharmony_ci			ret = -EINPROGRESS;
34628c2ecf20Sopenharmony_ci		} else if (!(fs_info->qgroup_flags &
34638c2ecf20Sopenharmony_ci			     BTRFS_QGROUP_STATUS_FLAG_ON)) {
34648c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
34658c2ecf20Sopenharmony_ci			"qgroup rescan init failed, qgroup is not enabled");
34668c2ecf20Sopenharmony_ci			ret = -EINVAL;
34678c2ecf20Sopenharmony_ci		} else if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
34688c2ecf20Sopenharmony_ci			/* Quota disable is in progress */
34698c2ecf20Sopenharmony_ci			ret = -EBUSY;
34708c2ecf20Sopenharmony_ci		}
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_ci		if (ret) {
34738c2ecf20Sopenharmony_ci			mutex_unlock(&fs_info->qgroup_rescan_lock);
34748c2ecf20Sopenharmony_ci			return ret;
34758c2ecf20Sopenharmony_ci		}
34768c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
34778c2ecf20Sopenharmony_ci	}
34788c2ecf20Sopenharmony_ci
34798c2ecf20Sopenharmony_ci	memset(&fs_info->qgroup_rescan_progress, 0,
34808c2ecf20Sopenharmony_ci		sizeof(fs_info->qgroup_rescan_progress));
34818c2ecf20Sopenharmony_ci	fs_info->qgroup_rescan_progress.objectid = progress_objectid;
34828c2ecf20Sopenharmony_ci	init_completion(&fs_info->qgroup_rescan_completion);
34838c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
34848c2ecf20Sopenharmony_ci
34858c2ecf20Sopenharmony_ci	btrfs_init_work(&fs_info->qgroup_rescan_work,
34868c2ecf20Sopenharmony_ci			btrfs_qgroup_rescan_worker, NULL, NULL);
34878c2ecf20Sopenharmony_ci	return 0;
34888c2ecf20Sopenharmony_ci}
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_cistatic void
34918c2ecf20Sopenharmony_ciqgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info)
34928c2ecf20Sopenharmony_ci{
34938c2ecf20Sopenharmony_ci	struct rb_node *n;
34948c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
34958c2ecf20Sopenharmony_ci
34968c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
34978c2ecf20Sopenharmony_ci	/* clear all current qgroup tracking information */
34988c2ecf20Sopenharmony_ci	for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) {
34998c2ecf20Sopenharmony_ci		qgroup = rb_entry(n, struct btrfs_qgroup, node);
35008c2ecf20Sopenharmony_ci		qgroup->rfer = 0;
35018c2ecf20Sopenharmony_ci		qgroup->rfer_cmpr = 0;
35028c2ecf20Sopenharmony_ci		qgroup->excl = 0;
35038c2ecf20Sopenharmony_ci		qgroup->excl_cmpr = 0;
35048c2ecf20Sopenharmony_ci		qgroup_dirty(fs_info, qgroup);
35058c2ecf20Sopenharmony_ci	}
35068c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
35078c2ecf20Sopenharmony_ci}
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ciint
35108c2ecf20Sopenharmony_cibtrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
35118c2ecf20Sopenharmony_ci{
35128c2ecf20Sopenharmony_ci	int ret = 0;
35138c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans;
35148c2ecf20Sopenharmony_ci
35158c2ecf20Sopenharmony_ci	ret = qgroup_rescan_init(fs_info, 0, 1);
35168c2ecf20Sopenharmony_ci	if (ret)
35178c2ecf20Sopenharmony_ci		return ret;
35188c2ecf20Sopenharmony_ci
35198c2ecf20Sopenharmony_ci	/*
35208c2ecf20Sopenharmony_ci	 * We have set the rescan_progress to 0, which means no more
35218c2ecf20Sopenharmony_ci	 * delayed refs will be accounted by btrfs_qgroup_account_ref.
35228c2ecf20Sopenharmony_ci	 * However, btrfs_qgroup_account_ref may be right after its call
35238c2ecf20Sopenharmony_ci	 * to btrfs_find_all_roots, in which case it would still do the
35248c2ecf20Sopenharmony_ci	 * accounting.
35258c2ecf20Sopenharmony_ci	 * To solve this, we're committing the transaction, which will
35268c2ecf20Sopenharmony_ci	 * ensure we run all delayed refs and only after that, we are
35278c2ecf20Sopenharmony_ci	 * going to clear all tracking information for a clean start.
35288c2ecf20Sopenharmony_ci	 */
35298c2ecf20Sopenharmony_ci
35308c2ecf20Sopenharmony_ci	trans = btrfs_join_transaction(fs_info->fs_root);
35318c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
35328c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
35338c2ecf20Sopenharmony_ci		return PTR_ERR(trans);
35348c2ecf20Sopenharmony_ci	}
35358c2ecf20Sopenharmony_ci	ret = btrfs_commit_transaction(trans);
35368c2ecf20Sopenharmony_ci	if (ret) {
35378c2ecf20Sopenharmony_ci		fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
35388c2ecf20Sopenharmony_ci		return ret;
35398c2ecf20Sopenharmony_ci	}
35408c2ecf20Sopenharmony_ci
35418c2ecf20Sopenharmony_ci	qgroup_rescan_zero_tracking(fs_info);
35428c2ecf20Sopenharmony_ci
35438c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
35448c2ecf20Sopenharmony_ci	fs_info->qgroup_rescan_running = true;
35458c2ecf20Sopenharmony_ci	btrfs_queue_work(fs_info->qgroup_rescan_workers,
35468c2ecf20Sopenharmony_ci			 &fs_info->qgroup_rescan_work);
35478c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ci	return 0;
35508c2ecf20Sopenharmony_ci}
35518c2ecf20Sopenharmony_ci
35528c2ecf20Sopenharmony_ciint btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
35538c2ecf20Sopenharmony_ci				     bool interruptible)
35548c2ecf20Sopenharmony_ci{
35558c2ecf20Sopenharmony_ci	int running;
35568c2ecf20Sopenharmony_ci	int ret = 0;
35578c2ecf20Sopenharmony_ci
35588c2ecf20Sopenharmony_ci	mutex_lock(&fs_info->qgroup_rescan_lock);
35598c2ecf20Sopenharmony_ci	running = fs_info->qgroup_rescan_running;
35608c2ecf20Sopenharmony_ci	mutex_unlock(&fs_info->qgroup_rescan_lock);
35618c2ecf20Sopenharmony_ci
35628c2ecf20Sopenharmony_ci	if (!running)
35638c2ecf20Sopenharmony_ci		return 0;
35648c2ecf20Sopenharmony_ci
35658c2ecf20Sopenharmony_ci	if (interruptible)
35668c2ecf20Sopenharmony_ci		ret = wait_for_completion_interruptible(
35678c2ecf20Sopenharmony_ci					&fs_info->qgroup_rescan_completion);
35688c2ecf20Sopenharmony_ci	else
35698c2ecf20Sopenharmony_ci		wait_for_completion(&fs_info->qgroup_rescan_completion);
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	return ret;
35728c2ecf20Sopenharmony_ci}
35738c2ecf20Sopenharmony_ci
35748c2ecf20Sopenharmony_ci/*
35758c2ecf20Sopenharmony_ci * this is only called from open_ctree where we're still single threaded, thus
35768c2ecf20Sopenharmony_ci * locking is omitted here.
35778c2ecf20Sopenharmony_ci */
35788c2ecf20Sopenharmony_civoid
35798c2ecf20Sopenharmony_cibtrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info)
35808c2ecf20Sopenharmony_ci{
35818c2ecf20Sopenharmony_ci	if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
35828c2ecf20Sopenharmony_ci		mutex_lock(&fs_info->qgroup_rescan_lock);
35838c2ecf20Sopenharmony_ci		fs_info->qgroup_rescan_running = true;
35848c2ecf20Sopenharmony_ci		btrfs_queue_work(fs_info->qgroup_rescan_workers,
35858c2ecf20Sopenharmony_ci				 &fs_info->qgroup_rescan_work);
35868c2ecf20Sopenharmony_ci		mutex_unlock(&fs_info->qgroup_rescan_lock);
35878c2ecf20Sopenharmony_ci	}
35888c2ecf20Sopenharmony_ci}
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci#define rbtree_iterate_from_safe(node, next, start)				\
35918c2ecf20Sopenharmony_ci       for (node = start; node && ({ next = rb_next(node); 1;}); node = next)
35928c2ecf20Sopenharmony_ci
35938c2ecf20Sopenharmony_cistatic int qgroup_unreserve_range(struct btrfs_inode *inode,
35948c2ecf20Sopenharmony_ci				  struct extent_changeset *reserved, u64 start,
35958c2ecf20Sopenharmony_ci				  u64 len)
35968c2ecf20Sopenharmony_ci{
35978c2ecf20Sopenharmony_ci	struct rb_node *node;
35988c2ecf20Sopenharmony_ci	struct rb_node *next;
35998c2ecf20Sopenharmony_ci	struct ulist_node *entry;
36008c2ecf20Sopenharmony_ci	int ret = 0;
36018c2ecf20Sopenharmony_ci
36028c2ecf20Sopenharmony_ci	node = reserved->range_changed.root.rb_node;
36038c2ecf20Sopenharmony_ci	if (!node)
36048c2ecf20Sopenharmony_ci		return 0;
36058c2ecf20Sopenharmony_ci	while (node) {
36068c2ecf20Sopenharmony_ci		entry = rb_entry(node, struct ulist_node, rb_node);
36078c2ecf20Sopenharmony_ci		if (entry->val < start)
36088c2ecf20Sopenharmony_ci			node = node->rb_right;
36098c2ecf20Sopenharmony_ci		else
36108c2ecf20Sopenharmony_ci			node = node->rb_left;
36118c2ecf20Sopenharmony_ci	}
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci	if (entry->val > start && rb_prev(&entry->rb_node))
36148c2ecf20Sopenharmony_ci		entry = rb_entry(rb_prev(&entry->rb_node), struct ulist_node,
36158c2ecf20Sopenharmony_ci				 rb_node);
36168c2ecf20Sopenharmony_ci
36178c2ecf20Sopenharmony_ci	rbtree_iterate_from_safe(node, next, &entry->rb_node) {
36188c2ecf20Sopenharmony_ci		u64 entry_start;
36198c2ecf20Sopenharmony_ci		u64 entry_end;
36208c2ecf20Sopenharmony_ci		u64 entry_len;
36218c2ecf20Sopenharmony_ci		int clear_ret;
36228c2ecf20Sopenharmony_ci
36238c2ecf20Sopenharmony_ci		entry = rb_entry(node, struct ulist_node, rb_node);
36248c2ecf20Sopenharmony_ci		entry_start = entry->val;
36258c2ecf20Sopenharmony_ci		entry_end = entry->aux;
36268c2ecf20Sopenharmony_ci		entry_len = entry_end - entry_start + 1;
36278c2ecf20Sopenharmony_ci
36288c2ecf20Sopenharmony_ci		if (entry_start >= start + len)
36298c2ecf20Sopenharmony_ci			break;
36308c2ecf20Sopenharmony_ci		if (entry_start + entry_len <= start)
36318c2ecf20Sopenharmony_ci			continue;
36328c2ecf20Sopenharmony_ci		/*
36338c2ecf20Sopenharmony_ci		 * Now the entry is in [start, start + len), revert the
36348c2ecf20Sopenharmony_ci		 * EXTENT_QGROUP_RESERVED bit.
36358c2ecf20Sopenharmony_ci		 */
36368c2ecf20Sopenharmony_ci		clear_ret = clear_extent_bits(&inode->io_tree, entry_start,
36378c2ecf20Sopenharmony_ci					      entry_end, EXTENT_QGROUP_RESERVED);
36388c2ecf20Sopenharmony_ci		if (!ret && clear_ret < 0)
36398c2ecf20Sopenharmony_ci			ret = clear_ret;
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci		ulist_del(&reserved->range_changed, entry->val, entry->aux);
36428c2ecf20Sopenharmony_ci		if (likely(reserved->bytes_changed >= entry_len)) {
36438c2ecf20Sopenharmony_ci			reserved->bytes_changed -= entry_len;
36448c2ecf20Sopenharmony_ci		} else {
36458c2ecf20Sopenharmony_ci			WARN_ON(1);
36468c2ecf20Sopenharmony_ci			reserved->bytes_changed = 0;
36478c2ecf20Sopenharmony_ci		}
36488c2ecf20Sopenharmony_ci	}
36498c2ecf20Sopenharmony_ci
36508c2ecf20Sopenharmony_ci	return ret;
36518c2ecf20Sopenharmony_ci}
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci/*
36548c2ecf20Sopenharmony_ci * Try to free some space for qgroup.
36558c2ecf20Sopenharmony_ci *
36568c2ecf20Sopenharmony_ci * For qgroup, there are only 3 ways to free qgroup space:
36578c2ecf20Sopenharmony_ci * - Flush nodatacow write
36588c2ecf20Sopenharmony_ci *   Any nodatacow write will free its reserved data space at run_delalloc_range().
36598c2ecf20Sopenharmony_ci *   In theory, we should only flush nodatacow inodes, but it's not yet
36608c2ecf20Sopenharmony_ci *   possible, so we need to flush the whole root.
36618c2ecf20Sopenharmony_ci *
36628c2ecf20Sopenharmony_ci * - Wait for ordered extents
36638c2ecf20Sopenharmony_ci *   When ordered extents are finished, their reserved metadata is finally
36648c2ecf20Sopenharmony_ci *   converted to per_trans status, which can be freed by later commit
36658c2ecf20Sopenharmony_ci *   transaction.
36668c2ecf20Sopenharmony_ci *
36678c2ecf20Sopenharmony_ci * - Commit transaction
36688c2ecf20Sopenharmony_ci *   This would free the meta_per_trans space.
36698c2ecf20Sopenharmony_ci *   In theory this shouldn't provide much space, but any more qgroup space
36708c2ecf20Sopenharmony_ci *   is needed.
36718c2ecf20Sopenharmony_ci */
36728c2ecf20Sopenharmony_cistatic int try_flush_qgroup(struct btrfs_root *root)
36738c2ecf20Sopenharmony_ci{
36748c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans;
36758c2ecf20Sopenharmony_ci	int ret;
36768c2ecf20Sopenharmony_ci	bool can_commit = true;
36778c2ecf20Sopenharmony_ci
36788c2ecf20Sopenharmony_ci	/*
36798c2ecf20Sopenharmony_ci	 * If current process holds a transaction, we shouldn't flush, as we
36808c2ecf20Sopenharmony_ci	 * assume all space reservation happens before a transaction handle is
36818c2ecf20Sopenharmony_ci	 * held.
36828c2ecf20Sopenharmony_ci	 *
36838c2ecf20Sopenharmony_ci	 * But there are cases like btrfs_delayed_item_reserve_metadata() where
36848c2ecf20Sopenharmony_ci	 * we try to reserve space with one transction handle already held.
36858c2ecf20Sopenharmony_ci	 * In that case we can't commit transaction, but at least try to end it
36868c2ecf20Sopenharmony_ci	 * and hope the started data writes can free some space.
36878c2ecf20Sopenharmony_ci	 */
36888c2ecf20Sopenharmony_ci	if (current->journal_info &&
36898c2ecf20Sopenharmony_ci	    current->journal_info != BTRFS_SEND_TRANS_STUB)
36908c2ecf20Sopenharmony_ci		can_commit = false;
36918c2ecf20Sopenharmony_ci
36928c2ecf20Sopenharmony_ci	/*
36938c2ecf20Sopenharmony_ci	 * We don't want to run flush again and again, so if there is a running
36948c2ecf20Sopenharmony_ci	 * one, we won't try to start a new flush, but exit directly.
36958c2ecf20Sopenharmony_ci	 */
36968c2ecf20Sopenharmony_ci	if (test_and_set_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state)) {
36978c2ecf20Sopenharmony_ci		/*
36988c2ecf20Sopenharmony_ci		 * We are already holding a transaction, thus we can block other
36998c2ecf20Sopenharmony_ci		 * threads from flushing.  So exit right now. This increases
37008c2ecf20Sopenharmony_ci		 * the chance of EDQUOT for heavy load and near limit cases.
37018c2ecf20Sopenharmony_ci		 * But we can argue that if we're already near limit, EDQUOT is
37028c2ecf20Sopenharmony_ci		 * unavoidable anyway.
37038c2ecf20Sopenharmony_ci		 */
37048c2ecf20Sopenharmony_ci		if (!can_commit)
37058c2ecf20Sopenharmony_ci			return 0;
37068c2ecf20Sopenharmony_ci
37078c2ecf20Sopenharmony_ci		wait_event(root->qgroup_flush_wait,
37088c2ecf20Sopenharmony_ci			!test_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state));
37098c2ecf20Sopenharmony_ci		return 0;
37108c2ecf20Sopenharmony_ci	}
37118c2ecf20Sopenharmony_ci
37128c2ecf20Sopenharmony_ci	ret = btrfs_start_delalloc_snapshot(root);
37138c2ecf20Sopenharmony_ci	if (ret < 0)
37148c2ecf20Sopenharmony_ci		goto out;
37158c2ecf20Sopenharmony_ci	btrfs_wait_ordered_extents(root, U64_MAX, 0, (u64)-1);
37168c2ecf20Sopenharmony_ci
37178c2ecf20Sopenharmony_ci	trans = btrfs_join_transaction(root);
37188c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
37198c2ecf20Sopenharmony_ci		ret = PTR_ERR(trans);
37208c2ecf20Sopenharmony_ci		goto out;
37218c2ecf20Sopenharmony_ci	}
37228c2ecf20Sopenharmony_ci
37238c2ecf20Sopenharmony_ci	if (can_commit)
37248c2ecf20Sopenharmony_ci		ret = btrfs_commit_transaction(trans);
37258c2ecf20Sopenharmony_ci	else
37268c2ecf20Sopenharmony_ci		ret = btrfs_end_transaction(trans);
37278c2ecf20Sopenharmony_ciout:
37288c2ecf20Sopenharmony_ci	clear_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state);
37298c2ecf20Sopenharmony_ci	wake_up(&root->qgroup_flush_wait);
37308c2ecf20Sopenharmony_ci	return ret;
37318c2ecf20Sopenharmony_ci}
37328c2ecf20Sopenharmony_ci
37338c2ecf20Sopenharmony_cistatic int qgroup_reserve_data(struct btrfs_inode *inode,
37348c2ecf20Sopenharmony_ci			struct extent_changeset **reserved_ret, u64 start,
37358c2ecf20Sopenharmony_ci			u64 len)
37368c2ecf20Sopenharmony_ci{
37378c2ecf20Sopenharmony_ci	struct btrfs_root *root = inode->root;
37388c2ecf20Sopenharmony_ci	struct extent_changeset *reserved;
37398c2ecf20Sopenharmony_ci	bool new_reserved = false;
37408c2ecf20Sopenharmony_ci	u64 orig_reserved;
37418c2ecf20Sopenharmony_ci	u64 to_reserve;
37428c2ecf20Sopenharmony_ci	int ret;
37438c2ecf20Sopenharmony_ci
37448c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags) ||
37458c2ecf20Sopenharmony_ci	    !is_fstree(root->root_key.objectid) || len == 0)
37468c2ecf20Sopenharmony_ci		return 0;
37478c2ecf20Sopenharmony_ci
37488c2ecf20Sopenharmony_ci	/* @reserved parameter is mandatory for qgroup */
37498c2ecf20Sopenharmony_ci	if (WARN_ON(!reserved_ret))
37508c2ecf20Sopenharmony_ci		return -EINVAL;
37518c2ecf20Sopenharmony_ci	if (!*reserved_ret) {
37528c2ecf20Sopenharmony_ci		new_reserved = true;
37538c2ecf20Sopenharmony_ci		*reserved_ret = extent_changeset_alloc();
37548c2ecf20Sopenharmony_ci		if (!*reserved_ret)
37558c2ecf20Sopenharmony_ci			return -ENOMEM;
37568c2ecf20Sopenharmony_ci	}
37578c2ecf20Sopenharmony_ci	reserved = *reserved_ret;
37588c2ecf20Sopenharmony_ci	/* Record already reserved space */
37598c2ecf20Sopenharmony_ci	orig_reserved = reserved->bytes_changed;
37608c2ecf20Sopenharmony_ci	ret = set_record_extent_bits(&inode->io_tree, start,
37618c2ecf20Sopenharmony_ci			start + len -1, EXTENT_QGROUP_RESERVED, reserved);
37628c2ecf20Sopenharmony_ci
37638c2ecf20Sopenharmony_ci	/* Newly reserved space */
37648c2ecf20Sopenharmony_ci	to_reserve = reserved->bytes_changed - orig_reserved;
37658c2ecf20Sopenharmony_ci	trace_btrfs_qgroup_reserve_data(&inode->vfs_inode, start, len,
37668c2ecf20Sopenharmony_ci					to_reserve, QGROUP_RESERVE);
37678c2ecf20Sopenharmony_ci	if (ret < 0)
37688c2ecf20Sopenharmony_ci		goto out;
37698c2ecf20Sopenharmony_ci	ret = qgroup_reserve(root, to_reserve, true, BTRFS_QGROUP_RSV_DATA);
37708c2ecf20Sopenharmony_ci	if (ret < 0)
37718c2ecf20Sopenharmony_ci		goto cleanup;
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci	return ret;
37748c2ecf20Sopenharmony_ci
37758c2ecf20Sopenharmony_cicleanup:
37768c2ecf20Sopenharmony_ci	qgroup_unreserve_range(inode, reserved, start, len);
37778c2ecf20Sopenharmony_ciout:
37788c2ecf20Sopenharmony_ci	if (new_reserved) {
37798c2ecf20Sopenharmony_ci		extent_changeset_release(reserved);
37808c2ecf20Sopenharmony_ci		kfree(reserved);
37818c2ecf20Sopenharmony_ci		*reserved_ret = NULL;
37828c2ecf20Sopenharmony_ci	}
37838c2ecf20Sopenharmony_ci	return ret;
37848c2ecf20Sopenharmony_ci}
37858c2ecf20Sopenharmony_ci
37868c2ecf20Sopenharmony_ci/*
37878c2ecf20Sopenharmony_ci * Reserve qgroup space for range [start, start + len).
37888c2ecf20Sopenharmony_ci *
37898c2ecf20Sopenharmony_ci * This function will either reserve space from related qgroups or do nothing
37908c2ecf20Sopenharmony_ci * if the range is already reserved.
37918c2ecf20Sopenharmony_ci *
37928c2ecf20Sopenharmony_ci * Return 0 for successful reservation
37938c2ecf20Sopenharmony_ci * Return <0 for error (including -EQUOT)
37948c2ecf20Sopenharmony_ci *
37958c2ecf20Sopenharmony_ci * NOTE: This function may sleep for memory allocation, dirty page flushing and
37968c2ecf20Sopenharmony_ci *	 commit transaction. So caller should not hold any dirty page locked.
37978c2ecf20Sopenharmony_ci */
37988c2ecf20Sopenharmony_ciint btrfs_qgroup_reserve_data(struct btrfs_inode *inode,
37998c2ecf20Sopenharmony_ci			struct extent_changeset **reserved_ret, u64 start,
38008c2ecf20Sopenharmony_ci			u64 len)
38018c2ecf20Sopenharmony_ci{
38028c2ecf20Sopenharmony_ci	int ret;
38038c2ecf20Sopenharmony_ci
38048c2ecf20Sopenharmony_ci	ret = qgroup_reserve_data(inode, reserved_ret, start, len);
38058c2ecf20Sopenharmony_ci	if (ret <= 0 && ret != -EDQUOT)
38068c2ecf20Sopenharmony_ci		return ret;
38078c2ecf20Sopenharmony_ci
38088c2ecf20Sopenharmony_ci	ret = try_flush_qgroup(inode->root);
38098c2ecf20Sopenharmony_ci	if (ret < 0)
38108c2ecf20Sopenharmony_ci		return ret;
38118c2ecf20Sopenharmony_ci	return qgroup_reserve_data(inode, reserved_ret, start, len);
38128c2ecf20Sopenharmony_ci}
38138c2ecf20Sopenharmony_ci
38148c2ecf20Sopenharmony_ci/* Free ranges specified by @reserved, normally in error path */
38158c2ecf20Sopenharmony_cistatic int qgroup_free_reserved_data(struct btrfs_inode *inode,
38168c2ecf20Sopenharmony_ci			struct extent_changeset *reserved, u64 start, u64 len)
38178c2ecf20Sopenharmony_ci{
38188c2ecf20Sopenharmony_ci	struct btrfs_root *root = inode->root;
38198c2ecf20Sopenharmony_ci	struct ulist_node *unode;
38208c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
38218c2ecf20Sopenharmony_ci	struct extent_changeset changeset;
38228c2ecf20Sopenharmony_ci	int freed = 0;
38238c2ecf20Sopenharmony_ci	int ret;
38248c2ecf20Sopenharmony_ci
38258c2ecf20Sopenharmony_ci	extent_changeset_init(&changeset);
38268c2ecf20Sopenharmony_ci	len = round_up(start + len, root->fs_info->sectorsize);
38278c2ecf20Sopenharmony_ci	start = round_down(start, root->fs_info->sectorsize);
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
38308c2ecf20Sopenharmony_ci	while ((unode = ulist_next(&reserved->range_changed, &uiter))) {
38318c2ecf20Sopenharmony_ci		u64 range_start = unode->val;
38328c2ecf20Sopenharmony_ci		/* unode->aux is the inclusive end */
38338c2ecf20Sopenharmony_ci		u64 range_len = unode->aux - range_start + 1;
38348c2ecf20Sopenharmony_ci		u64 free_start;
38358c2ecf20Sopenharmony_ci		u64 free_len;
38368c2ecf20Sopenharmony_ci
38378c2ecf20Sopenharmony_ci		extent_changeset_release(&changeset);
38388c2ecf20Sopenharmony_ci
38398c2ecf20Sopenharmony_ci		/* Only free range in range [start, start + len) */
38408c2ecf20Sopenharmony_ci		if (range_start >= start + len ||
38418c2ecf20Sopenharmony_ci		    range_start + range_len <= start)
38428c2ecf20Sopenharmony_ci			continue;
38438c2ecf20Sopenharmony_ci		free_start = max(range_start, start);
38448c2ecf20Sopenharmony_ci		free_len = min(start + len, range_start + range_len) -
38458c2ecf20Sopenharmony_ci			   free_start;
38468c2ecf20Sopenharmony_ci		/*
38478c2ecf20Sopenharmony_ci		 * TODO: To also modify reserved->ranges_reserved to reflect
38488c2ecf20Sopenharmony_ci		 * the modification.
38498c2ecf20Sopenharmony_ci		 *
38508c2ecf20Sopenharmony_ci		 * However as long as we free qgroup reserved according to
38518c2ecf20Sopenharmony_ci		 * EXTENT_QGROUP_RESERVED, we won't double free.
38528c2ecf20Sopenharmony_ci		 * So not need to rush.
38538c2ecf20Sopenharmony_ci		 */
38548c2ecf20Sopenharmony_ci		ret = clear_record_extent_bits(&inode->io_tree, free_start,
38558c2ecf20Sopenharmony_ci				free_start + free_len - 1,
38568c2ecf20Sopenharmony_ci				EXTENT_QGROUP_RESERVED, &changeset);
38578c2ecf20Sopenharmony_ci		if (ret < 0)
38588c2ecf20Sopenharmony_ci			goto out;
38598c2ecf20Sopenharmony_ci		freed += changeset.bytes_changed;
38608c2ecf20Sopenharmony_ci	}
38618c2ecf20Sopenharmony_ci	btrfs_qgroup_free_refroot(root->fs_info, root->root_key.objectid, freed,
38628c2ecf20Sopenharmony_ci				  BTRFS_QGROUP_RSV_DATA);
38638c2ecf20Sopenharmony_ci	ret = freed;
38648c2ecf20Sopenharmony_ciout:
38658c2ecf20Sopenharmony_ci	extent_changeset_release(&changeset);
38668c2ecf20Sopenharmony_ci	return ret;
38678c2ecf20Sopenharmony_ci}
38688c2ecf20Sopenharmony_ci
38698c2ecf20Sopenharmony_cistatic int __btrfs_qgroup_release_data(struct btrfs_inode *inode,
38708c2ecf20Sopenharmony_ci			struct extent_changeset *reserved, u64 start, u64 len,
38718c2ecf20Sopenharmony_ci			int free)
38728c2ecf20Sopenharmony_ci{
38738c2ecf20Sopenharmony_ci	struct extent_changeset changeset;
38748c2ecf20Sopenharmony_ci	int trace_op = QGROUP_RELEASE;
38758c2ecf20Sopenharmony_ci	int ret;
38768c2ecf20Sopenharmony_ci
38778c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &inode->root->fs_info->flags))
38788c2ecf20Sopenharmony_ci		return 0;
38798c2ecf20Sopenharmony_ci
38808c2ecf20Sopenharmony_ci	/* In release case, we shouldn't have @reserved */
38818c2ecf20Sopenharmony_ci	WARN_ON(!free && reserved);
38828c2ecf20Sopenharmony_ci	if (free && reserved)
38838c2ecf20Sopenharmony_ci		return qgroup_free_reserved_data(inode, reserved, start, len);
38848c2ecf20Sopenharmony_ci	extent_changeset_init(&changeset);
38858c2ecf20Sopenharmony_ci	ret = clear_record_extent_bits(&inode->io_tree, start, start + len -1,
38868c2ecf20Sopenharmony_ci				       EXTENT_QGROUP_RESERVED, &changeset);
38878c2ecf20Sopenharmony_ci	if (ret < 0)
38888c2ecf20Sopenharmony_ci		goto out;
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci	if (free)
38918c2ecf20Sopenharmony_ci		trace_op = QGROUP_FREE;
38928c2ecf20Sopenharmony_ci	trace_btrfs_qgroup_release_data(&inode->vfs_inode, start, len,
38938c2ecf20Sopenharmony_ci					changeset.bytes_changed, trace_op);
38948c2ecf20Sopenharmony_ci	if (free)
38958c2ecf20Sopenharmony_ci		btrfs_qgroup_free_refroot(inode->root->fs_info,
38968c2ecf20Sopenharmony_ci				inode->root->root_key.objectid,
38978c2ecf20Sopenharmony_ci				changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
38988c2ecf20Sopenharmony_ci	ret = changeset.bytes_changed;
38998c2ecf20Sopenharmony_ciout:
39008c2ecf20Sopenharmony_ci	extent_changeset_release(&changeset);
39018c2ecf20Sopenharmony_ci	return ret;
39028c2ecf20Sopenharmony_ci}
39038c2ecf20Sopenharmony_ci
39048c2ecf20Sopenharmony_ci/*
39058c2ecf20Sopenharmony_ci * Free a reserved space range from io_tree and related qgroups
39068c2ecf20Sopenharmony_ci *
39078c2ecf20Sopenharmony_ci * Should be called when a range of pages get invalidated before reaching disk.
39088c2ecf20Sopenharmony_ci * Or for error cleanup case.
39098c2ecf20Sopenharmony_ci * if @reserved is given, only reserved range in [@start, @start + @len) will
39108c2ecf20Sopenharmony_ci * be freed.
39118c2ecf20Sopenharmony_ci *
39128c2ecf20Sopenharmony_ci * For data written to disk, use btrfs_qgroup_release_data().
39138c2ecf20Sopenharmony_ci *
39148c2ecf20Sopenharmony_ci * NOTE: This function may sleep for memory allocation.
39158c2ecf20Sopenharmony_ci */
39168c2ecf20Sopenharmony_ciint btrfs_qgroup_free_data(struct btrfs_inode *inode,
39178c2ecf20Sopenharmony_ci			struct extent_changeset *reserved, u64 start, u64 len)
39188c2ecf20Sopenharmony_ci{
39198c2ecf20Sopenharmony_ci	return __btrfs_qgroup_release_data(inode, reserved, start, len, 1);
39208c2ecf20Sopenharmony_ci}
39218c2ecf20Sopenharmony_ci
39228c2ecf20Sopenharmony_ci/*
39238c2ecf20Sopenharmony_ci * Release a reserved space range from io_tree only.
39248c2ecf20Sopenharmony_ci *
39258c2ecf20Sopenharmony_ci * Should be called when a range of pages get written to disk and corresponding
39268c2ecf20Sopenharmony_ci * FILE_EXTENT is inserted into corresponding root.
39278c2ecf20Sopenharmony_ci *
39288c2ecf20Sopenharmony_ci * Since new qgroup accounting framework will only update qgroup numbers at
39298c2ecf20Sopenharmony_ci * commit_transaction() time, its reserved space shouldn't be freed from
39308c2ecf20Sopenharmony_ci * related qgroups.
39318c2ecf20Sopenharmony_ci *
39328c2ecf20Sopenharmony_ci * But we should release the range from io_tree, to allow further write to be
39338c2ecf20Sopenharmony_ci * COWed.
39348c2ecf20Sopenharmony_ci *
39358c2ecf20Sopenharmony_ci * NOTE: This function may sleep for memory allocation.
39368c2ecf20Sopenharmony_ci */
39378c2ecf20Sopenharmony_ciint btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len)
39388c2ecf20Sopenharmony_ci{
39398c2ecf20Sopenharmony_ci	return __btrfs_qgroup_release_data(inode, NULL, start, len, 0);
39408c2ecf20Sopenharmony_ci}
39418c2ecf20Sopenharmony_ci
39428c2ecf20Sopenharmony_cistatic void add_root_meta_rsv(struct btrfs_root *root, int num_bytes,
39438c2ecf20Sopenharmony_ci			      enum btrfs_qgroup_rsv_type type)
39448c2ecf20Sopenharmony_ci{
39458c2ecf20Sopenharmony_ci	if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
39468c2ecf20Sopenharmony_ci	    type != BTRFS_QGROUP_RSV_META_PERTRANS)
39478c2ecf20Sopenharmony_ci		return;
39488c2ecf20Sopenharmony_ci	if (num_bytes == 0)
39498c2ecf20Sopenharmony_ci		return;
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci	spin_lock(&root->qgroup_meta_rsv_lock);
39528c2ecf20Sopenharmony_ci	if (type == BTRFS_QGROUP_RSV_META_PREALLOC)
39538c2ecf20Sopenharmony_ci		root->qgroup_meta_rsv_prealloc += num_bytes;
39548c2ecf20Sopenharmony_ci	else
39558c2ecf20Sopenharmony_ci		root->qgroup_meta_rsv_pertrans += num_bytes;
39568c2ecf20Sopenharmony_ci	spin_unlock(&root->qgroup_meta_rsv_lock);
39578c2ecf20Sopenharmony_ci}
39588c2ecf20Sopenharmony_ci
39598c2ecf20Sopenharmony_cistatic int sub_root_meta_rsv(struct btrfs_root *root, int num_bytes,
39608c2ecf20Sopenharmony_ci			     enum btrfs_qgroup_rsv_type type)
39618c2ecf20Sopenharmony_ci{
39628c2ecf20Sopenharmony_ci	if (type != BTRFS_QGROUP_RSV_META_PREALLOC &&
39638c2ecf20Sopenharmony_ci	    type != BTRFS_QGROUP_RSV_META_PERTRANS)
39648c2ecf20Sopenharmony_ci		return 0;
39658c2ecf20Sopenharmony_ci	if (num_bytes == 0)
39668c2ecf20Sopenharmony_ci		return 0;
39678c2ecf20Sopenharmony_ci
39688c2ecf20Sopenharmony_ci	spin_lock(&root->qgroup_meta_rsv_lock);
39698c2ecf20Sopenharmony_ci	if (type == BTRFS_QGROUP_RSV_META_PREALLOC) {
39708c2ecf20Sopenharmony_ci		num_bytes = min_t(u64, root->qgroup_meta_rsv_prealloc,
39718c2ecf20Sopenharmony_ci				  num_bytes);
39728c2ecf20Sopenharmony_ci		root->qgroup_meta_rsv_prealloc -= num_bytes;
39738c2ecf20Sopenharmony_ci	} else {
39748c2ecf20Sopenharmony_ci		num_bytes = min_t(u64, root->qgroup_meta_rsv_pertrans,
39758c2ecf20Sopenharmony_ci				  num_bytes);
39768c2ecf20Sopenharmony_ci		root->qgroup_meta_rsv_pertrans -= num_bytes;
39778c2ecf20Sopenharmony_ci	}
39788c2ecf20Sopenharmony_ci	spin_unlock(&root->qgroup_meta_rsv_lock);
39798c2ecf20Sopenharmony_ci	return num_bytes;
39808c2ecf20Sopenharmony_ci}
39818c2ecf20Sopenharmony_ci
39828c2ecf20Sopenharmony_ciint btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
39838c2ecf20Sopenharmony_ci			      enum btrfs_qgroup_rsv_type type, bool enforce)
39848c2ecf20Sopenharmony_ci{
39858c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
39868c2ecf20Sopenharmony_ci	int ret;
39878c2ecf20Sopenharmony_ci
39888c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
39898c2ecf20Sopenharmony_ci	    !is_fstree(root->root_key.objectid) || num_bytes == 0)
39908c2ecf20Sopenharmony_ci		return 0;
39918c2ecf20Sopenharmony_ci
39928c2ecf20Sopenharmony_ci	BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
39938c2ecf20Sopenharmony_ci	trace_qgroup_meta_reserve(root, (s64)num_bytes, type);
39948c2ecf20Sopenharmony_ci	ret = qgroup_reserve(root, num_bytes, enforce, type);
39958c2ecf20Sopenharmony_ci	if (ret < 0)
39968c2ecf20Sopenharmony_ci		return ret;
39978c2ecf20Sopenharmony_ci	/*
39988c2ecf20Sopenharmony_ci	 * Record what we have reserved into root.
39998c2ecf20Sopenharmony_ci	 *
40008c2ecf20Sopenharmony_ci	 * To avoid quota disabled->enabled underflow.
40018c2ecf20Sopenharmony_ci	 * In that case, we may try to free space we haven't reserved
40028c2ecf20Sopenharmony_ci	 * (since quota was disabled), so record what we reserved into root.
40038c2ecf20Sopenharmony_ci	 * And ensure later release won't underflow this number.
40048c2ecf20Sopenharmony_ci	 */
40058c2ecf20Sopenharmony_ci	add_root_meta_rsv(root, num_bytes, type);
40068c2ecf20Sopenharmony_ci	return ret;
40078c2ecf20Sopenharmony_ci}
40088c2ecf20Sopenharmony_ci
40098c2ecf20Sopenharmony_ciint __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
40108c2ecf20Sopenharmony_ci				enum btrfs_qgroup_rsv_type type, bool enforce)
40118c2ecf20Sopenharmony_ci{
40128c2ecf20Sopenharmony_ci	int ret;
40138c2ecf20Sopenharmony_ci
40148c2ecf20Sopenharmony_ci	ret = btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce);
40158c2ecf20Sopenharmony_ci	if (ret <= 0 && ret != -EDQUOT)
40168c2ecf20Sopenharmony_ci		return ret;
40178c2ecf20Sopenharmony_ci
40188c2ecf20Sopenharmony_ci	ret = try_flush_qgroup(root);
40198c2ecf20Sopenharmony_ci	if (ret < 0)
40208c2ecf20Sopenharmony_ci		return ret;
40218c2ecf20Sopenharmony_ci	return btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce);
40228c2ecf20Sopenharmony_ci}
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_civoid btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root)
40258c2ecf20Sopenharmony_ci{
40268c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
40298c2ecf20Sopenharmony_ci	    !is_fstree(root->root_key.objectid))
40308c2ecf20Sopenharmony_ci		return;
40318c2ecf20Sopenharmony_ci
40328c2ecf20Sopenharmony_ci	/* TODO: Update trace point to handle such free */
40338c2ecf20Sopenharmony_ci	trace_qgroup_meta_free_all_pertrans(root);
40348c2ecf20Sopenharmony_ci	/* Special value -1 means to free all reserved space */
40358c2ecf20Sopenharmony_ci	btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid, (u64)-1,
40368c2ecf20Sopenharmony_ci				  BTRFS_QGROUP_RSV_META_PERTRANS);
40378c2ecf20Sopenharmony_ci}
40388c2ecf20Sopenharmony_ci
40398c2ecf20Sopenharmony_civoid __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
40408c2ecf20Sopenharmony_ci			      enum btrfs_qgroup_rsv_type type)
40418c2ecf20Sopenharmony_ci{
40428c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
40438c2ecf20Sopenharmony_ci
40448c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
40458c2ecf20Sopenharmony_ci	    !is_fstree(root->root_key.objectid))
40468c2ecf20Sopenharmony_ci		return;
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci	/*
40498c2ecf20Sopenharmony_ci	 * reservation for META_PREALLOC can happen before quota is enabled,
40508c2ecf20Sopenharmony_ci	 * which can lead to underflow.
40518c2ecf20Sopenharmony_ci	 * Here ensure we will only free what we really have reserved.
40528c2ecf20Sopenharmony_ci	 */
40538c2ecf20Sopenharmony_ci	num_bytes = sub_root_meta_rsv(root, num_bytes, type);
40548c2ecf20Sopenharmony_ci	BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
40558c2ecf20Sopenharmony_ci	trace_qgroup_meta_reserve(root, -(s64)num_bytes, type);
40568c2ecf20Sopenharmony_ci	btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid,
40578c2ecf20Sopenharmony_ci				  num_bytes, type);
40588c2ecf20Sopenharmony_ci}
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_cistatic void qgroup_convert_meta(struct btrfs_fs_info *fs_info, u64 ref_root,
40618c2ecf20Sopenharmony_ci				int num_bytes)
40628c2ecf20Sopenharmony_ci{
40638c2ecf20Sopenharmony_ci	struct btrfs_qgroup *qgroup;
40648c2ecf20Sopenharmony_ci	struct ulist_node *unode;
40658c2ecf20Sopenharmony_ci	struct ulist_iterator uiter;
40668c2ecf20Sopenharmony_ci	int ret = 0;
40678c2ecf20Sopenharmony_ci
40688c2ecf20Sopenharmony_ci	if (num_bytes == 0)
40698c2ecf20Sopenharmony_ci		return;
40708c2ecf20Sopenharmony_ci	if (!fs_info->quota_root)
40718c2ecf20Sopenharmony_ci		return;
40728c2ecf20Sopenharmony_ci
40738c2ecf20Sopenharmony_ci	spin_lock(&fs_info->qgroup_lock);
40748c2ecf20Sopenharmony_ci	qgroup = find_qgroup_rb(fs_info, ref_root);
40758c2ecf20Sopenharmony_ci	if (!qgroup)
40768c2ecf20Sopenharmony_ci		goto out;
40778c2ecf20Sopenharmony_ci	ulist_reinit(fs_info->qgroup_ulist);
40788c2ecf20Sopenharmony_ci	ret = ulist_add(fs_info->qgroup_ulist, qgroup->qgroupid,
40798c2ecf20Sopenharmony_ci		       qgroup_to_aux(qgroup), GFP_ATOMIC);
40808c2ecf20Sopenharmony_ci	if (ret < 0)
40818c2ecf20Sopenharmony_ci		goto out;
40828c2ecf20Sopenharmony_ci	ULIST_ITER_INIT(&uiter);
40838c2ecf20Sopenharmony_ci	while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) {
40848c2ecf20Sopenharmony_ci		struct btrfs_qgroup *qg;
40858c2ecf20Sopenharmony_ci		struct btrfs_qgroup_list *glist;
40868c2ecf20Sopenharmony_ci
40878c2ecf20Sopenharmony_ci		qg = unode_aux_to_qgroup(unode);
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci		qgroup_rsv_release(fs_info, qg, num_bytes,
40908c2ecf20Sopenharmony_ci				BTRFS_QGROUP_RSV_META_PREALLOC);
40918c2ecf20Sopenharmony_ci		qgroup_rsv_add(fs_info, qg, num_bytes,
40928c2ecf20Sopenharmony_ci				BTRFS_QGROUP_RSV_META_PERTRANS);
40938c2ecf20Sopenharmony_ci		list_for_each_entry(glist, &qg->groups, next_group) {
40948c2ecf20Sopenharmony_ci			ret = ulist_add(fs_info->qgroup_ulist,
40958c2ecf20Sopenharmony_ci					glist->group->qgroupid,
40968c2ecf20Sopenharmony_ci					qgroup_to_aux(glist->group), GFP_ATOMIC);
40978c2ecf20Sopenharmony_ci			if (ret < 0)
40988c2ecf20Sopenharmony_ci				goto out;
40998c2ecf20Sopenharmony_ci		}
41008c2ecf20Sopenharmony_ci	}
41018c2ecf20Sopenharmony_ciout:
41028c2ecf20Sopenharmony_ci	spin_unlock(&fs_info->qgroup_lock);
41038c2ecf20Sopenharmony_ci}
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_civoid btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
41068c2ecf20Sopenharmony_ci{
41078c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
41088c2ecf20Sopenharmony_ci
41098c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) ||
41108c2ecf20Sopenharmony_ci	    !is_fstree(root->root_key.objectid))
41118c2ecf20Sopenharmony_ci		return;
41128c2ecf20Sopenharmony_ci	/* Same as btrfs_qgroup_free_meta_prealloc() */
41138c2ecf20Sopenharmony_ci	num_bytes = sub_root_meta_rsv(root, num_bytes,
41148c2ecf20Sopenharmony_ci				      BTRFS_QGROUP_RSV_META_PREALLOC);
41158c2ecf20Sopenharmony_ci	trace_qgroup_meta_convert(root, num_bytes);
41168c2ecf20Sopenharmony_ci	qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
41178c2ecf20Sopenharmony_ci}
41188c2ecf20Sopenharmony_ci
41198c2ecf20Sopenharmony_ci/*
41208c2ecf20Sopenharmony_ci * Check qgroup reserved space leaking, normally at destroy inode
41218c2ecf20Sopenharmony_ci * time
41228c2ecf20Sopenharmony_ci */
41238c2ecf20Sopenharmony_civoid btrfs_qgroup_check_reserved_leak(struct btrfs_inode *inode)
41248c2ecf20Sopenharmony_ci{
41258c2ecf20Sopenharmony_ci	struct extent_changeset changeset;
41268c2ecf20Sopenharmony_ci	struct ulist_node *unode;
41278c2ecf20Sopenharmony_ci	struct ulist_iterator iter;
41288c2ecf20Sopenharmony_ci	int ret;
41298c2ecf20Sopenharmony_ci
41308c2ecf20Sopenharmony_ci	extent_changeset_init(&changeset);
41318c2ecf20Sopenharmony_ci	ret = clear_record_extent_bits(&inode->io_tree, 0, (u64)-1,
41328c2ecf20Sopenharmony_ci			EXTENT_QGROUP_RESERVED, &changeset);
41338c2ecf20Sopenharmony_ci
41348c2ecf20Sopenharmony_ci	WARN_ON(ret < 0);
41358c2ecf20Sopenharmony_ci	if (WARN_ON(changeset.bytes_changed)) {
41368c2ecf20Sopenharmony_ci		ULIST_ITER_INIT(&iter);
41378c2ecf20Sopenharmony_ci		while ((unode = ulist_next(&changeset.range_changed, &iter))) {
41388c2ecf20Sopenharmony_ci			btrfs_warn(inode->root->fs_info,
41398c2ecf20Sopenharmony_ci		"leaking qgroup reserved space, ino: %llu, start: %llu, end: %llu",
41408c2ecf20Sopenharmony_ci				btrfs_ino(inode), unode->val, unode->aux);
41418c2ecf20Sopenharmony_ci		}
41428c2ecf20Sopenharmony_ci		btrfs_qgroup_free_refroot(inode->root->fs_info,
41438c2ecf20Sopenharmony_ci				inode->root->root_key.objectid,
41448c2ecf20Sopenharmony_ci				changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci	}
41478c2ecf20Sopenharmony_ci	extent_changeset_release(&changeset);
41488c2ecf20Sopenharmony_ci}
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_civoid btrfs_qgroup_init_swapped_blocks(
41518c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_blocks *swapped_blocks)
41528c2ecf20Sopenharmony_ci{
41538c2ecf20Sopenharmony_ci	int i;
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci	spin_lock_init(&swapped_blocks->lock);
41568c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_MAX_LEVEL; i++)
41578c2ecf20Sopenharmony_ci		swapped_blocks->blocks[i] = RB_ROOT;
41588c2ecf20Sopenharmony_ci	swapped_blocks->swapped = false;
41598c2ecf20Sopenharmony_ci}
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci/*
41628c2ecf20Sopenharmony_ci * Delete all swapped blocks record of @root.
41638c2ecf20Sopenharmony_ci * Every record here means we skipped a full subtree scan for qgroup.
41648c2ecf20Sopenharmony_ci *
41658c2ecf20Sopenharmony_ci * Gets called when committing one transaction.
41668c2ecf20Sopenharmony_ci */
41678c2ecf20Sopenharmony_civoid btrfs_qgroup_clean_swapped_blocks(struct btrfs_root *root)
41688c2ecf20Sopenharmony_ci{
41698c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_blocks *swapped_blocks;
41708c2ecf20Sopenharmony_ci	int i;
41718c2ecf20Sopenharmony_ci
41728c2ecf20Sopenharmony_ci	swapped_blocks = &root->swapped_blocks;
41738c2ecf20Sopenharmony_ci
41748c2ecf20Sopenharmony_ci	spin_lock(&swapped_blocks->lock);
41758c2ecf20Sopenharmony_ci	if (!swapped_blocks->swapped)
41768c2ecf20Sopenharmony_ci		goto out;
41778c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
41788c2ecf20Sopenharmony_ci		struct rb_root *cur_root = &swapped_blocks->blocks[i];
41798c2ecf20Sopenharmony_ci		struct btrfs_qgroup_swapped_block *entry;
41808c2ecf20Sopenharmony_ci		struct btrfs_qgroup_swapped_block *next;
41818c2ecf20Sopenharmony_ci
41828c2ecf20Sopenharmony_ci		rbtree_postorder_for_each_entry_safe(entry, next, cur_root,
41838c2ecf20Sopenharmony_ci						     node)
41848c2ecf20Sopenharmony_ci			kfree(entry);
41858c2ecf20Sopenharmony_ci		swapped_blocks->blocks[i] = RB_ROOT;
41868c2ecf20Sopenharmony_ci	}
41878c2ecf20Sopenharmony_ci	swapped_blocks->swapped = false;
41888c2ecf20Sopenharmony_ciout:
41898c2ecf20Sopenharmony_ci	spin_unlock(&swapped_blocks->lock);
41908c2ecf20Sopenharmony_ci}
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_ci/*
41938c2ecf20Sopenharmony_ci * Add subtree roots record into @subvol_root.
41948c2ecf20Sopenharmony_ci *
41958c2ecf20Sopenharmony_ci * @subvol_root:	tree root of the subvolume tree get swapped
41968c2ecf20Sopenharmony_ci * @bg:			block group under balance
41978c2ecf20Sopenharmony_ci * @subvol_parent/slot:	pointer to the subtree root in subvolume tree
41988c2ecf20Sopenharmony_ci * @reloc_parent/slot:	pointer to the subtree root in reloc tree
41998c2ecf20Sopenharmony_ci *			BOTH POINTERS ARE BEFORE TREE SWAP
42008c2ecf20Sopenharmony_ci * @last_snapshot:	last snapshot generation of the subvolume tree
42018c2ecf20Sopenharmony_ci */
42028c2ecf20Sopenharmony_ciint btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
42038c2ecf20Sopenharmony_ci		struct btrfs_root *subvol_root,
42048c2ecf20Sopenharmony_ci		struct btrfs_block_group *bg,
42058c2ecf20Sopenharmony_ci		struct extent_buffer *subvol_parent, int subvol_slot,
42068c2ecf20Sopenharmony_ci		struct extent_buffer *reloc_parent, int reloc_slot,
42078c2ecf20Sopenharmony_ci		u64 last_snapshot)
42088c2ecf20Sopenharmony_ci{
42098c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = subvol_root->fs_info;
42108c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_blocks *blocks = &subvol_root->swapped_blocks;
42118c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_block *block;
42128c2ecf20Sopenharmony_ci	struct rb_node **cur;
42138c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
42148c2ecf20Sopenharmony_ci	int level = btrfs_header_level(subvol_parent) - 1;
42158c2ecf20Sopenharmony_ci	int ret = 0;
42168c2ecf20Sopenharmony_ci
42178c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
42188c2ecf20Sopenharmony_ci		return 0;
42198c2ecf20Sopenharmony_ci
42208c2ecf20Sopenharmony_ci	if (btrfs_node_ptr_generation(subvol_parent, subvol_slot) >
42218c2ecf20Sopenharmony_ci	    btrfs_node_ptr_generation(reloc_parent, reloc_slot)) {
42228c2ecf20Sopenharmony_ci		btrfs_err_rl(fs_info,
42238c2ecf20Sopenharmony_ci		"%s: bad parameter order, subvol_gen=%llu reloc_gen=%llu",
42248c2ecf20Sopenharmony_ci			__func__,
42258c2ecf20Sopenharmony_ci			btrfs_node_ptr_generation(subvol_parent, subvol_slot),
42268c2ecf20Sopenharmony_ci			btrfs_node_ptr_generation(reloc_parent, reloc_slot));
42278c2ecf20Sopenharmony_ci		return -EUCLEAN;
42288c2ecf20Sopenharmony_ci	}
42298c2ecf20Sopenharmony_ci
42308c2ecf20Sopenharmony_ci	block = kmalloc(sizeof(*block), GFP_NOFS);
42318c2ecf20Sopenharmony_ci	if (!block) {
42328c2ecf20Sopenharmony_ci		ret = -ENOMEM;
42338c2ecf20Sopenharmony_ci		goto out;
42348c2ecf20Sopenharmony_ci	}
42358c2ecf20Sopenharmony_ci
42368c2ecf20Sopenharmony_ci	/*
42378c2ecf20Sopenharmony_ci	 * @reloc_parent/slot is still before swap, while @block is going to
42388c2ecf20Sopenharmony_ci	 * record the bytenr after swap, so we do the swap here.
42398c2ecf20Sopenharmony_ci	 */
42408c2ecf20Sopenharmony_ci	block->subvol_bytenr = btrfs_node_blockptr(reloc_parent, reloc_slot);
42418c2ecf20Sopenharmony_ci	block->subvol_generation = btrfs_node_ptr_generation(reloc_parent,
42428c2ecf20Sopenharmony_ci							     reloc_slot);
42438c2ecf20Sopenharmony_ci	block->reloc_bytenr = btrfs_node_blockptr(subvol_parent, subvol_slot);
42448c2ecf20Sopenharmony_ci	block->reloc_generation = btrfs_node_ptr_generation(subvol_parent,
42458c2ecf20Sopenharmony_ci							    subvol_slot);
42468c2ecf20Sopenharmony_ci	block->last_snapshot = last_snapshot;
42478c2ecf20Sopenharmony_ci	block->level = level;
42488c2ecf20Sopenharmony_ci
42498c2ecf20Sopenharmony_ci	/*
42508c2ecf20Sopenharmony_ci	 * If we have bg == NULL, we're called from btrfs_recover_relocation(),
42518c2ecf20Sopenharmony_ci	 * no one else can modify tree blocks thus we qgroup will not change
42528c2ecf20Sopenharmony_ci	 * no matter the value of trace_leaf.
42538c2ecf20Sopenharmony_ci	 */
42548c2ecf20Sopenharmony_ci	if (bg && bg->flags & BTRFS_BLOCK_GROUP_DATA)
42558c2ecf20Sopenharmony_ci		block->trace_leaf = true;
42568c2ecf20Sopenharmony_ci	else
42578c2ecf20Sopenharmony_ci		block->trace_leaf = false;
42588c2ecf20Sopenharmony_ci	btrfs_node_key_to_cpu(reloc_parent, &block->first_key, reloc_slot);
42598c2ecf20Sopenharmony_ci
42608c2ecf20Sopenharmony_ci	/* Insert @block into @blocks */
42618c2ecf20Sopenharmony_ci	spin_lock(&blocks->lock);
42628c2ecf20Sopenharmony_ci	cur = &blocks->blocks[level].rb_node;
42638c2ecf20Sopenharmony_ci	while (*cur) {
42648c2ecf20Sopenharmony_ci		struct btrfs_qgroup_swapped_block *entry;
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci		parent = *cur;
42678c2ecf20Sopenharmony_ci		entry = rb_entry(parent, struct btrfs_qgroup_swapped_block,
42688c2ecf20Sopenharmony_ci				 node);
42698c2ecf20Sopenharmony_ci
42708c2ecf20Sopenharmony_ci		if (entry->subvol_bytenr < block->subvol_bytenr) {
42718c2ecf20Sopenharmony_ci			cur = &(*cur)->rb_left;
42728c2ecf20Sopenharmony_ci		} else if (entry->subvol_bytenr > block->subvol_bytenr) {
42738c2ecf20Sopenharmony_ci			cur = &(*cur)->rb_right;
42748c2ecf20Sopenharmony_ci		} else {
42758c2ecf20Sopenharmony_ci			if (entry->subvol_generation !=
42768c2ecf20Sopenharmony_ci					block->subvol_generation ||
42778c2ecf20Sopenharmony_ci			    entry->reloc_bytenr != block->reloc_bytenr ||
42788c2ecf20Sopenharmony_ci			    entry->reloc_generation !=
42798c2ecf20Sopenharmony_ci					block->reloc_generation) {
42808c2ecf20Sopenharmony_ci				/*
42818c2ecf20Sopenharmony_ci				 * Duplicated but mismatch entry found.
42828c2ecf20Sopenharmony_ci				 * Shouldn't happen.
42838c2ecf20Sopenharmony_ci				 *
42848c2ecf20Sopenharmony_ci				 * Marking qgroup inconsistent should be enough
42858c2ecf20Sopenharmony_ci				 * for end users.
42868c2ecf20Sopenharmony_ci				 */
42878c2ecf20Sopenharmony_ci				WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
42888c2ecf20Sopenharmony_ci				ret = -EEXIST;
42898c2ecf20Sopenharmony_ci			}
42908c2ecf20Sopenharmony_ci			kfree(block);
42918c2ecf20Sopenharmony_ci			goto out_unlock;
42928c2ecf20Sopenharmony_ci		}
42938c2ecf20Sopenharmony_ci	}
42948c2ecf20Sopenharmony_ci	rb_link_node(&block->node, parent, cur);
42958c2ecf20Sopenharmony_ci	rb_insert_color(&block->node, &blocks->blocks[level]);
42968c2ecf20Sopenharmony_ci	blocks->swapped = true;
42978c2ecf20Sopenharmony_ciout_unlock:
42988c2ecf20Sopenharmony_ci	spin_unlock(&blocks->lock);
42998c2ecf20Sopenharmony_ciout:
43008c2ecf20Sopenharmony_ci	if (ret < 0)
43018c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |=
43028c2ecf20Sopenharmony_ci			BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
43038c2ecf20Sopenharmony_ci	return ret;
43048c2ecf20Sopenharmony_ci}
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_ci/*
43078c2ecf20Sopenharmony_ci * Check if the tree block is a subtree root, and if so do the needed
43088c2ecf20Sopenharmony_ci * delayed subtree trace for qgroup.
43098c2ecf20Sopenharmony_ci *
43108c2ecf20Sopenharmony_ci * This is called during btrfs_cow_block().
43118c2ecf20Sopenharmony_ci */
43128c2ecf20Sopenharmony_ciint btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
43138c2ecf20Sopenharmony_ci					 struct btrfs_root *root,
43148c2ecf20Sopenharmony_ci					 struct extent_buffer *subvol_eb)
43158c2ecf20Sopenharmony_ci{
43168c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = root->fs_info;
43178c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_blocks *blocks = &root->swapped_blocks;
43188c2ecf20Sopenharmony_ci	struct btrfs_qgroup_swapped_block *block;
43198c2ecf20Sopenharmony_ci	struct extent_buffer *reloc_eb = NULL;
43208c2ecf20Sopenharmony_ci	struct rb_node *node;
43218c2ecf20Sopenharmony_ci	bool found = false;
43228c2ecf20Sopenharmony_ci	bool swapped = false;
43238c2ecf20Sopenharmony_ci	int level = btrfs_header_level(subvol_eb);
43248c2ecf20Sopenharmony_ci	int ret = 0;
43258c2ecf20Sopenharmony_ci	int i;
43268c2ecf20Sopenharmony_ci
43278c2ecf20Sopenharmony_ci	if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
43288c2ecf20Sopenharmony_ci		return 0;
43298c2ecf20Sopenharmony_ci	if (!is_fstree(root->root_key.objectid) || !root->reloc_root)
43308c2ecf20Sopenharmony_ci		return 0;
43318c2ecf20Sopenharmony_ci
43328c2ecf20Sopenharmony_ci	spin_lock(&blocks->lock);
43338c2ecf20Sopenharmony_ci	if (!blocks->swapped) {
43348c2ecf20Sopenharmony_ci		spin_unlock(&blocks->lock);
43358c2ecf20Sopenharmony_ci		return 0;
43368c2ecf20Sopenharmony_ci	}
43378c2ecf20Sopenharmony_ci	node = blocks->blocks[level].rb_node;
43388c2ecf20Sopenharmony_ci
43398c2ecf20Sopenharmony_ci	while (node) {
43408c2ecf20Sopenharmony_ci		block = rb_entry(node, struct btrfs_qgroup_swapped_block, node);
43418c2ecf20Sopenharmony_ci		if (block->subvol_bytenr < subvol_eb->start) {
43428c2ecf20Sopenharmony_ci			node = node->rb_left;
43438c2ecf20Sopenharmony_ci		} else if (block->subvol_bytenr > subvol_eb->start) {
43448c2ecf20Sopenharmony_ci			node = node->rb_right;
43458c2ecf20Sopenharmony_ci		} else {
43468c2ecf20Sopenharmony_ci			found = true;
43478c2ecf20Sopenharmony_ci			break;
43488c2ecf20Sopenharmony_ci		}
43498c2ecf20Sopenharmony_ci	}
43508c2ecf20Sopenharmony_ci	if (!found) {
43518c2ecf20Sopenharmony_ci		spin_unlock(&blocks->lock);
43528c2ecf20Sopenharmony_ci		goto out;
43538c2ecf20Sopenharmony_ci	}
43548c2ecf20Sopenharmony_ci	/* Found one, remove it from @blocks first and update blocks->swapped */
43558c2ecf20Sopenharmony_ci	rb_erase(&block->node, &blocks->blocks[level]);
43568c2ecf20Sopenharmony_ci	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
43578c2ecf20Sopenharmony_ci		if (RB_EMPTY_ROOT(&blocks->blocks[i])) {
43588c2ecf20Sopenharmony_ci			swapped = true;
43598c2ecf20Sopenharmony_ci			break;
43608c2ecf20Sopenharmony_ci		}
43618c2ecf20Sopenharmony_ci	}
43628c2ecf20Sopenharmony_ci	blocks->swapped = swapped;
43638c2ecf20Sopenharmony_ci	spin_unlock(&blocks->lock);
43648c2ecf20Sopenharmony_ci
43658c2ecf20Sopenharmony_ci	/* Read out reloc subtree root */
43668c2ecf20Sopenharmony_ci	reloc_eb = read_tree_block(fs_info, block->reloc_bytenr,
43678c2ecf20Sopenharmony_ci				   block->reloc_generation, block->level,
43688c2ecf20Sopenharmony_ci				   &block->first_key);
43698c2ecf20Sopenharmony_ci	if (IS_ERR(reloc_eb)) {
43708c2ecf20Sopenharmony_ci		ret = PTR_ERR(reloc_eb);
43718c2ecf20Sopenharmony_ci		reloc_eb = NULL;
43728c2ecf20Sopenharmony_ci		goto free_out;
43738c2ecf20Sopenharmony_ci	}
43748c2ecf20Sopenharmony_ci	if (!extent_buffer_uptodate(reloc_eb)) {
43758c2ecf20Sopenharmony_ci		ret = -EIO;
43768c2ecf20Sopenharmony_ci		goto free_out;
43778c2ecf20Sopenharmony_ci	}
43788c2ecf20Sopenharmony_ci
43798c2ecf20Sopenharmony_ci	ret = qgroup_trace_subtree_swap(trans, reloc_eb, subvol_eb,
43808c2ecf20Sopenharmony_ci			block->last_snapshot, block->trace_leaf);
43818c2ecf20Sopenharmony_cifree_out:
43828c2ecf20Sopenharmony_ci	kfree(block);
43838c2ecf20Sopenharmony_ci	free_extent_buffer(reloc_eb);
43848c2ecf20Sopenharmony_ciout:
43858c2ecf20Sopenharmony_ci	if (ret < 0) {
43868c2ecf20Sopenharmony_ci		btrfs_err_rl(fs_info,
43878c2ecf20Sopenharmony_ci			     "failed to account subtree at bytenr %llu: %d",
43888c2ecf20Sopenharmony_ci			     subvol_eb->start, ret);
43898c2ecf20Sopenharmony_ci		fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
43908c2ecf20Sopenharmony_ci	}
43918c2ecf20Sopenharmony_ci	return ret;
43928c2ecf20Sopenharmony_ci}
43938c2ecf20Sopenharmony_ci
43948c2ecf20Sopenharmony_civoid btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
43958c2ecf20Sopenharmony_ci{
43968c2ecf20Sopenharmony_ci	struct btrfs_qgroup_extent_record *entry;
43978c2ecf20Sopenharmony_ci	struct btrfs_qgroup_extent_record *next;
43988c2ecf20Sopenharmony_ci	struct rb_root *root;
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci	root = &trans->delayed_refs.dirty_extent_root;
44018c2ecf20Sopenharmony_ci	rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
44028c2ecf20Sopenharmony_ci		ulist_free(entry->old_roots);
44038c2ecf20Sopenharmony_ci		kfree(entry);
44048c2ecf20Sopenharmony_ci	}
44058c2ecf20Sopenharmony_ci	*root = RB_ROOT;
44068c2ecf20Sopenharmony_ci}
4407