xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision da17066c)
1faa2dbf0SJosef Bacik /*
2faa2dbf0SJosef Bacik  * Copyright (C) 2013 Facebook.  All rights reserved.
3faa2dbf0SJosef Bacik  *
4faa2dbf0SJosef Bacik  * This program is free software; you can redistribute it and/or
5faa2dbf0SJosef Bacik  * modify it under the terms of the GNU General Public
6faa2dbf0SJosef Bacik  * License v2 as published by the Free Software Foundation.
7faa2dbf0SJosef Bacik  *
8faa2dbf0SJosef Bacik  * This program is distributed in the hope that it will be useful,
9faa2dbf0SJosef Bacik  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10faa2dbf0SJosef Bacik  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11faa2dbf0SJosef Bacik  * General Public License for more details.
12faa2dbf0SJosef Bacik  *
13faa2dbf0SJosef Bacik  * You should have received a copy of the GNU General Public
14faa2dbf0SJosef Bacik  * License along with this program; if not, write to the
15faa2dbf0SJosef Bacik  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16faa2dbf0SJosef Bacik  * Boston, MA 021110-1307, USA.
17faa2dbf0SJosef Bacik  */
18faa2dbf0SJosef Bacik 
19b9ef22deSFeifei Xu #include <linux/types.h>
20faa2dbf0SJosef Bacik #include "btrfs-tests.h"
21faa2dbf0SJosef Bacik #include "../ctree.h"
22faa2dbf0SJosef Bacik #include "../transaction.h"
23faa2dbf0SJosef Bacik #include "../disk-io.h"
24faa2dbf0SJosef Bacik #include "../qgroup.h"
25442244c9SQu Wenruo #include "../backref.h"
26faa2dbf0SJosef Bacik 
27faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
28faa2dbf0SJosef Bacik 				  u64 num_bytes, u64 parent, u64 root_objectid)
29faa2dbf0SJosef Bacik {
30faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
31faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
32faa2dbf0SJosef Bacik 	struct btrfs_extent_inline_ref *iref;
33faa2dbf0SJosef Bacik 	struct btrfs_tree_block_info *block_info;
34faa2dbf0SJosef Bacik 	struct btrfs_path *path;
35faa2dbf0SJosef Bacik 	struct extent_buffer *leaf;
36faa2dbf0SJosef Bacik 	struct btrfs_key ins;
37faa2dbf0SJosef Bacik 	u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
38faa2dbf0SJosef Bacik 	int ret;
39faa2dbf0SJosef Bacik 
407c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
41faa2dbf0SJosef Bacik 
42faa2dbf0SJosef Bacik 	ins.objectid = bytenr;
43faa2dbf0SJosef Bacik 	ins.type = BTRFS_EXTENT_ITEM_KEY;
44faa2dbf0SJosef Bacik 	ins.offset = num_bytes;
45faa2dbf0SJosef Bacik 
46faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
47faa2dbf0SJosef Bacik 	if (!path) {
48faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
49faa2dbf0SJosef Bacik 		return -ENOMEM;
50faa2dbf0SJosef Bacik 	}
51faa2dbf0SJosef Bacik 
52faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
53faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
54faa2dbf0SJosef Bacik 	if (ret) {
55faa2dbf0SJosef Bacik 		test_msg("Couldn't insert ref %d\n", ret);
56faa2dbf0SJosef Bacik 		btrfs_free_path(path);
57faa2dbf0SJosef Bacik 		return ret;
58faa2dbf0SJosef Bacik 	}
59faa2dbf0SJosef Bacik 
60faa2dbf0SJosef Bacik 	leaf = path->nodes[0];
61faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
62faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(leaf, item, 1);
63faa2dbf0SJosef Bacik 	btrfs_set_extent_generation(leaf, item, 1);
64faa2dbf0SJosef Bacik 	btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
65faa2dbf0SJosef Bacik 	block_info = (struct btrfs_tree_block_info *)(item + 1);
66faa2dbf0SJosef Bacik 	btrfs_set_tree_block_level(leaf, block_info, 1);
67faa2dbf0SJosef Bacik 	iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
68faa2dbf0SJosef Bacik 	if (parent > 0) {
69faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref,
70faa2dbf0SJosef Bacik 						 BTRFS_SHARED_BLOCK_REF_KEY);
71faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
72faa2dbf0SJosef Bacik 	} else {
73faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
74faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
75faa2dbf0SJosef Bacik 	}
76faa2dbf0SJosef Bacik 	btrfs_free_path(path);
77faa2dbf0SJosef Bacik 	return 0;
78faa2dbf0SJosef Bacik }
79faa2dbf0SJosef Bacik 
80faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
81faa2dbf0SJosef Bacik 			u64 parent, u64 root_objectid)
82faa2dbf0SJosef Bacik {
83faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
84faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
85faa2dbf0SJosef Bacik 	struct btrfs_path *path;
86faa2dbf0SJosef Bacik 	struct btrfs_key key;
87faa2dbf0SJosef Bacik 	u64 refs;
88faa2dbf0SJosef Bacik 	int ret;
89faa2dbf0SJosef Bacik 
907c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
91faa2dbf0SJosef Bacik 
92faa2dbf0SJosef Bacik 	key.objectid = bytenr;
93faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
94faa2dbf0SJosef Bacik 	key.offset = num_bytes;
95faa2dbf0SJosef Bacik 
96faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
97faa2dbf0SJosef Bacik 	if (!path) {
98faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
99faa2dbf0SJosef Bacik 		return -ENOMEM;
100faa2dbf0SJosef Bacik 	}
101faa2dbf0SJosef Bacik 
102faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
103faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
104faa2dbf0SJosef Bacik 	if (ret) {
105faa2dbf0SJosef Bacik 		test_msg("Couldn't find extent ref\n");
106faa2dbf0SJosef Bacik 		btrfs_free_path(path);
107faa2dbf0SJosef Bacik 		return ret;
108faa2dbf0SJosef Bacik 	}
109faa2dbf0SJosef Bacik 
110faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
111faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
112faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
113faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs + 1);
114faa2dbf0SJosef Bacik 	btrfs_release_path(path);
115faa2dbf0SJosef Bacik 
116faa2dbf0SJosef Bacik 	key.objectid = bytenr;
117faa2dbf0SJosef Bacik 	if (parent) {
118faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
119faa2dbf0SJosef Bacik 		key.offset = parent;
120faa2dbf0SJosef Bacik 	} else {
121faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
122faa2dbf0SJosef Bacik 		key.offset = root_objectid;
123faa2dbf0SJosef Bacik 	}
124faa2dbf0SJosef Bacik 
125faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
126faa2dbf0SJosef Bacik 	if (ret)
127faa2dbf0SJosef Bacik 		test_msg("Failed to insert backref\n");
128faa2dbf0SJosef Bacik 	btrfs_free_path(path);
129faa2dbf0SJosef Bacik 	return ret;
130faa2dbf0SJosef Bacik }
131faa2dbf0SJosef Bacik 
132faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
133faa2dbf0SJosef Bacik 			      u64 num_bytes)
134faa2dbf0SJosef Bacik {
135faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
136faa2dbf0SJosef Bacik 	struct btrfs_key key;
137faa2dbf0SJosef Bacik 	struct btrfs_path *path;
138faa2dbf0SJosef Bacik 	int ret;
139faa2dbf0SJosef Bacik 
1407c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
141faa2dbf0SJosef Bacik 
142faa2dbf0SJosef Bacik 	key.objectid = bytenr;
143faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
144faa2dbf0SJosef Bacik 	key.offset = num_bytes;
145faa2dbf0SJosef Bacik 
146faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
147faa2dbf0SJosef Bacik 	if (!path) {
148faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
149faa2dbf0SJosef Bacik 		return -ENOMEM;
150faa2dbf0SJosef Bacik 	}
151faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
152faa2dbf0SJosef Bacik 
153faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
154faa2dbf0SJosef Bacik 	if (ret) {
155faa2dbf0SJosef Bacik 		test_msg("Didn't find our key %d\n", ret);
156faa2dbf0SJosef Bacik 		btrfs_free_path(path);
157faa2dbf0SJosef Bacik 		return ret;
158faa2dbf0SJosef Bacik 	}
159faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
160faa2dbf0SJosef Bacik 	btrfs_free_path(path);
161faa2dbf0SJosef Bacik 	return 0;
162faa2dbf0SJosef Bacik }
163faa2dbf0SJosef Bacik 
164faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
165faa2dbf0SJosef Bacik 			     u64 num_bytes, u64 parent, u64 root_objectid)
166faa2dbf0SJosef Bacik {
167faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
168faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
169faa2dbf0SJosef Bacik 	struct btrfs_path *path;
170faa2dbf0SJosef Bacik 	struct btrfs_key key;
171faa2dbf0SJosef Bacik 	u64 refs;
172faa2dbf0SJosef Bacik 	int ret;
173faa2dbf0SJosef Bacik 
1747c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
175faa2dbf0SJosef Bacik 
176faa2dbf0SJosef Bacik 	key.objectid = bytenr;
177faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
178faa2dbf0SJosef Bacik 	key.offset = num_bytes;
179faa2dbf0SJosef Bacik 
180faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
181faa2dbf0SJosef Bacik 	if (!path) {
182faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
183faa2dbf0SJosef Bacik 		return -ENOMEM;
184faa2dbf0SJosef Bacik 	}
185faa2dbf0SJosef Bacik 
186faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
187faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
188faa2dbf0SJosef Bacik 	if (ret) {
189faa2dbf0SJosef Bacik 		test_msg("Couldn't find extent ref\n");
190faa2dbf0SJosef Bacik 		btrfs_free_path(path);
191faa2dbf0SJosef Bacik 		return ret;
192faa2dbf0SJosef Bacik 	}
193faa2dbf0SJosef Bacik 
194faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
195faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
196faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
197faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
198faa2dbf0SJosef Bacik 	btrfs_release_path(path);
199faa2dbf0SJosef Bacik 
200faa2dbf0SJosef Bacik 	key.objectid = bytenr;
201faa2dbf0SJosef Bacik 	if (parent) {
202faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
203faa2dbf0SJosef Bacik 		key.offset = parent;
204faa2dbf0SJosef Bacik 	} else {
205faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
206faa2dbf0SJosef Bacik 		key.offset = root_objectid;
207faa2dbf0SJosef Bacik 	}
208faa2dbf0SJosef Bacik 
209faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
210faa2dbf0SJosef Bacik 	if (ret) {
211faa2dbf0SJosef Bacik 		test_msg("Couldn't find backref %d\n", ret);
212faa2dbf0SJosef Bacik 		btrfs_free_path(path);
213faa2dbf0SJosef Bacik 		return ret;
214faa2dbf0SJosef Bacik 	}
215faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
216faa2dbf0SJosef Bacik 	btrfs_free_path(path);
217faa2dbf0SJosef Bacik 	return ret;
218faa2dbf0SJosef Bacik }
219faa2dbf0SJosef Bacik 
220b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root,
221b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
222faa2dbf0SJosef Bacik {
223faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
224faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
225442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
226442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
227faa2dbf0SJosef Bacik 	int ret;
228faa2dbf0SJosef Bacik 
2297c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
230faa2dbf0SJosef Bacik 
231faa2dbf0SJosef Bacik 	test_msg("Qgroup basic add\n");
232ef9f2db3SFeifei Xu 	ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FS_TREE_OBJECTID);
233faa2dbf0SJosef Bacik 	if (ret) {
234faa2dbf0SJosef Bacik 		test_msg("Couldn't create a qgroup %d\n", ret);
235faa2dbf0SJosef Bacik 		return ret;
236faa2dbf0SJosef Bacik 	}
237faa2dbf0SJosef Bacik 
238442244c9SQu Wenruo 	/*
23901327610SNicholas D Steeves 	 * Since the test trans doesn't have the complicated delayed refs,
240442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
241442244c9SQu Wenruo 	 * quota.
242442244c9SQu Wenruo 	 */
243b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
244faa2dbf0SJosef Bacik 	if (ret) {
245442244c9SQu Wenruo 		ulist_free(old_roots);
246442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
247faa2dbf0SJosef Bacik 		return ret;
248faa2dbf0SJosef Bacik 	}
249faa2dbf0SJosef Bacik 
250ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
251ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
252faa2dbf0SJosef Bacik 	if (ret)
253faa2dbf0SJosef Bacik 		return ret;
254faa2dbf0SJosef Bacik 
255b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
256faa2dbf0SJosef Bacik 	if (ret) {
257442244c9SQu Wenruo 		ulist_free(old_roots);
258442244c9SQu Wenruo 		ulist_free(new_roots);
259442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
260442244c9SQu Wenruo 		return ret;
261442244c9SQu Wenruo 	}
262442244c9SQu Wenruo 
263b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
264b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
265442244c9SQu Wenruo 	if (ret) {
266442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
267faa2dbf0SJosef Bacik 		return ret;
268faa2dbf0SJosef Bacik 	}
269faa2dbf0SJosef Bacik 
270ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
271ef9f2db3SFeifei Xu 				nodesize, nodesize)) {
272faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
273faa2dbf0SJosef Bacik 		return -EINVAL;
274faa2dbf0SJosef Bacik 	}
275442244c9SQu Wenruo 	old_roots = NULL;
276442244c9SQu Wenruo 	new_roots = NULL;
277442244c9SQu Wenruo 
278b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
279442244c9SQu Wenruo 	if (ret) {
280442244c9SQu Wenruo 		ulist_free(old_roots);
281442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
282442244c9SQu Wenruo 		return ret;
283442244c9SQu Wenruo 	}
284faa2dbf0SJosef Bacik 
285b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
286faa2dbf0SJosef Bacik 	if (ret)
287faa2dbf0SJosef Bacik 		return -EINVAL;
288faa2dbf0SJosef Bacik 
289b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
290faa2dbf0SJosef Bacik 	if (ret) {
291442244c9SQu Wenruo 		ulist_free(old_roots);
292442244c9SQu Wenruo 		ulist_free(new_roots);
293442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
294442244c9SQu Wenruo 		return ret;
295faa2dbf0SJosef Bacik 	}
296faa2dbf0SJosef Bacik 
297b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
298b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
299faa2dbf0SJosef Bacik 	if (ret) {
300442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
301faa2dbf0SJosef Bacik 		return -EINVAL;
302faa2dbf0SJosef Bacik 	}
303faa2dbf0SJosef Bacik 
304ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
305faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
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  */
317b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root,
318b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
319faa2dbf0SJosef Bacik {
320faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
321faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
322442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
323442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
324faa2dbf0SJosef Bacik 	int ret;
325faa2dbf0SJosef Bacik 
3267c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
327faa2dbf0SJosef Bacik 
328faa2dbf0SJosef Bacik 	test_msg("Qgroup multiple refs test\n");
329faa2dbf0SJosef Bacik 
330ef9f2db3SFeifei Xu 	/*
331ef9f2db3SFeifei Xu 	 * We have BTRFS_FS_TREE_OBJECTID created already from the
332ef9f2db3SFeifei Xu 	 * previous test.
333ef9f2db3SFeifei Xu 	 */
334ef9f2db3SFeifei Xu 	ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FIRST_FREE_OBJECTID);
335faa2dbf0SJosef Bacik 	if (ret) {
336faa2dbf0SJosef Bacik 		test_msg("Couldn't create a qgroup %d\n", ret);
337faa2dbf0SJosef Bacik 		return ret;
338faa2dbf0SJosef Bacik 	}
339faa2dbf0SJosef Bacik 
340b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
341442244c9SQu Wenruo 	if (ret) {
342442244c9SQu Wenruo 		ulist_free(old_roots);
343442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
344442244c9SQu Wenruo 		return ret;
345442244c9SQu Wenruo 	}
346442244c9SQu Wenruo 
347ef9f2db3SFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
348ef9f2db3SFeifei Xu 				BTRFS_FS_TREE_OBJECTID);
349faa2dbf0SJosef Bacik 	if (ret)
350faa2dbf0SJosef Bacik 		return ret;
351faa2dbf0SJosef Bacik 
352b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
353faa2dbf0SJosef Bacik 	if (ret) {
354442244c9SQu Wenruo 		ulist_free(old_roots);
355442244c9SQu Wenruo 		ulist_free(new_roots);
356442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
357faa2dbf0SJosef Bacik 		return ret;
358faa2dbf0SJosef Bacik 	}
359faa2dbf0SJosef Bacik 
360b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
361b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
362faa2dbf0SJosef Bacik 	if (ret) {
363442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
364faa2dbf0SJosef Bacik 		return ret;
365faa2dbf0SJosef Bacik 	}
366faa2dbf0SJosef Bacik 
367ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
368b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
369faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
370faa2dbf0SJosef Bacik 		return -EINVAL;
371faa2dbf0SJosef Bacik 	}
372faa2dbf0SJosef Bacik 
373b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
374442244c9SQu Wenruo 	if (ret) {
375442244c9SQu Wenruo 		ulist_free(old_roots);
376442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
377442244c9SQu Wenruo 		return ret;
378442244c9SQu Wenruo 	}
379442244c9SQu Wenruo 
380ef9f2db3SFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0,
381ef9f2db3SFeifei Xu 			BTRFS_FIRST_FREE_OBJECTID);
382faa2dbf0SJosef Bacik 	if (ret)
383faa2dbf0SJosef Bacik 		return ret;
384faa2dbf0SJosef Bacik 
385b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
386faa2dbf0SJosef Bacik 	if (ret) {
387442244c9SQu Wenruo 		ulist_free(old_roots);
388442244c9SQu Wenruo 		ulist_free(new_roots);
389442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
390faa2dbf0SJosef Bacik 		return ret;
391faa2dbf0SJosef Bacik 	}
392faa2dbf0SJosef Bacik 
393b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
394b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
395faa2dbf0SJosef Bacik 	if (ret) {
396442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
397faa2dbf0SJosef Bacik 		return ret;
398faa2dbf0SJosef Bacik 	}
399faa2dbf0SJosef Bacik 
400ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
401ef9f2db3SFeifei Xu 					nodesize, 0)) {
402faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
403faa2dbf0SJosef Bacik 		return -EINVAL;
404faa2dbf0SJosef Bacik 	}
405faa2dbf0SJosef Bacik 
406ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
407ef9f2db3SFeifei Xu 					nodesize, 0)) {
408faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
409faa2dbf0SJosef Bacik 		return -EINVAL;
410faa2dbf0SJosef Bacik 	}
411faa2dbf0SJosef Bacik 
412b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
413442244c9SQu Wenruo 	if (ret) {
414442244c9SQu Wenruo 		ulist_free(old_roots);
415442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
416442244c9SQu Wenruo 		return ret;
417442244c9SQu Wenruo 	}
418442244c9SQu Wenruo 
419ef9f2db3SFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0,
420ef9f2db3SFeifei Xu 				BTRFS_FIRST_FREE_OBJECTID);
421faa2dbf0SJosef Bacik 	if (ret)
422faa2dbf0SJosef Bacik 		return ret;
423faa2dbf0SJosef Bacik 
424b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
425faa2dbf0SJosef Bacik 	if (ret) {
426442244c9SQu Wenruo 		ulist_free(old_roots);
427442244c9SQu Wenruo 		ulist_free(new_roots);
428442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
429faa2dbf0SJosef Bacik 		return ret;
430faa2dbf0SJosef Bacik 	}
431faa2dbf0SJosef Bacik 
432b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
433b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
434faa2dbf0SJosef Bacik 	if (ret) {
435442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
436faa2dbf0SJosef Bacik 		return ret;
437faa2dbf0SJosef Bacik 	}
438faa2dbf0SJosef Bacik 
439ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
440ef9f2db3SFeifei Xu 					0, 0)) {
441faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
442faa2dbf0SJosef Bacik 		return -EINVAL;
443faa2dbf0SJosef Bacik 	}
444faa2dbf0SJosef Bacik 
445ef9f2db3SFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
446ef9f2db3SFeifei Xu 					nodesize, nodesize)) {
447faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
448faa2dbf0SJosef Bacik 		return -EINVAL;
449faa2dbf0SJosef Bacik 	}
450faa2dbf0SJosef Bacik 
451faa2dbf0SJosef Bacik 	return 0;
452faa2dbf0SJosef Bacik }
453faa2dbf0SJosef Bacik 
454b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
455faa2dbf0SJosef Bacik {
4567c0260eeSJeff Mahoney 	struct btrfs_fs_info *fs_info = NULL;
457faa2dbf0SJosef Bacik 	struct btrfs_root *root;
458faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
459faa2dbf0SJosef Bacik 	int ret = 0;
460faa2dbf0SJosef Bacik 
461da17066cSJeff Mahoney 	fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
4627c0260eeSJeff Mahoney 	if (!fs_info) {
4637c0260eeSJeff Mahoney 		test_msg("Couldn't allocate dummy fs info\n");
4647c0260eeSJeff Mahoney 		return -ENOMEM;
465faa2dbf0SJosef Bacik 	}
466faa2dbf0SJosef Bacik 
467da17066cSJeff Mahoney 	root = btrfs_alloc_dummy_root(fs_info);
4687c0260eeSJeff Mahoney 	if (IS_ERR(root)) {
4697c0260eeSJeff Mahoney 		test_msg("Couldn't allocate root\n");
4707c0260eeSJeff Mahoney 		ret = PTR_ERR(root);
471faa2dbf0SJosef Bacik 		goto out;
472faa2dbf0SJosef Bacik 	}
4737c0260eeSJeff Mahoney 
4743f556f78SDavid Sterba 	/* We are using this root as our extent root */
4753f556f78SDavid Sterba 	root->fs_info->extent_root = root;
4763f556f78SDavid Sterba 
4773f556f78SDavid Sterba 	/*
4783f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4793f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
4803f556f78SDavid Sterba 	 */
4813f556f78SDavid Sterba 	root->fs_info->tree_root = root;
4823f556f78SDavid Sterba 	root->fs_info->quota_root = root;
483afcdd129SJosef Bacik 	set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
484faa2dbf0SJosef Bacik 
485faa2dbf0SJosef Bacik 	/*
486faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
487faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
488faa2dbf0SJosef Bacik 	 */
489da17066cSJeff Mahoney 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
490faa2dbf0SJosef Bacik 	if (!root->node) {
491faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate dummy buffer\n");
492faa2dbf0SJosef Bacik 		ret = -ENOMEM;
493faa2dbf0SJosef Bacik 		goto out;
494faa2dbf0SJosef Bacik 	}
495b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
496b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
497b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
498faa2dbf0SJosef Bacik 
499da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
500faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
501faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
502faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
503faa2dbf0SJosef Bacik 		goto out;
504faa2dbf0SJosef Bacik 	}
505faa2dbf0SJosef Bacik 
506ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
507faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
508faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
509faa2dbf0SJosef Bacik 	if (ret) {
510faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
511faa2dbf0SJosef Bacik 		goto out;
512faa2dbf0SJosef Bacik 	}
513faa2dbf0SJosef Bacik 
514da17066cSJeff Mahoney 	tmp_root = btrfs_alloc_dummy_root(fs_info);
515faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
516faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
517faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
518faa2dbf0SJosef Bacik 		goto out;
519faa2dbf0SJosef Bacik 	}
520faa2dbf0SJosef Bacik 
521ef9f2db3SFeifei Xu 	tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
522faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
523faa2dbf0SJosef Bacik 	if (ret) {
524faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
525faa2dbf0SJosef Bacik 		goto out;
526faa2dbf0SJosef Bacik 	}
527faa2dbf0SJosef Bacik 
528faa2dbf0SJosef Bacik 	test_msg("Running qgroup tests\n");
529b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
530faa2dbf0SJosef Bacik 	if (ret)
531faa2dbf0SJosef Bacik 		goto out;
532b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
533faa2dbf0SJosef Bacik out:
534faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
5357c0260eeSJeff Mahoney 	btrfs_free_dummy_fs_info(fs_info);
536faa2dbf0SJosef Bacik 	return ret;
537faa2dbf0SJosef Bacik }
538