xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision a2c8d27e)
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"
1407e81dc9SJosef Bacik #include "../accessors.h"
15faa2dbf0SJosef Bacik 
insert_normal_tree_ref(struct btrfs_root * root,u64 bytenr,u64 num_bytes,u64 parent,u64 root_objectid)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 
add_tree_ref(struct btrfs_root * root,u64 bytenr,u64 num_bytes,u64 parent,u64 root_objectid)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 
remove_extent_item(struct btrfs_root * root,u64 bytenr,u64 num_bytes)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 
remove_extent_ref(struct btrfs_root * root,u64 bytenr,u64 num_bytes,u64 parent,u64 root_objectid)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 
test_no_shared_qgroup(struct btrfs_root * root,u32 sectorsize,u32 nodesize)205b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root,
206b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
207faa2dbf0SJosef Bacik {
208*a2c8d27eSFilipe Manana 	struct btrfs_backref_walk_ctx ctx = { 0 };
209faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
210faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
211442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
212442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
213faa2dbf0SJosef Bacik 	int ret;
214faa2dbf0SJosef Bacik 
215483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
216faa2dbf0SJosef Bacik 
217e4fa7469SDavid Sterba 	test_msg("running qgroup add/remove tests");
21849a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID);
219faa2dbf0SJosef Bacik 	if (ret) {
2203c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
221faa2dbf0SJosef Bacik 		return ret;
222faa2dbf0SJosef Bacik 	}
223faa2dbf0SJosef Bacik 
224*a2c8d27eSFilipe Manana 	ctx.bytenr = nodesize;
225*a2c8d27eSFilipe Manana 	ctx.trans = &trans;
226*a2c8d27eSFilipe Manana 	ctx.fs_info = fs_info;
227*a2c8d27eSFilipe Manana 
228442244c9SQu Wenruo 	/*
22901327610SNicholas D Steeves 	 * Since the test trans doesn't have the complicated delayed refs,
230442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
231442244c9SQu Wenruo 	 * quota.
232442244c9SQu Wenruo 	 */
233*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
234faa2dbf0SJosef Bacik 	if (ret) {
2353c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
236faa2dbf0SJosef Bacik 		return ret;
237faa2dbf0SJosef Bacik 	}
238*a2c8d27eSFilipe Manana 	old_roots = ctx.roots;
239*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
240faa2dbf0SJosef Bacik 
241ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
242ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
243d37de92bSFilipe Manana 	if (ret) {
244d37de92bSFilipe Manana 		ulist_free(old_roots);
245faa2dbf0SJosef Bacik 		return ret;
246d37de92bSFilipe Manana 	}
247faa2dbf0SJosef Bacik 
248*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
249faa2dbf0SJosef Bacik 	if (ret) {
250442244c9SQu Wenruo 		ulist_free(old_roots);
2513c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
252442244c9SQu Wenruo 		return ret;
253442244c9SQu Wenruo 	}
254*a2c8d27eSFilipe Manana 	new_roots = ctx.roots;
255*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
256442244c9SQu Wenruo 
2578696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2588696d760SLu Fengqi 					  new_roots);
259442244c9SQu Wenruo 	if (ret) {
2603c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
261faa2dbf0SJosef Bacik 		return ret;
262faa2dbf0SJosef Bacik 	}
263faa2dbf0SJosef Bacik 
264d0ea17aeSFilipe Manana 	/* btrfs_qgroup_account_extent() always frees the ulists passed to it. */
265d0ea17aeSFilipe Manana 	old_roots = NULL;
266d0ea17aeSFilipe Manana 	new_roots = NULL;
267d0ea17aeSFilipe Manana 
268ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
269ef9f2db3SFeifei Xu 				nodesize, nodesize)) {
2703c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
271faa2dbf0SJosef Bacik 		return -EINVAL;
272faa2dbf0SJosef Bacik 	}
273442244c9SQu Wenruo 
274*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
275442244c9SQu Wenruo 	if (ret) {
2763c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
277442244c9SQu Wenruo 		return ret;
278442244c9SQu Wenruo 	}
279*a2c8d27eSFilipe Manana 	old_roots = ctx.roots;
280*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
281faa2dbf0SJosef Bacik 
282b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
283d37de92bSFilipe Manana 	if (ret) {
284d37de92bSFilipe Manana 		ulist_free(old_roots);
285faa2dbf0SJosef Bacik 		return -EINVAL;
286d37de92bSFilipe Manana 	}
287faa2dbf0SJosef Bacik 
288*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
289faa2dbf0SJosef Bacik 	if (ret) {
290442244c9SQu Wenruo 		ulist_free(old_roots);
2913c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
292442244c9SQu Wenruo 		return ret;
293faa2dbf0SJosef Bacik 	}
294*a2c8d27eSFilipe Manana 	new_roots = ctx.roots;
295*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
296faa2dbf0SJosef Bacik 
2978696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
2988696d760SLu Fengqi 					  new_roots);
299faa2dbf0SJosef Bacik 	if (ret) {
3003c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
301faa2dbf0SJosef Bacik 		return -EINVAL;
302faa2dbf0SJosef Bacik 	}
303faa2dbf0SJosef Bacik 
304ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
3053c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
306faa2dbf0SJosef Bacik 		return -EINVAL;
307faa2dbf0SJosef Bacik 	}
308faa2dbf0SJosef Bacik 
309faa2dbf0SJosef Bacik 	return 0;
310faa2dbf0SJosef Bacik }
311faa2dbf0SJosef Bacik 
312faa2dbf0SJosef Bacik /*
313faa2dbf0SJosef Bacik  * Add a ref for two different roots to make sure the shared value comes out
314faa2dbf0SJosef Bacik  * right, also remove one of the roots and make sure the exclusive count is
315faa2dbf0SJosef Bacik  * adjusted properly.
316faa2dbf0SJosef Bacik  */
test_multiple_refs(struct btrfs_root * root,u32 sectorsize,u32 nodesize)317b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root,
318b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
319faa2dbf0SJosef Bacik {
320*a2c8d27eSFilipe Manana 	struct btrfs_backref_walk_ctx ctx = { 0 };
321faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
322faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
323442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
324442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
325faa2dbf0SJosef Bacik 	int ret;
326faa2dbf0SJosef Bacik 
327483bce06SNikolay Borisov 	btrfs_init_dummy_trans(&trans, fs_info);
328faa2dbf0SJosef Bacik 
329e4fa7469SDavid Sterba 	test_msg("running qgroup multiple refs test");
330faa2dbf0SJosef Bacik 
331ef9f2db3SFeifei Xu 	/*
332ef9f2db3SFeifei Xu 	 * We have BTRFS_FS_TREE_OBJECTID created already from the
333ef9f2db3SFeifei Xu 	 * previous test.
334ef9f2db3SFeifei Xu 	 */
33549a05ecdSLu Fengqi 	ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID);
336faa2dbf0SJosef Bacik 	if (ret) {
3373c7251f2SDavid Sterba 		test_err("couldn't create a qgroup %d", ret);
338faa2dbf0SJosef Bacik 		return ret;
339faa2dbf0SJosef Bacik 	}
340faa2dbf0SJosef Bacik 
341*a2c8d27eSFilipe Manana 	ctx.bytenr = nodesize;
342*a2c8d27eSFilipe Manana 	ctx.trans = &trans;
343*a2c8d27eSFilipe Manana 	ctx.fs_info = fs_info;
344*a2c8d27eSFilipe Manana 
345*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
346442244c9SQu Wenruo 	if (ret) {
3473c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
348442244c9SQu Wenruo 		return ret;
349442244c9SQu Wenruo 	}
350*a2c8d27eSFilipe Manana 	old_roots = ctx.roots;
351*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
352442244c9SQu Wenruo 
353ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
354ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
355d37de92bSFilipe Manana 	if (ret) {
356d37de92bSFilipe Manana 		ulist_free(old_roots);
357faa2dbf0SJosef Bacik 		return ret;
358d37de92bSFilipe Manana 	}
359faa2dbf0SJosef Bacik 
360*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
361faa2dbf0SJosef Bacik 	if (ret) {
362442244c9SQu Wenruo 		ulist_free(old_roots);
3633c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
364faa2dbf0SJosef Bacik 		return ret;
365faa2dbf0SJosef Bacik 	}
366*a2c8d27eSFilipe Manana 	new_roots = ctx.roots;
367*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
368faa2dbf0SJosef Bacik 
3698696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
3708696d760SLu Fengqi 					  new_roots);
371faa2dbf0SJosef Bacik 	if (ret) {
3723c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
373faa2dbf0SJosef Bacik 		return ret;
374faa2dbf0SJosef Bacik 	}
375faa2dbf0SJosef Bacik 
376ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
377b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
3783c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
379faa2dbf0SJosef Bacik 		return -EINVAL;
380faa2dbf0SJosef Bacik 	}
381faa2dbf0SJosef Bacik 
382*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
383442244c9SQu Wenruo 	if (ret) {
3843c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
385442244c9SQu Wenruo 		return ret;
386442244c9SQu Wenruo 	}
387*a2c8d27eSFilipe Manana 	old_roots = ctx.roots;
388*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
389442244c9SQu Wenruo 
390ef9f2db3SFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0,
391ef9f2db3SFeifei Xu 			BTRFS_FIRST_FREE_OBJECTID);
392d37de92bSFilipe Manana 	if (ret) {
393d37de92bSFilipe Manana 		ulist_free(old_roots);
394faa2dbf0SJosef Bacik 		return ret;
395d37de92bSFilipe Manana 	}
396faa2dbf0SJosef Bacik 
397*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
398faa2dbf0SJosef Bacik 	if (ret) {
399442244c9SQu Wenruo 		ulist_free(old_roots);
4003c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
401faa2dbf0SJosef Bacik 		return ret;
402faa2dbf0SJosef Bacik 	}
403*a2c8d27eSFilipe Manana 	new_roots = ctx.roots;
404*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
405faa2dbf0SJosef Bacik 
4068696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
4078696d760SLu Fengqi 					  new_roots);
408faa2dbf0SJosef Bacik 	if (ret) {
4093c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
410faa2dbf0SJosef Bacik 		return ret;
411faa2dbf0SJosef Bacik 	}
412faa2dbf0SJosef Bacik 
413ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
414ef9f2db3SFeifei Xu 					nodesize, 0)) {
4153c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
416faa2dbf0SJosef Bacik 		return -EINVAL;
417faa2dbf0SJosef Bacik 	}
418faa2dbf0SJosef Bacik 
419ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
420ef9f2db3SFeifei Xu 					nodesize, 0)) {
4213c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
422faa2dbf0SJosef Bacik 		return -EINVAL;
423faa2dbf0SJosef Bacik 	}
424faa2dbf0SJosef Bacik 
425*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
426442244c9SQu Wenruo 	if (ret) {
4273c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
428442244c9SQu Wenruo 		return ret;
429442244c9SQu Wenruo 	}
430*a2c8d27eSFilipe Manana 	old_roots = ctx.roots;
431*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
432442244c9SQu Wenruo 
433ef9f2db3SFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0,
434ef9f2db3SFeifei Xu 				BTRFS_FIRST_FREE_OBJECTID);
435d37de92bSFilipe Manana 	if (ret) {
436d37de92bSFilipe Manana 		ulist_free(old_roots);
437faa2dbf0SJosef Bacik 		return ret;
438d37de92bSFilipe Manana 	}
439faa2dbf0SJosef Bacik 
440*a2c8d27eSFilipe Manana 	ret = btrfs_find_all_roots(&ctx, false);
441faa2dbf0SJosef Bacik 	if (ret) {
442442244c9SQu Wenruo 		ulist_free(old_roots);
4433c7251f2SDavid Sterba 		test_err("couldn't find old roots: %d", ret);
444faa2dbf0SJosef Bacik 		return ret;
445faa2dbf0SJosef Bacik 	}
446*a2c8d27eSFilipe Manana 	new_roots = ctx.roots;
447*a2c8d27eSFilipe Manana 	ctx.roots = NULL;
448faa2dbf0SJosef Bacik 
4498696d760SLu Fengqi 	ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
4508696d760SLu Fengqi 					  new_roots);
451faa2dbf0SJosef Bacik 	if (ret) {
4523c7251f2SDavid Sterba 		test_err("couldn't account space for a qgroup %d", ret);
453faa2dbf0SJosef Bacik 		return ret;
454faa2dbf0SJosef Bacik 	}
455faa2dbf0SJosef Bacik 
456ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
457ef9f2db3SFeifei Xu 					0, 0)) {
4583c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
459faa2dbf0SJosef Bacik 		return -EINVAL;
460faa2dbf0SJosef Bacik 	}
461faa2dbf0SJosef Bacik 
462ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
463ef9f2db3SFeifei Xu 					nodesize, nodesize)) {
4643c7251f2SDavid Sterba 		test_err("qgroup counts didn't match expected values");
465faa2dbf0SJosef Bacik 		return -EINVAL;
466faa2dbf0SJosef Bacik 	}
467faa2dbf0SJosef Bacik 
468faa2dbf0SJosef Bacik 	return 0;
469faa2dbf0SJosef Bacik }
470faa2dbf0SJosef Bacik 
btrfs_test_qgroups(u32 sectorsize,u32 nodesize)471b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
472faa2dbf0SJosef Bacik {
4737c0260eeSJeff Mahoney 	struct btrfs_fs_info *fs_info = NULL;
474faa2dbf0SJosef Bacik 	struct btrfs_root *root;
475faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
476faa2dbf0SJosef Bacik 	int ret = 0;
477faa2dbf0SJosef Bacik 
478da17066cSJeff Mahoney 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
4797c0260eeSJeff Mahoney 	if (!fs_info) {
48037b2a7bcSDavid Sterba 		test_std_err(TEST_ALLOC_FS_INFO);
4817c0260eeSJeff Mahoney 		return -ENOMEM;
482faa2dbf0SJosef Bacik 	}
483faa2dbf0SJosef Bacik 
484da17066cSJeff Mahoney 	root = btrfs_alloc_dummy_root(fs_info);
4857c0260eeSJeff Mahoney 	if (IS_ERR(root)) {
48652ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
4877c0260eeSJeff Mahoney 		ret = PTR_ERR(root);
488faa2dbf0SJosef Bacik 		goto out;
489faa2dbf0SJosef Bacik 	}
4907c0260eeSJeff Mahoney 
4913f556f78SDavid Sterba 	/* We are using this root as our extent root */
492abed4aaaSJosef Bacik 	root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
493abed4aaaSJosef Bacik 	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
494abed4aaaSJosef Bacik 	root->root_key.offset = 0;
495abed4aaaSJosef Bacik 	btrfs_global_root_insert(root);
4963f556f78SDavid Sterba 
4973f556f78SDavid Sterba 	/*
4983f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4993f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
5003f556f78SDavid Sterba 	 */
5013f556f78SDavid Sterba 	root->fs_info->tree_root = root;
5023f556f78SDavid Sterba 	root->fs_info->quota_root = root;
503afcdd129SJosef Bacik 	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
504faa2dbf0SJosef Bacik 
505faa2dbf0SJosef Bacik 	/*
506faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
507faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
508faa2dbf0SJosef Bacik 	 */
509da17066cSJeff Mahoney 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
510b6293c82SDan Carpenter 	if (IS_ERR(root->node)) {
5113c7251f2SDavid Sterba 		test_err("couldn't allocate dummy buffer");
512b6293c82SDan Carpenter 		ret = PTR_ERR(root->node);
513faa2dbf0SJosef Bacik 		goto out;
514faa2dbf0SJosef Bacik 	}
515b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
516b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
517b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
518faa2dbf0SJosef Bacik 
519da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
520faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
52152ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
522faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
523faa2dbf0SJosef Bacik 		goto out;
524faa2dbf0SJosef Bacik 	}
525faa2dbf0SJosef Bacik 
526ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
527faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
528faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
529faa2dbf0SJosef Bacik 	if (ret) {
5303c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
531faa2dbf0SJosef Bacik 		goto out;
532faa2dbf0SJosef Bacik 	}
5334785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
534faa2dbf0SJosef Bacik 
535da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
536faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
53752ab7bcaSDavid Sterba 		test_std_err(TEST_ALLOC_ROOT);
538faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
539faa2dbf0SJosef Bacik 		goto out;
540faa2dbf0SJosef Bacik 	}
541faa2dbf0SJosef Bacik 
542ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
543faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
544faa2dbf0SJosef Bacik 	if (ret) {
5453c7251f2SDavid Sterba 		test_err("couldn't insert fs root %d", ret);
546faa2dbf0SJosef Bacik 		goto out;
547faa2dbf0SJosef Bacik 	}
5484785e24fSJosef Bacik 	btrfs_put_root(tmp_root);
549faa2dbf0SJosef Bacik 
550315b76b4SDavid Sterba 	test_msg("running qgroup tests");
551b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
552faa2dbf0SJosef Bacik 	if (ret)
553faa2dbf0SJosef Bacik 		goto out;
554b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
555faa2dbf0SJosef Bacik out:
556faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
5577c0260eeSJeff Mahoney 	btrfs_free_dummy_fs_info(fs_info);
558faa2dbf0SJosef Bacik 	return ret;
559faa2dbf0SJosef Bacik }
560