xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision 770e0cc0)
1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0
2faa2dbf0SJosef Bacik /*
3faa2dbf0SJosef Bacik  * Copyright (C) 2013 Facebook.  All rights reserved.
4faa2dbf0SJosef Bacik  */
5faa2dbf0SJosef Bacik 
6b9ef22deSFeifei Xu #include <linux/types.h>
7faa2dbf0SJosef Bacik #include "btrfs-tests.h"
8faa2dbf0SJosef Bacik #include "../ctree.h"
9faa2dbf0SJosef Bacik #include "../transaction.h"
10faa2dbf0SJosef Bacik #include "../disk-io.h"
11faa2dbf0SJosef Bacik #include "../qgroup.h"
12442244c9SQu Wenruo #include "../backref.h"
13faa2dbf0SJosef Bacik 
14faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
15faa2dbf0SJosef Bacik 				  u64 num_bytes, u64 parent, u64 root_objectid)
16faa2dbf0SJosef Bacik {
17faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
18faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
19faa2dbf0SJosef Bacik 	struct btrfs_extent_inline_ref *iref;
20faa2dbf0SJosef Bacik 	struct btrfs_tree_block_info *block_info;
21faa2dbf0SJosef Bacik 	struct btrfs_path *path;
22faa2dbf0SJosef Bacik 	struct extent_buffer *leaf;
23faa2dbf0SJosef Bacik 	struct btrfs_key ins;
24faa2dbf0SJosef Bacik 	u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
25faa2dbf0SJosef Bacik 	int ret;
26faa2dbf0SJosef Bacik 
27483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
28faa2dbf0SJosef Bacik 
29faa2dbf0SJosef Bacik 	ins.objectid = bytenr;
30faa2dbf0SJosef Bacik 	ins.type = BTRFS_EXTENT_ITEM_KEY;
31faa2dbf0SJosef Bacik 	ins.offset = num_bytes;
32faa2dbf0SJosef Bacik 
33faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
34faa2dbf0SJosef Bacik 	if (!path) {
35770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
36faa2dbf0SJosef Bacik 		return -ENOMEM;
37faa2dbf0SJosef Bacik 	}
38faa2dbf0SJosef Bacik 
39faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
40faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
41faa2dbf0SJosef Bacik 	if (ret) {
423c7251f2SDavid Sterba 		test_err("couldn't insert ref %d", ret);
43faa2dbf0SJosef Bacik 		btrfs_free_path(path);
44faa2dbf0SJosef Bacik 		return ret;
45faa2dbf0SJosef Bacik 	}
46faa2dbf0SJosef Bacik 
47faa2dbf0SJosef Bacik 	leaf = path->nodes[0];
48faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
49faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(leaf, item, 1);
50faa2dbf0SJosef Bacik 	btrfs_set_extent_generation(leaf, item, 1);
51faa2dbf0SJosef Bacik 	btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
52faa2dbf0SJosef Bacik 	block_info = (struct btrfs_tree_block_info *)(item + 1);
533c0efdf0SQu Wenruo 	btrfs_set_tree_block_level(leaf, block_info, 0);
54faa2dbf0SJosef Bacik 	iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
55faa2dbf0SJosef Bacik 	if (parent > 0) {
56faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref,
57faa2dbf0SJosef Bacik 						 BTRFS_SHARED_BLOCK_REF_KEY);
58faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
59faa2dbf0SJosef Bacik 	} else {
60faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
61faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
62faa2dbf0SJosef Bacik 	}
63faa2dbf0SJosef Bacik 	btrfs_free_path(path);
64faa2dbf0SJosef Bacik 	return 0;
65faa2dbf0SJosef Bacik }
66faa2dbf0SJosef Bacik 
67faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
68faa2dbf0SJosef Bacik 			u64 parent, u64 root_objectid)
69faa2dbf0SJosef Bacik {
70faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
71faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
72faa2dbf0SJosef Bacik 	struct btrfs_path *path;
73faa2dbf0SJosef Bacik 	struct btrfs_key key;
74faa2dbf0SJosef Bacik 	u64 refs;
75faa2dbf0SJosef Bacik 	int ret;
76faa2dbf0SJosef Bacik 
77483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
78faa2dbf0SJosef Bacik 
79faa2dbf0SJosef Bacik 	key.objectid = bytenr;
80faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
81faa2dbf0SJosef Bacik 	key.offset = num_bytes;
82faa2dbf0SJosef Bacik 
83faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
84faa2dbf0SJosef Bacik 	if (!path) {
85770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
86faa2dbf0SJosef Bacik 		return -ENOMEM;
87faa2dbf0SJosef Bacik 	}
88faa2dbf0SJosef Bacik 
89faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
90faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
91faa2dbf0SJosef Bacik 	if (ret) {
923c7251f2SDavid Sterba 		test_err("couldn't find extent ref");
93faa2dbf0SJosef Bacik 		btrfs_free_path(path);
94faa2dbf0SJosef Bacik 		return ret;
95faa2dbf0SJosef Bacik 	}
96faa2dbf0SJosef Bacik 
97faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
98faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
99faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
100faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs + 1);
101faa2dbf0SJosef Bacik 	btrfs_release_path(path);
102faa2dbf0SJosef Bacik 
103faa2dbf0SJosef Bacik 	key.objectid = bytenr;
104faa2dbf0SJosef Bacik 	if (parent) {
105faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
106faa2dbf0SJosef Bacik 		key.offset = parent;
107faa2dbf0SJosef Bacik 	} else {
108faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
109faa2dbf0SJosef Bacik 		key.offset = root_objectid;
110faa2dbf0SJosef Bacik 	}
111faa2dbf0SJosef Bacik 
112faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
113faa2dbf0SJosef Bacik 	if (ret)
1143c7251f2SDavid Sterba 		test_err("failed to insert backref");
115faa2dbf0SJosef Bacik 	btrfs_free_path(path);
116faa2dbf0SJosef Bacik 	return ret;
117faa2dbf0SJosef Bacik }
118faa2dbf0SJosef Bacik 
119faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
120faa2dbf0SJosef Bacik 			      u64 num_bytes)
121faa2dbf0SJosef Bacik {
122faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
123faa2dbf0SJosef Bacik 	struct btrfs_key key;
124faa2dbf0SJosef Bacik 	struct btrfs_path *path;
125faa2dbf0SJosef Bacik 	int ret;
126faa2dbf0SJosef Bacik 
127483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
128faa2dbf0SJosef Bacik 
129faa2dbf0SJosef Bacik 	key.objectid = bytenr;
130faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
131faa2dbf0SJosef Bacik 	key.offset = num_bytes;
132faa2dbf0SJosef Bacik 
133faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
134faa2dbf0SJosef Bacik 	if (!path) {
135770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
136faa2dbf0SJosef Bacik 		return -ENOMEM;
137faa2dbf0SJosef Bacik 	}
138faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
139faa2dbf0SJosef Bacik 
140faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
141faa2dbf0SJosef Bacik 	if (ret) {
1423c7251f2SDavid Sterba 		test_err("didn't find our key %d", ret);
143faa2dbf0SJosef Bacik 		btrfs_free_path(path);
144faa2dbf0SJosef Bacik 		return ret;
145faa2dbf0SJosef Bacik 	}
146faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
147faa2dbf0SJosef Bacik 	btrfs_free_path(path);
148faa2dbf0SJosef Bacik 	return 0;
149faa2dbf0SJosef Bacik }
150faa2dbf0SJosef Bacik 
151faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
152faa2dbf0SJosef Bacik 			     u64 num_bytes, u64 parent, u64 root_objectid)
153faa2dbf0SJosef Bacik {
154faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
155faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
156faa2dbf0SJosef Bacik 	struct btrfs_path *path;
157faa2dbf0SJosef Bacik 	struct btrfs_key key;
158faa2dbf0SJosef Bacik 	u64 refs;
159faa2dbf0SJosef Bacik 	int ret;
160faa2dbf0SJosef Bacik 
161483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
162faa2dbf0SJosef Bacik 
163faa2dbf0SJosef Bacik 	key.objectid = bytenr;
164faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
165faa2dbf0SJosef Bacik 	key.offset = num_bytes;
166faa2dbf0SJosef Bacik 
167faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
168faa2dbf0SJosef Bacik 	if (!path) {
169770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
170faa2dbf0SJosef Bacik 		return -ENOMEM;
171faa2dbf0SJosef Bacik 	}
172faa2dbf0SJosef Bacik 
173faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
174faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
175faa2dbf0SJosef Bacik 	if (ret) {
1763c7251f2SDavid Sterba 		test_err("couldn't find extent ref");
177faa2dbf0SJosef Bacik 		btrfs_free_path(path);
178faa2dbf0SJosef Bacik 		return ret;
179faa2dbf0SJosef Bacik 	}
180faa2dbf0SJosef Bacik 
181faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
182faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
183faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
184faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
185faa2dbf0SJosef Bacik 	btrfs_release_path(path);
186faa2dbf0SJosef Bacik 
187faa2dbf0SJosef Bacik 	key.objectid = bytenr;
188faa2dbf0SJosef Bacik 	if (parent) {
189faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
190faa2dbf0SJosef Bacik 		key.offset = parent;
191faa2dbf0SJosef Bacik 	} else {
192faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
193faa2dbf0SJosef Bacik 		key.offset = root_objectid;
194faa2dbf0SJosef Bacik 	}
195faa2dbf0SJosef Bacik 
196faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
197faa2dbf0SJosef Bacik 	if (ret) {
1983c7251f2SDavid Sterba 		test_err("couldn't find backref %d", ret);
199faa2dbf0SJosef Bacik 		btrfs_free_path(path);
200faa2dbf0SJosef Bacik 		return ret;
201faa2dbf0SJosef Bacik 	}
202faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
203faa2dbf0SJosef Bacik 	btrfs_free_path(path);
204faa2dbf0SJosef Bacik 	return ret;
205faa2dbf0SJosef Bacik }
206faa2dbf0SJosef Bacik 
207b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root,
208b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
209faa2dbf0SJosef Bacik {
210faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
211faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
212442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
213442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
214faa2dbf0SJosef Bacik 	int ret;
215faa2dbf0SJosef Bacik 
216483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
217faa2dbf0SJosef Bacik 
218315b76b4SDavid Sterba 	test_msg("qgroup basic add");
21949a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID);
220faa2dbf0SJosef Bacik 	if (ret) {
2213c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
222faa2dbf0SJosef Bacik 		return ret;
223faa2dbf0SJosef Bacik 	}
224faa2dbf0SJosef Bacik 
225442244c9SQu Wenruo 	/*
22601327610SNicholas D Steeves 	 * Since the test trans doesn't have the complicated delayed refs,
227442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
228442244c9SQu Wenruo 	 * quota.
229442244c9SQu Wenruo 	 */
230c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
231c995ab3cSZygo Blaxell 			false);
232faa2dbf0SJosef Bacik 	if (ret) {
233442244c9SQu Wenruo 		ulist_free(old_roots);
2343c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
235faa2dbf0SJosef Bacik 		return ret;
236faa2dbf0SJosef Bacik 	}
237faa2dbf0SJosef Bacik 
238ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
239ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
240faa2dbf0SJosef Bacik 	if (ret)
241faa2dbf0SJosef Bacik 		return ret;
242faa2dbf0SJosef Bacik 
243c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
244c995ab3cSZygo Blaxell 			false);
245faa2dbf0SJosef Bacik 	if (ret) {
246442244c9SQu Wenruo 		ulist_free(old_roots);
247442244c9SQu Wenruo 		ulist_free(new_roots);
2483c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
249442244c9SQu Wenruo 		return ret;
250442244c9SQu Wenruo 	}
251442244c9SQu Wenruo 
2528696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2538696d760SLu Fengqi 					  new_roots);
254442244c9SQu Wenruo 	if (ret) {
2553c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
256faa2dbf0SJosef Bacik 		return ret;
257faa2dbf0SJosef Bacik 	}
258faa2dbf0SJosef Bacik 
259ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
260ef9f2db3SFeifei Xu 				nodesize, nodesize)) {
2613c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
262faa2dbf0SJosef Bacik 		return -EINVAL;
263faa2dbf0SJosef Bacik 	}
264442244c9SQu Wenruo 	old_roots = NULL;
265442244c9SQu Wenruo 	new_roots = NULL;
266442244c9SQu Wenruo 
267c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
268c995ab3cSZygo Blaxell 			false);
269442244c9SQu Wenruo 	if (ret) {
270442244c9SQu Wenruo 		ulist_free(old_roots);
2713c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
272442244c9SQu Wenruo 		return ret;
273442244c9SQu Wenruo 	}
274faa2dbf0SJosef Bacik 
275b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
276faa2dbf0SJosef Bacik 	if (ret)
277faa2dbf0SJosef Bacik 		return -EINVAL;
278faa2dbf0SJosef Bacik 
279c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
280c995ab3cSZygo Blaxell 			false);
281faa2dbf0SJosef Bacik 	if (ret) {
282442244c9SQu Wenruo 		ulist_free(old_roots);
283442244c9SQu Wenruo 		ulist_free(new_roots);
2843c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
285442244c9SQu Wenruo 		return ret;
286faa2dbf0SJosef Bacik 	}
287faa2dbf0SJosef Bacik 
2888696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2898696d760SLu Fengqi 					  new_roots);
290faa2dbf0SJosef Bacik 	if (ret) {
2913c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
292faa2dbf0SJosef Bacik 		return -EINVAL;
293faa2dbf0SJosef Bacik 	}
294faa2dbf0SJosef Bacik 
295ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
2963c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
297faa2dbf0SJosef Bacik 		return -EINVAL;
298faa2dbf0SJosef Bacik 	}
299faa2dbf0SJosef Bacik 
300faa2dbf0SJosef Bacik 	return 0;
301faa2dbf0SJosef Bacik }
302faa2dbf0SJosef Bacik 
303faa2dbf0SJosef Bacik /*
304faa2dbf0SJosef Bacik  * Add a ref for two different roots to make sure the shared value comes out
305faa2dbf0SJosef Bacik  * right, also remove one of the roots and make sure the exclusive count is
306faa2dbf0SJosef Bacik  * adjusted properly.
307faa2dbf0SJosef Bacik  */
308b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root,
309b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
310faa2dbf0SJosef Bacik {
311faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
312faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
313442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
314442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
315faa2dbf0SJosef Bacik 	int ret;
316faa2dbf0SJosef Bacik 
317483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
318faa2dbf0SJosef Bacik 
319315b76b4SDavid Sterba 	test_msg("qgroup multiple refs test");
320faa2dbf0SJosef Bacik 
321ef9f2db3SFeifei Xu 	/*
322ef9f2db3SFeifei Xu 	 * We have BTRFS_FS_TREE_OBJECTID created already from the
323ef9f2db3SFeifei Xu 	 * previous test.
324ef9f2db3SFeifei Xu 	 */
32549a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID);
326faa2dbf0SJosef Bacik 	if (ret) {
3273c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
328faa2dbf0SJosef Bacik 		return ret;
329faa2dbf0SJosef Bacik 	}
330faa2dbf0SJosef Bacik 
331c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
332c995ab3cSZygo Blaxell 			false);
333442244c9SQu Wenruo 	if (ret) {
334442244c9SQu Wenruo 		ulist_free(old_roots);
3353c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
336442244c9SQu Wenruo 		return ret;
337442244c9SQu Wenruo 	}
338442244c9SQu Wenruo 
339ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
340ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
341faa2dbf0SJosef Bacik 	if (ret)
342faa2dbf0SJosef Bacik 		return ret;
343faa2dbf0SJosef Bacik 
344c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
345c995ab3cSZygo Blaxell 			false);
346faa2dbf0SJosef Bacik 	if (ret) {
347442244c9SQu Wenruo 		ulist_free(old_roots);
348442244c9SQu Wenruo 		ulist_free(new_roots);
3493c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
350faa2dbf0SJosef Bacik 		return ret;
351faa2dbf0SJosef Bacik 	}
352faa2dbf0SJosef Bacik 
3538696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3548696d760SLu Fengqi 					  new_roots);
355faa2dbf0SJosef Bacik 	if (ret) {
3563c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
357faa2dbf0SJosef Bacik 		return ret;
358faa2dbf0SJosef Bacik 	}
359faa2dbf0SJosef Bacik 
360ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
361b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
3623c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
363faa2dbf0SJosef Bacik 		return -EINVAL;
364faa2dbf0SJosef Bacik 	}
365faa2dbf0SJosef Bacik 
366c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
367c995ab3cSZygo Blaxell 			false);
368442244c9SQu Wenruo 	if (ret) {
369442244c9SQu Wenruo 		ulist_free(old_roots);
3703c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
371442244c9SQu Wenruo 		return ret;
372442244c9SQu Wenruo 	}
373442244c9SQu Wenruo 
374ef9f2db3SFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0,
375ef9f2db3SFeifei Xu 			BTRFS_FIRST_FREE_OBJECTID);
376faa2dbf0SJosef Bacik 	if (ret)
377faa2dbf0SJosef Bacik 		return ret;
378faa2dbf0SJosef Bacik 
379c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
380c995ab3cSZygo Blaxell 			false);
381faa2dbf0SJosef Bacik 	if (ret) {
382442244c9SQu Wenruo 		ulist_free(old_roots);
383442244c9SQu Wenruo 		ulist_free(new_roots);
3843c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
385faa2dbf0SJosef Bacik 		return ret;
386faa2dbf0SJosef Bacik 	}
387faa2dbf0SJosef Bacik 
3888696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3898696d760SLu Fengqi 					  new_roots);
390faa2dbf0SJosef Bacik 	if (ret) {
3913c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
392faa2dbf0SJosef Bacik 		return ret;
393faa2dbf0SJosef Bacik 	}
394faa2dbf0SJosef Bacik 
395ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
396ef9f2db3SFeifei Xu 					nodesize, 0)) {
3973c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
398faa2dbf0SJosef Bacik 		return -EINVAL;
399faa2dbf0SJosef Bacik 	}
400faa2dbf0SJosef Bacik 
401ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
402ef9f2db3SFeifei Xu 					nodesize, 0)) {
4033c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
404faa2dbf0SJosef Bacik 		return -EINVAL;
405faa2dbf0SJosef Bacik 	}
406faa2dbf0SJosef Bacik 
407c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
408c995ab3cSZygo Blaxell 			false);
409442244c9SQu Wenruo 	if (ret) {
410442244c9SQu Wenruo 		ulist_free(old_roots);
4113c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
412442244c9SQu Wenruo 		return ret;
413442244c9SQu Wenruo 	}
414442244c9SQu Wenruo 
415ef9f2db3SFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0,
416ef9f2db3SFeifei Xu 				BTRFS_FIRST_FREE_OBJECTID);
417faa2dbf0SJosef Bacik 	if (ret)
418faa2dbf0SJosef Bacik 		return ret;
419faa2dbf0SJosef Bacik 
420c995ab3cSZygo Blaxell 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
421c995ab3cSZygo Blaxell 			false);
422faa2dbf0SJosef Bacik 	if (ret) {
423442244c9SQu Wenruo 		ulist_free(old_roots);
424442244c9SQu Wenruo 		ulist_free(new_roots);
4253c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
426faa2dbf0SJosef Bacik 		return ret;
427faa2dbf0SJosef Bacik 	}
428faa2dbf0SJosef Bacik 
4298696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
4308696d760SLu Fengqi 					  new_roots);
431faa2dbf0SJosef Bacik 	if (ret) {
4323c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
433faa2dbf0SJosef Bacik 		return ret;
434faa2dbf0SJosef Bacik 	}
435faa2dbf0SJosef Bacik 
436ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
437ef9f2db3SFeifei Xu 					0, 0)) {
4383c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
439faa2dbf0SJosef Bacik 		return -EINVAL;
440faa2dbf0SJosef Bacik 	}
441faa2dbf0SJosef Bacik 
442ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
443ef9f2db3SFeifei Xu 					nodesize, nodesize)) {
4443c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
445faa2dbf0SJosef Bacik 		return -EINVAL;
446faa2dbf0SJosef Bacik 	}
447faa2dbf0SJosef Bacik 
448faa2dbf0SJosef Bacik 	return 0;
449faa2dbf0SJosef Bacik }
450faa2dbf0SJosef Bacik 
451b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
452faa2dbf0SJosef Bacik {
4537c0260eeSJeff Mahoney 	struct btrfs_fs_info *fs_info = NULL;
454faa2dbf0SJosef Bacik 	struct btrfs_root *root;
455faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
456faa2dbf0SJosef Bacik 	int ret = 0;
457faa2dbf0SJosef Bacik 
458da17066cSJeff Mahoney 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
4597c0260eeSJeff Mahoney 	if (!fs_info) {
46037b2a7bcSDavid Sterba 		test_std_err(TEST_ALLOC_FS_INFO);
4617c0260eeSJeff Mahoney 		return -ENOMEM;
462faa2dbf0SJosef Bacik 	}
463faa2dbf0SJosef Bacik 
464da17066cSJeff Mahoney 	root = btrfs_alloc_dummy_root(fs_info);
4657c0260eeSJeff Mahoney 	if (IS_ERR(root)) {
46652ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
4677c0260eeSJeff Mahoney 		ret = PTR_ERR(root);
468faa2dbf0SJosef Bacik 		goto out;
469faa2dbf0SJosef Bacik 	}
4707c0260eeSJeff Mahoney 
4713f556f78SDavid Sterba 	/* We are using this root as our extent root */
4723f556f78SDavid Sterba 	root->fs_info->extent_root = root;
4733f556f78SDavid Sterba 
4743f556f78SDavid Sterba 	/*
4753f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4763f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
4773f556f78SDavid Sterba 	 */
4783f556f78SDavid Sterba 	root->fs_info->tree_root = root;
4793f556f78SDavid Sterba 	root->fs_info->quota_root = root;
480afcdd129SJosef Bacik 	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
481faa2dbf0SJosef Bacik 
482faa2dbf0SJosef Bacik 	/*
483faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
484faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
485faa2dbf0SJosef Bacik 	 */
486da17066cSJeff Mahoney 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
487faa2dbf0SJosef Bacik 	if (!root->node) {
4883c7251f2SDavid Sterba 		test_err("couldn't allocate dummy buffer");
489faa2dbf0SJosef Bacik 		ret = -ENOMEM;
490faa2dbf0SJosef Bacik 		goto out;
491faa2dbf0SJosef Bacik 	}
492b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
493b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
494b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
495faa2dbf0SJosef Bacik 
496da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
497faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
49852ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
499faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
500faa2dbf0SJosef Bacik 		goto out;
501faa2dbf0SJosef Bacik 	}
502faa2dbf0SJosef Bacik 
503ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
504faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
505faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
506faa2dbf0SJosef Bacik 	if (ret) {
5073c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
508faa2dbf0SJosef Bacik 		goto out;
509faa2dbf0SJosef Bacik 	}
510faa2dbf0SJosef Bacik 
511da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
512faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
51352ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
514faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
515faa2dbf0SJosef Bacik 		goto out;
516faa2dbf0SJosef Bacik 	}
517faa2dbf0SJosef Bacik 
518ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
519faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
520faa2dbf0SJosef Bacik 	if (ret) {
5213c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
522faa2dbf0SJosef Bacik 		goto out;
523faa2dbf0SJosef Bacik 	}
524faa2dbf0SJosef Bacik 
525315b76b4SDavid Sterba 	test_msg("running qgroup tests");
526b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
527faa2dbf0SJosef Bacik 	if (ret)
528faa2dbf0SJosef Bacik 		goto out;
529b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
530faa2dbf0SJosef Bacik out:
531faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
5327c0260eeSJeff Mahoney 	btrfs_free_dummy_fs_info(fs_info);
533faa2dbf0SJosef Bacik 	return ret;
534faa2dbf0SJosef Bacik }
535