xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision d37de92b)
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 	ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
40faa2dbf0SJosef Bacik 	if (ret) {
413c7251f2SDavid Sterba 		test_err("couldn't insert ref %d", ret);
42faa2dbf0SJosef Bacik 		btrfs_free_path(path);
43faa2dbf0SJosef Bacik 		return ret;
44faa2dbf0SJosef Bacik 	}
45faa2dbf0SJosef Bacik 
46faa2dbf0SJosef Bacik 	leaf = path->nodes[0];
47faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
48faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(leaf, item, 1);
49faa2dbf0SJosef Bacik 	btrfs_set_extent_generation(leaf, item, 1);
50faa2dbf0SJosef Bacik 	btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
51faa2dbf0SJosef Bacik 	block_info = (struct btrfs_tree_block_info *)(item + 1);
523c0efdf0SQu Wenruo 	btrfs_set_tree_block_level(leaf, block_info, 0);
53faa2dbf0SJosef Bacik 	iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
54faa2dbf0SJosef Bacik 	if (parent > 0) {
55faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref,
56faa2dbf0SJosef Bacik 						 BTRFS_SHARED_BLOCK_REF_KEY);
57faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
58faa2dbf0SJosef Bacik 	} else {
59faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
60faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
61faa2dbf0SJosef Bacik 	}
62faa2dbf0SJosef Bacik 	btrfs_free_path(path);
63faa2dbf0SJosef Bacik 	return 0;
64faa2dbf0SJosef Bacik }
65faa2dbf0SJosef Bacik 
66faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
67faa2dbf0SJosef Bacik 			u64 parent, u64 root_objectid)
68faa2dbf0SJosef Bacik {
69faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
70faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
71faa2dbf0SJosef Bacik 	struct btrfs_path *path;
72faa2dbf0SJosef Bacik 	struct btrfs_key key;
73faa2dbf0SJosef Bacik 	u64 refs;
74faa2dbf0SJosef Bacik 	int ret;
75faa2dbf0SJosef Bacik 
76483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
77faa2dbf0SJosef Bacik 
78faa2dbf0SJosef Bacik 	key.objectid = bytenr;
79faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
80faa2dbf0SJosef Bacik 	key.offset = num_bytes;
81faa2dbf0SJosef Bacik 
82faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
83faa2dbf0SJosef Bacik 	if (!path) {
84770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
85faa2dbf0SJosef Bacik 		return -ENOMEM;
86faa2dbf0SJosef Bacik 	}
87faa2dbf0SJosef Bacik 
88faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
89faa2dbf0SJosef Bacik 	if (ret) {
903c7251f2SDavid Sterba 		test_err("couldn't find extent ref");
91faa2dbf0SJosef Bacik 		btrfs_free_path(path);
92faa2dbf0SJosef Bacik 		return ret;
93faa2dbf0SJosef Bacik 	}
94faa2dbf0SJosef Bacik 
95faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
96faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
97faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
98faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs + 1);
99faa2dbf0SJosef Bacik 	btrfs_release_path(path);
100faa2dbf0SJosef Bacik 
101faa2dbf0SJosef Bacik 	key.objectid = bytenr;
102faa2dbf0SJosef Bacik 	if (parent) {
103faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
104faa2dbf0SJosef Bacik 		key.offset = parent;
105faa2dbf0SJosef Bacik 	} else {
106faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
107faa2dbf0SJosef Bacik 		key.offset = root_objectid;
108faa2dbf0SJosef Bacik 	}
109faa2dbf0SJosef Bacik 
110faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
111faa2dbf0SJosef Bacik 	if (ret)
1123c7251f2SDavid Sterba 		test_err("failed to insert backref");
113faa2dbf0SJosef Bacik 	btrfs_free_path(path);
114faa2dbf0SJosef Bacik 	return ret;
115faa2dbf0SJosef Bacik }
116faa2dbf0SJosef Bacik 
117faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
118faa2dbf0SJosef Bacik 			      u64 num_bytes)
119faa2dbf0SJosef Bacik {
120faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
121faa2dbf0SJosef Bacik 	struct btrfs_key key;
122faa2dbf0SJosef Bacik 	struct btrfs_path *path;
123faa2dbf0SJosef Bacik 	int ret;
124faa2dbf0SJosef Bacik 
125483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
126faa2dbf0SJosef Bacik 
127faa2dbf0SJosef Bacik 	key.objectid = bytenr;
128faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
129faa2dbf0SJosef Bacik 	key.offset = num_bytes;
130faa2dbf0SJosef Bacik 
131faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
132faa2dbf0SJosef Bacik 	if (!path) {
133770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
134faa2dbf0SJosef Bacik 		return -ENOMEM;
135faa2dbf0SJosef Bacik 	}
136faa2dbf0SJosef Bacik 
137faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
138faa2dbf0SJosef Bacik 	if (ret) {
1393c7251f2SDavid Sterba 		test_err("didn't find our key %d", ret);
140faa2dbf0SJosef Bacik 		btrfs_free_path(path);
141faa2dbf0SJosef Bacik 		return ret;
142faa2dbf0SJosef Bacik 	}
143faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
144faa2dbf0SJosef Bacik 	btrfs_free_path(path);
145faa2dbf0SJosef Bacik 	return 0;
146faa2dbf0SJosef Bacik }
147faa2dbf0SJosef Bacik 
148faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
149faa2dbf0SJosef Bacik 			     u64 num_bytes, u64 parent, u64 root_objectid)
150faa2dbf0SJosef Bacik {
151faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
152faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
153faa2dbf0SJosef Bacik 	struct btrfs_path *path;
154faa2dbf0SJosef Bacik 	struct btrfs_key key;
155faa2dbf0SJosef Bacik 	u64 refs;
156faa2dbf0SJosef Bacik 	int ret;
157faa2dbf0SJosef Bacik 
158483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
159faa2dbf0SJosef Bacik 
160faa2dbf0SJosef Bacik 	key.objectid = bytenr;
161faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
162faa2dbf0SJosef Bacik 	key.offset = num_bytes;
163faa2dbf0SJosef Bacik 
164faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
165faa2dbf0SJosef Bacik 	if (!path) {
166770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
167faa2dbf0SJosef Bacik 		return -ENOMEM;
168faa2dbf0SJosef Bacik 	}
169faa2dbf0SJosef Bacik 
170faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
171faa2dbf0SJosef Bacik 	if (ret) {
1723c7251f2SDavid Sterba 		test_err("couldn't find extent ref");
173faa2dbf0SJosef Bacik 		btrfs_free_path(path);
174faa2dbf0SJosef Bacik 		return ret;
175faa2dbf0SJosef Bacik 	}
176faa2dbf0SJosef Bacik 
177faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
178faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
179faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
180faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
181faa2dbf0SJosef Bacik 	btrfs_release_path(path);
182faa2dbf0SJosef Bacik 
183faa2dbf0SJosef Bacik 	key.objectid = bytenr;
184faa2dbf0SJosef Bacik 	if (parent) {
185faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
186faa2dbf0SJosef Bacik 		key.offset = parent;
187faa2dbf0SJosef Bacik 	} else {
188faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
189faa2dbf0SJosef Bacik 		key.offset = root_objectid;
190faa2dbf0SJosef Bacik 	}
191faa2dbf0SJosef Bacik 
192faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
193faa2dbf0SJosef Bacik 	if (ret) {
1943c7251f2SDavid Sterba 		test_err("couldn't find backref %d", ret);
195faa2dbf0SJosef Bacik 		btrfs_free_path(path);
196faa2dbf0SJosef Bacik 		return ret;
197faa2dbf0SJosef Bacik 	}
198faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
199faa2dbf0SJosef Bacik 	btrfs_free_path(path);
200faa2dbf0SJosef Bacik 	return ret;
201faa2dbf0SJosef Bacik }
202faa2dbf0SJosef Bacik 
203b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root,
204b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
205faa2dbf0SJosef Bacik {
206faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
207faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
208442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
209442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
210faa2dbf0SJosef Bacik 	int ret;
211faa2dbf0SJosef Bacik 
212483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
213faa2dbf0SJosef Bacik 
214e4fa7469SDavid Sterba 	test_msg("running qgroup add/remove tests");
21549a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID);
216faa2dbf0SJosef Bacik 	if (ret) {
2173c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
218faa2dbf0SJosef Bacik 		return ret;
219faa2dbf0SJosef Bacik 	}
220faa2dbf0SJosef Bacik 
221442244c9SQu Wenruo 	/*
22201327610SNicholas D Steeves 	 * Since the test trans doesn't have the complicated delayed refs,
223442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
224442244c9SQu Wenruo 	 * quota.
225442244c9SQu Wenruo 	 */
226c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
227faa2dbf0SJosef Bacik 	if (ret) {
228442244c9SQu Wenruo 		ulist_free(old_roots);
2293c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
230faa2dbf0SJosef Bacik 		return ret;
231faa2dbf0SJosef Bacik 	}
232faa2dbf0SJosef Bacik 
233ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
234ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
235*d37de92bSFilipe Manana 	if (ret) {
236*d37de92bSFilipe Manana 		ulist_free(old_roots);
237faa2dbf0SJosef Bacik 		return ret;
238*d37de92bSFilipe Manana 	}
239faa2dbf0SJosef Bacik 
240c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
241faa2dbf0SJosef Bacik 	if (ret) {
242442244c9SQu Wenruo 		ulist_free(old_roots);
243442244c9SQu Wenruo 		ulist_free(new_roots);
2443c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
245442244c9SQu Wenruo 		return ret;
246442244c9SQu Wenruo 	}
247442244c9SQu Wenruo 
2488696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2498696d760SLu Fengqi 					  new_roots);
250442244c9SQu Wenruo 	if (ret) {
2513c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
252faa2dbf0SJosef Bacik 		return ret;
253faa2dbf0SJosef Bacik 	}
254faa2dbf0SJosef Bacik 
255ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
256ef9f2db3SFeifei Xu 				nodesize, nodesize)) {
2573c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
258faa2dbf0SJosef Bacik 		return -EINVAL;
259faa2dbf0SJosef Bacik 	}
260442244c9SQu Wenruo 	old_roots = NULL;
261442244c9SQu Wenruo 	new_roots = NULL;
262442244c9SQu Wenruo 
263c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
264442244c9SQu Wenruo 	if (ret) {
265442244c9SQu Wenruo 		ulist_free(old_roots);
2663c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
267442244c9SQu Wenruo 		return ret;
268442244c9SQu Wenruo 	}
269faa2dbf0SJosef Bacik 
270b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
271*d37de92bSFilipe Manana 	if (ret) {
272*d37de92bSFilipe Manana 		ulist_free(old_roots);
273faa2dbf0SJosef Bacik 		return -EINVAL;
274*d37de92bSFilipe Manana 	}
275faa2dbf0SJosef Bacik 
276c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
277faa2dbf0SJosef Bacik 	if (ret) {
278442244c9SQu Wenruo 		ulist_free(old_roots);
279442244c9SQu Wenruo 		ulist_free(new_roots);
2803c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
281442244c9SQu Wenruo 		return ret;
282faa2dbf0SJosef Bacik 	}
283faa2dbf0SJosef Bacik 
2848696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2858696d760SLu Fengqi 					  new_roots);
286faa2dbf0SJosef Bacik 	if (ret) {
2873c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
288faa2dbf0SJosef Bacik 		return -EINVAL;
289faa2dbf0SJosef Bacik 	}
290faa2dbf0SJosef Bacik 
291ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
2923c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
293faa2dbf0SJosef Bacik 		return -EINVAL;
294faa2dbf0SJosef Bacik 	}
295faa2dbf0SJosef Bacik 
296faa2dbf0SJosef Bacik 	return 0;
297faa2dbf0SJosef Bacik }
298faa2dbf0SJosef Bacik 
299faa2dbf0SJosef Bacik /*
300faa2dbf0SJosef Bacik  * Add a ref for two different roots to make sure the shared value comes out
301faa2dbf0SJosef Bacik  * right, also remove one of the roots and make sure the exclusive count is
302faa2dbf0SJosef Bacik  * adjusted properly.
303faa2dbf0SJosef Bacik  */
304b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root,
305b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
306faa2dbf0SJosef Bacik {
307faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
308faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
309442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
310442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
311faa2dbf0SJosef Bacik 	int ret;
312faa2dbf0SJosef Bacik 
313483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
314faa2dbf0SJosef Bacik 
315e4fa7469SDavid Sterba 	test_msg("running qgroup multiple refs test");
316faa2dbf0SJosef Bacik 
317ef9f2db3SFeifei Xu 	/*
318ef9f2db3SFeifei Xu 	 * We have BTRFS_FS_TREE_OBJECTID created already from the
319ef9f2db3SFeifei Xu 	 * previous test.
320ef9f2db3SFeifei Xu 	 */
32149a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID);
322faa2dbf0SJosef Bacik 	if (ret) {
3233c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
324faa2dbf0SJosef Bacik 		return ret;
325faa2dbf0SJosef Bacik 	}
326faa2dbf0SJosef Bacik 
327c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
328442244c9SQu Wenruo 	if (ret) {
329442244c9SQu Wenruo 		ulist_free(old_roots);
3303c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
331442244c9SQu Wenruo 		return ret;
332442244c9SQu Wenruo 	}
333442244c9SQu Wenruo 
334ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
335ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
336*d37de92bSFilipe Manana 	if (ret) {
337*d37de92bSFilipe Manana 		ulist_free(old_roots);
338faa2dbf0SJosef Bacik 		return ret;
339*d37de92bSFilipe Manana 	}
340faa2dbf0SJosef Bacik 
341c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
342faa2dbf0SJosef Bacik 	if (ret) {
343442244c9SQu Wenruo 		ulist_free(old_roots);
344442244c9SQu Wenruo 		ulist_free(new_roots);
3453c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
346faa2dbf0SJosef Bacik 		return ret;
347faa2dbf0SJosef Bacik 	}
348faa2dbf0SJosef Bacik 
3498696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3508696d760SLu Fengqi 					  new_roots);
351faa2dbf0SJosef Bacik 	if (ret) {
3523c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
353faa2dbf0SJosef Bacik 		return ret;
354faa2dbf0SJosef Bacik 	}
355faa2dbf0SJosef Bacik 
356ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
357b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
3583c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
359faa2dbf0SJosef Bacik 		return -EINVAL;
360faa2dbf0SJosef Bacik 	}
361faa2dbf0SJosef Bacik 
362c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
363442244c9SQu Wenruo 	if (ret) {
364442244c9SQu Wenruo 		ulist_free(old_roots);
3653c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
366442244c9SQu Wenruo 		return ret;
367442244c9SQu Wenruo 	}
368442244c9SQu Wenruo 
369ef9f2db3SFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0,
370ef9f2db3SFeifei Xu 			BTRFS_FIRST_FREE_OBJECTID);
371*d37de92bSFilipe Manana 	if (ret) {
372*d37de92bSFilipe Manana 		ulist_free(old_roots);
373faa2dbf0SJosef Bacik 		return ret;
374*d37de92bSFilipe Manana 	}
375faa2dbf0SJosef Bacik 
376c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
377faa2dbf0SJosef Bacik 	if (ret) {
378442244c9SQu Wenruo 		ulist_free(old_roots);
379442244c9SQu Wenruo 		ulist_free(new_roots);
3803c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
381faa2dbf0SJosef Bacik 		return ret;
382faa2dbf0SJosef Bacik 	}
383faa2dbf0SJosef Bacik 
3848696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3858696d760SLu Fengqi 					  new_roots);
386faa2dbf0SJosef Bacik 	if (ret) {
3873c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
388faa2dbf0SJosef Bacik 		return ret;
389faa2dbf0SJosef Bacik 	}
390faa2dbf0SJosef Bacik 
391ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
392ef9f2db3SFeifei Xu 					nodesize, 0)) {
3933c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
394faa2dbf0SJosef Bacik 		return -EINVAL;
395faa2dbf0SJosef Bacik 	}
396faa2dbf0SJosef Bacik 
397ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
398ef9f2db3SFeifei Xu 					nodesize, 0)) {
3993c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
400faa2dbf0SJosef Bacik 		return -EINVAL;
401faa2dbf0SJosef Bacik 	}
402faa2dbf0SJosef Bacik 
403c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
404442244c9SQu Wenruo 	if (ret) {
405442244c9SQu Wenruo 		ulist_free(old_roots);
4063c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
407442244c9SQu Wenruo 		return ret;
408442244c9SQu Wenruo 	}
409442244c9SQu Wenruo 
410ef9f2db3SFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0,
411ef9f2db3SFeifei Xu 				BTRFS_FIRST_FREE_OBJECTID);
412*d37de92bSFilipe Manana 	if (ret) {
413*d37de92bSFilipe Manana 		ulist_free(old_roots);
414faa2dbf0SJosef Bacik 		return ret;
415*d37de92bSFilipe Manana 	}
416faa2dbf0SJosef Bacik 
417c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
418faa2dbf0SJosef Bacik 	if (ret) {
419442244c9SQu Wenruo 		ulist_free(old_roots);
420442244c9SQu Wenruo 		ulist_free(new_roots);
4213c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
422faa2dbf0SJosef Bacik 		return ret;
423faa2dbf0SJosef Bacik 	}
424faa2dbf0SJosef Bacik 
4258696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
4268696d760SLu Fengqi 					  new_roots);
427faa2dbf0SJosef Bacik 	if (ret) {
4283c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
429faa2dbf0SJosef Bacik 		return ret;
430faa2dbf0SJosef Bacik 	}
431faa2dbf0SJosef Bacik 
432ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
433ef9f2db3SFeifei Xu 					0, 0)) {
4343c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
435faa2dbf0SJosef Bacik 		return -EINVAL;
436faa2dbf0SJosef Bacik 	}
437faa2dbf0SJosef Bacik 
438ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
439ef9f2db3SFeifei Xu 					nodesize, nodesize)) {
4403c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
441faa2dbf0SJosef Bacik 		return -EINVAL;
442faa2dbf0SJosef Bacik 	}
443faa2dbf0SJosef Bacik 
444faa2dbf0SJosef Bacik 	return 0;
445faa2dbf0SJosef Bacik }
446faa2dbf0SJosef Bacik 
447b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
448faa2dbf0SJosef Bacik {
4497c0260eeSJeff Mahoney 	struct btrfs_fs_info *fs_info = NULL;
450faa2dbf0SJosef Bacik 	struct btrfs_root *root;
451faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
452faa2dbf0SJosef Bacik 	int ret = 0;
453faa2dbf0SJosef Bacik 
454da17066cSJeff Mahoney 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
4557c0260eeSJeff Mahoney 	if (!fs_info) {
45637b2a7bcSDavid Sterba 		test_std_err(TEST_ALLOC_FS_INFO);
4577c0260eeSJeff Mahoney 		return -ENOMEM;
458faa2dbf0SJosef Bacik 	}
459faa2dbf0SJosef Bacik 
460da17066cSJeff Mahoney 	root = btrfs_alloc_dummy_root(fs_info);
4617c0260eeSJeff Mahoney 	if (IS_ERR(root)) {
46252ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
4637c0260eeSJeff Mahoney 		ret = PTR_ERR(root);
464faa2dbf0SJosef Bacik 		goto out;
465faa2dbf0SJosef Bacik 	}
4667c0260eeSJeff Mahoney 
4673f556f78SDavid Sterba 	/* We are using this root as our extent root */
468abed4aaaSJosef Bacik 	root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
469abed4aaaSJosef Bacik 	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
470abed4aaaSJosef Bacik 	root->root_key.offset = 0;
471abed4aaaSJosef Bacik 	btrfs_global_root_insert(root);
4723f556f78SDavid Sterba 
4733f556f78SDavid Sterba 	/*
4743f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4753f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
4763f556f78SDavid Sterba 	 */
4773f556f78SDavid Sterba 	root->fs_info->tree_root = root;
4783f556f78SDavid Sterba 	root->fs_info->quota_root = root;
479afcdd129SJosef Bacik 	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
480faa2dbf0SJosef Bacik 
481faa2dbf0SJosef Bacik 	/*
482faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
483faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
484faa2dbf0SJosef Bacik 	 */
485da17066cSJeff Mahoney 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
486b6293c82SDan Carpenter 	if (IS_ERR(root->node)) {
4873c7251f2SDavid Sterba 		test_err("couldn't allocate dummy buffer");
488b6293c82SDan Carpenter 		ret = PTR_ERR(root->node);
489faa2dbf0SJosef Bacik 		goto out;
490faa2dbf0SJosef Bacik 	}
491b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
492b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
493b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
494faa2dbf0SJosef Bacik 
495da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
496faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
49752ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
498faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
499faa2dbf0SJosef Bacik 		goto out;
500faa2dbf0SJosef Bacik 	}
501faa2dbf0SJosef Bacik 
502ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
503faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
504faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
505faa2dbf0SJosef Bacik 	if (ret) {
5063c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
507faa2dbf0SJosef Bacik 		goto out;
508faa2dbf0SJosef Bacik 	}
5094785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
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 	}
5244785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
525faa2dbf0SJosef Bacik 
526315b76b4SDavid Sterba 	test_msg("running qgroup tests");
527b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
528faa2dbf0SJosef Bacik 	if (ret)
529faa2dbf0SJosef Bacik 		goto out;
530b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
531faa2dbf0SJosef Bacik out:
532faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
5337c0260eeSJeff Mahoney 	btrfs_free_dummy_fs_info(fs_info);
534faa2dbf0SJosef Bacik 	return ret;
535faa2dbf0SJosef Bacik }
536