xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision 07e81dc9)
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"
137966a6b5SJosef Bacik #include "../fs.h"
14*07e81dc9SJosef Bacik #include "../accessors.h"
15faa2dbf0SJosef Bacik 
16faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
17faa2dbf0SJosef Bacik 				  u64 num_bytes, u64 parent, u64 root_objectid)
18faa2dbf0SJosef Bacik {
19faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
20faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
21faa2dbf0SJosef Bacik 	struct btrfs_extent_inline_ref *iref;
22faa2dbf0SJosef Bacik 	struct btrfs_tree_block_info *block_info;
23faa2dbf0SJosef Bacik 	struct btrfs_path *path;
24faa2dbf0SJosef Bacik 	struct extent_buffer *leaf;
25faa2dbf0SJosef Bacik 	struct btrfs_key ins;
26faa2dbf0SJosef Bacik 	u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
27faa2dbf0SJosef Bacik 	int ret;
28faa2dbf0SJosef Bacik 
29483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
30faa2dbf0SJosef Bacik 
31faa2dbf0SJosef Bacik 	ins.objectid = bytenr;
32faa2dbf0SJosef Bacik 	ins.type = BTRFS_EXTENT_ITEM_KEY;
33faa2dbf0SJosef Bacik 	ins.offset = num_bytes;
34faa2dbf0SJosef Bacik 
35faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
36faa2dbf0SJosef Bacik 	if (!path) {
37770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
38faa2dbf0SJosef Bacik 		return -ENOMEM;
39faa2dbf0SJosef Bacik 	}
40faa2dbf0SJosef Bacik 
41faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
42faa2dbf0SJosef Bacik 	if (ret) {
433c7251f2SDavid Sterba 		test_err("couldn't insert ref %d", ret);
44faa2dbf0SJosef Bacik 		btrfs_free_path(path);
45faa2dbf0SJosef Bacik 		return ret;
46faa2dbf0SJosef Bacik 	}
47faa2dbf0SJosef Bacik 
48faa2dbf0SJosef Bacik 	leaf = path->nodes[0];
49faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
50faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(leaf, item, 1);
51faa2dbf0SJosef Bacik 	btrfs_set_extent_generation(leaf, item, 1);
52faa2dbf0SJosef Bacik 	btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
53faa2dbf0SJosef Bacik 	block_info = (struct btrfs_tree_block_info *)(item + 1);
543c0efdf0SQu Wenruo 	btrfs_set_tree_block_level(leaf, block_info, 0);
55faa2dbf0SJosef Bacik 	iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
56faa2dbf0SJosef Bacik 	if (parent > 0) {
57faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref,
58faa2dbf0SJosef Bacik 						 BTRFS_SHARED_BLOCK_REF_KEY);
59faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
60faa2dbf0SJosef Bacik 	} else {
61faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
62faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
63faa2dbf0SJosef Bacik 	}
64faa2dbf0SJosef Bacik 	btrfs_free_path(path);
65faa2dbf0SJosef Bacik 	return 0;
66faa2dbf0SJosef Bacik }
67faa2dbf0SJosef Bacik 
68faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
69faa2dbf0SJosef Bacik 			u64 parent, u64 root_objectid)
70faa2dbf0SJosef Bacik {
71faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
72faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
73faa2dbf0SJosef Bacik 	struct btrfs_path *path;
74faa2dbf0SJosef Bacik 	struct btrfs_key key;
75faa2dbf0SJosef Bacik 	u64 refs;
76faa2dbf0SJosef Bacik 	int ret;
77faa2dbf0SJosef Bacik 
78483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
79faa2dbf0SJosef Bacik 
80faa2dbf0SJosef Bacik 	key.objectid = bytenr;
81faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
82faa2dbf0SJosef Bacik 	key.offset = num_bytes;
83faa2dbf0SJosef Bacik 
84faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
85faa2dbf0SJosef Bacik 	if (!path) {
86770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
87faa2dbf0SJosef Bacik 		return -ENOMEM;
88faa2dbf0SJosef Bacik 	}
89faa2dbf0SJosef Bacik 
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 
139faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
140faa2dbf0SJosef Bacik 	if (ret) {
1413c7251f2SDavid Sterba 		test_err("didn't find our key %d", ret);
142faa2dbf0SJosef Bacik 		btrfs_free_path(path);
143faa2dbf0SJosef Bacik 		return ret;
144faa2dbf0SJosef Bacik 	}
145faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
146faa2dbf0SJosef Bacik 	btrfs_free_path(path);
147faa2dbf0SJosef Bacik 	return 0;
148faa2dbf0SJosef Bacik }
149faa2dbf0SJosef Bacik 
150faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
151faa2dbf0SJosef Bacik 			     u64 num_bytes, u64 parent, u64 root_objectid)
152faa2dbf0SJosef Bacik {
153faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
154faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
155faa2dbf0SJosef Bacik 	struct btrfs_path *path;
156faa2dbf0SJosef Bacik 	struct btrfs_key key;
157faa2dbf0SJosef Bacik 	u64 refs;
158faa2dbf0SJosef Bacik 	int ret;
159faa2dbf0SJosef Bacik 
160483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, NULL);
161faa2dbf0SJosef Bacik 
162faa2dbf0SJosef Bacik 	key.objectid = bytenr;
163faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
164faa2dbf0SJosef Bacik 	key.offset = num_bytes;
165faa2dbf0SJosef Bacik 
166faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
167faa2dbf0SJosef Bacik 	if (!path) {
168770e0cc0SDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
169faa2dbf0SJosef Bacik 		return -ENOMEM;
170faa2dbf0SJosef Bacik 	}
171faa2dbf0SJosef Bacik 
172faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
173faa2dbf0SJosef Bacik 	if (ret) {
1743c7251f2SDavid Sterba 		test_err("couldn't find extent ref");
175faa2dbf0SJosef Bacik 		btrfs_free_path(path);
176faa2dbf0SJosef Bacik 		return ret;
177faa2dbf0SJosef Bacik 	}
178faa2dbf0SJosef Bacik 
179faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
180faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
181faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
182faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
183faa2dbf0SJosef Bacik 	btrfs_release_path(path);
184faa2dbf0SJosef Bacik 
185faa2dbf0SJosef Bacik 	key.objectid = bytenr;
186faa2dbf0SJosef Bacik 	if (parent) {
187faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
188faa2dbf0SJosef Bacik 		key.offset = parent;
189faa2dbf0SJosef Bacik 	} else {
190faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
191faa2dbf0SJosef Bacik 		key.offset = root_objectid;
192faa2dbf0SJosef Bacik 	}
193faa2dbf0SJosef Bacik 
194faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
195faa2dbf0SJosef Bacik 	if (ret) {
1963c7251f2SDavid Sterba 		test_err("couldn't find backref %d", ret);
197faa2dbf0SJosef Bacik 		btrfs_free_path(path);
198faa2dbf0SJosef Bacik 		return ret;
199faa2dbf0SJosef Bacik 	}
200faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
201faa2dbf0SJosef Bacik 	btrfs_free_path(path);
202faa2dbf0SJosef Bacik 	return ret;
203faa2dbf0SJosef Bacik }
204faa2dbf0SJosef Bacik 
205b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root,
206b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
207faa2dbf0SJosef Bacik {
208faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
209faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
210442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
211442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
212faa2dbf0SJosef Bacik 	int ret;
213faa2dbf0SJosef Bacik 
214483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
215faa2dbf0SJosef Bacik 
216e4fa7469SDavid Sterba 	test_msg("running qgroup add/remove tests");
21749a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID);
218faa2dbf0SJosef Bacik 	if (ret) {
2193c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
220faa2dbf0SJosef Bacik 		return ret;
221faa2dbf0SJosef Bacik 	}
222faa2dbf0SJosef Bacik 
223442244c9SQu Wenruo 	/*
22401327610SNicholas D Steeves 	 * Since the test trans doesn't have the complicated delayed refs,
225442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
226442244c9SQu Wenruo 	 * quota.
227442244c9SQu Wenruo 	 */
228c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
229faa2dbf0SJosef Bacik 	if (ret) {
2303c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
231faa2dbf0SJosef Bacik 		return ret;
232faa2dbf0SJosef Bacik 	}
233faa2dbf0SJosef Bacik 
234ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
235ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
236d37de92bSFilipe Manana 	if (ret) {
237d37de92bSFilipe Manana 		ulist_free(old_roots);
238faa2dbf0SJosef Bacik 		return ret;
239d37de92bSFilipe Manana 	}
240faa2dbf0SJosef Bacik 
241c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
242faa2dbf0SJosef Bacik 	if (ret) {
243442244c9SQu Wenruo 		ulist_free(old_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 
255d0ea17aeSFilipe Manana 	/* btrfs_qgroup_account_extent() always frees the ulists passed to it. */
256d0ea17aeSFilipe Manana 	old_roots = NULL;
257d0ea17aeSFilipe Manana 	new_roots = NULL;
258d0ea17aeSFilipe Manana 
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 
265c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
266442244c9SQu Wenruo 	if (ret) {
2673c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
268442244c9SQu Wenruo 		return ret;
269442244c9SQu Wenruo 	}
270faa2dbf0SJosef Bacik 
271b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
272d37de92bSFilipe Manana 	if (ret) {
273d37de92bSFilipe Manana 		ulist_free(old_roots);
274faa2dbf0SJosef Bacik 		return -EINVAL;
275d37de92bSFilipe Manana 	}
276faa2dbf0SJosef Bacik 
277c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
278faa2dbf0SJosef Bacik 	if (ret) {
279442244c9SQu Wenruo 		ulist_free(old_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) {
3293c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
330442244c9SQu Wenruo 		return ret;
331442244c9SQu Wenruo 	}
332442244c9SQu Wenruo 
333ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
334ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
335d37de92bSFilipe Manana 	if (ret) {
336d37de92bSFilipe Manana 		ulist_free(old_roots);
337faa2dbf0SJosef Bacik 		return ret;
338d37de92bSFilipe Manana 	}
339faa2dbf0SJosef Bacik 
340c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
341faa2dbf0SJosef Bacik 	if (ret) {
342442244c9SQu Wenruo 		ulist_free(old_roots);
3433c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
344faa2dbf0SJosef Bacik 		return ret;
345faa2dbf0SJosef Bacik 	}
346faa2dbf0SJosef Bacik 
3478696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3488696d760SLu Fengqi 					  new_roots);
349faa2dbf0SJosef Bacik 	if (ret) {
3503c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
351faa2dbf0SJosef Bacik 		return ret;
352faa2dbf0SJosef Bacik 	}
353faa2dbf0SJosef Bacik 
354ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
355b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
3563c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
357faa2dbf0SJosef Bacik 		return -EINVAL;
358faa2dbf0SJosef Bacik 	}
359faa2dbf0SJosef Bacik 
360c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
361442244c9SQu Wenruo 	if (ret) {
3623c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
363442244c9SQu Wenruo 		return ret;
364442244c9SQu Wenruo 	}
365442244c9SQu Wenruo 
366ef9f2db3SFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0,
367ef9f2db3SFeifei Xu 			BTRFS_FIRST_FREE_OBJECTID);
368d37de92bSFilipe Manana 	if (ret) {
369d37de92bSFilipe Manana 		ulist_free(old_roots);
370faa2dbf0SJosef Bacik 		return ret;
371d37de92bSFilipe Manana 	}
372faa2dbf0SJosef Bacik 
373c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
374faa2dbf0SJosef Bacik 	if (ret) {
375442244c9SQu Wenruo 		ulist_free(old_roots);
3763c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
377faa2dbf0SJosef Bacik 		return ret;
378faa2dbf0SJosef Bacik 	}
379faa2dbf0SJosef Bacik 
3808696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3818696d760SLu Fengqi 					  new_roots);
382faa2dbf0SJosef Bacik 	if (ret) {
3833c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
384faa2dbf0SJosef Bacik 		return ret;
385faa2dbf0SJosef Bacik 	}
386faa2dbf0SJosef Bacik 
387ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
388ef9f2db3SFeifei Xu 					nodesize, 0)) {
3893c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
390faa2dbf0SJosef Bacik 		return -EINVAL;
391faa2dbf0SJosef Bacik 	}
392faa2dbf0SJosef Bacik 
393ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
394ef9f2db3SFeifei Xu 					nodesize, 0)) {
3953c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
396faa2dbf0SJosef Bacik 		return -EINVAL;
397faa2dbf0SJosef Bacik 	}
398faa2dbf0SJosef Bacik 
399c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
400442244c9SQu Wenruo 	if (ret) {
4013c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
402442244c9SQu Wenruo 		return ret;
403442244c9SQu Wenruo 	}
404442244c9SQu Wenruo 
405ef9f2db3SFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0,
406ef9f2db3SFeifei Xu 				BTRFS_FIRST_FREE_OBJECTID);
407d37de92bSFilipe Manana 	if (ret) {
408d37de92bSFilipe Manana 		ulist_free(old_roots);
409faa2dbf0SJosef Bacik 		return ret;
410d37de92bSFilipe Manana 	}
411faa2dbf0SJosef Bacik 
412c7bcbb21SFilipe Manana 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
413faa2dbf0SJosef Bacik 	if (ret) {
414442244c9SQu Wenruo 		ulist_free(old_roots);
4153c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
416faa2dbf0SJosef Bacik 		return ret;
417faa2dbf0SJosef Bacik 	}
418faa2dbf0SJosef Bacik 
4198696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
4208696d760SLu Fengqi 					  new_roots);
421faa2dbf0SJosef Bacik 	if (ret) {
4223c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
423faa2dbf0SJosef Bacik 		return ret;
424faa2dbf0SJosef Bacik 	}
425faa2dbf0SJosef Bacik 
426ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
427ef9f2db3SFeifei Xu 					0, 0)) {
4283c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
429faa2dbf0SJosef Bacik 		return -EINVAL;
430faa2dbf0SJosef Bacik 	}
431faa2dbf0SJosef Bacik 
432ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
433ef9f2db3SFeifei Xu 					nodesize, nodesize)) {
4343c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
435faa2dbf0SJosef Bacik 		return -EINVAL;
436faa2dbf0SJosef Bacik 	}
437faa2dbf0SJosef Bacik 
438faa2dbf0SJosef Bacik 	return 0;
439faa2dbf0SJosef Bacik }
440faa2dbf0SJosef Bacik 
441b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
442faa2dbf0SJosef Bacik {
4437c0260eeSJeff Mahoney 	struct btrfs_fs_info *fs_info = NULL;
444faa2dbf0SJosef Bacik 	struct btrfs_root *root;
445faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
446faa2dbf0SJosef Bacik 	int ret = 0;
447faa2dbf0SJosef Bacik 
448da17066cSJeff Mahoney 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
4497c0260eeSJeff Mahoney 	if (!fs_info) {
45037b2a7bcSDavid Sterba 		test_std_err(TEST_ALLOC_FS_INFO);
4517c0260eeSJeff Mahoney 		return -ENOMEM;
452faa2dbf0SJosef Bacik 	}
453faa2dbf0SJosef Bacik 
454da17066cSJeff Mahoney 	root = btrfs_alloc_dummy_root(fs_info);
4557c0260eeSJeff Mahoney 	if (IS_ERR(root)) {
45652ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
4577c0260eeSJeff Mahoney 		ret = PTR_ERR(root);
458faa2dbf0SJosef Bacik 		goto out;
459faa2dbf0SJosef Bacik 	}
4607c0260eeSJeff Mahoney 
4613f556f78SDavid Sterba 	/* We are using this root as our extent root */
462abed4aaaSJosef Bacik 	root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
463abed4aaaSJosef Bacik 	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
464abed4aaaSJosef Bacik 	root->root_key.offset = 0;
465abed4aaaSJosef Bacik 	btrfs_global_root_insert(root);
4663f556f78SDavid Sterba 
4673f556f78SDavid Sterba 	/*
4683f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4693f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
4703f556f78SDavid Sterba 	 */
4713f556f78SDavid Sterba 	root->fs_info->tree_root = root;
4723f556f78SDavid Sterba 	root->fs_info->quota_root = root;
473afcdd129SJosef Bacik 	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
474faa2dbf0SJosef Bacik 
475faa2dbf0SJosef Bacik 	/*
476faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
477faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
478faa2dbf0SJosef Bacik 	 */
479da17066cSJeff Mahoney 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
480b6293c82SDan Carpenter 	if (IS_ERR(root->node)) {
4813c7251f2SDavid Sterba 		test_err("couldn't allocate dummy buffer");
482b6293c82SDan Carpenter 		ret = PTR_ERR(root->node);
483faa2dbf0SJosef Bacik 		goto out;
484faa2dbf0SJosef Bacik 	}
485b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
486b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
487b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
488faa2dbf0SJosef Bacik 
489da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
490faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
49152ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
492faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
493faa2dbf0SJosef Bacik 		goto out;
494faa2dbf0SJosef Bacik 	}
495faa2dbf0SJosef Bacik 
496ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
497faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
498faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
499faa2dbf0SJosef Bacik 	if (ret) {
5003c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
501faa2dbf0SJosef Bacik 		goto out;
502faa2dbf0SJosef Bacik 	}
5034785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
504faa2dbf0SJosef Bacik 
505da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
506faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
50752ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
508faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
509faa2dbf0SJosef Bacik 		goto out;
510faa2dbf0SJosef Bacik 	}
511faa2dbf0SJosef Bacik 
512ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
513faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
514faa2dbf0SJosef Bacik 	if (ret) {
5153c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
516faa2dbf0SJosef Bacik 		goto out;
517faa2dbf0SJosef Bacik 	}
5184785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
519faa2dbf0SJosef Bacik 
520315b76b4SDavid Sterba 	test_msg("running qgroup tests");
521b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
522faa2dbf0SJosef Bacik 	if (ret)
523faa2dbf0SJosef Bacik 		goto out;
524b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
525faa2dbf0SJosef Bacik out:
526faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
5277c0260eeSJeff Mahoney 	btrfs_free_dummy_fs_info(fs_info);
528faa2dbf0SJosef Bacik 	return ret;
529faa2dbf0SJosef Bacik }
530