xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision b9ef22de)
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");
2324087cf24SDongsheng Yang 	ret = btrfs_create_qgroup(NULL, fs_info, 5);
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 
250b9ef22deSFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 5);
251faa2dbf0SJosef Bacik 	if (ret)
252faa2dbf0SJosef Bacik 		return ret;
253faa2dbf0SJosef Bacik 
254b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
255faa2dbf0SJosef Bacik 	if (ret) {
256442244c9SQu Wenruo 		ulist_free(old_roots);
257442244c9SQu Wenruo 		ulist_free(new_roots);
258442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
259442244c9SQu Wenruo 		return ret;
260442244c9SQu Wenruo 	}
261442244c9SQu Wenruo 
262b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
263b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
264442244c9SQu Wenruo 	if (ret) {
265442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
266faa2dbf0SJosef Bacik 		return ret;
267faa2dbf0SJosef Bacik 	}
268faa2dbf0SJosef Bacik 
269b9ef22deSFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, nodesize)) {
270faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
271faa2dbf0SJosef Bacik 		return -EINVAL;
272faa2dbf0SJosef Bacik 	}
273442244c9SQu Wenruo 	old_roots = NULL;
274442244c9SQu Wenruo 	new_roots = NULL;
275442244c9SQu Wenruo 
276b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
277442244c9SQu Wenruo 	if (ret) {
278442244c9SQu Wenruo 		ulist_free(old_roots);
279442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
280442244c9SQu Wenruo 		return ret;
281442244c9SQu Wenruo 	}
282faa2dbf0SJosef Bacik 
283b9ef22deSFeifei Xu 	ret = remove_extent_item(root, nodesize, nodesize);
284faa2dbf0SJosef Bacik 	if (ret)
285faa2dbf0SJosef Bacik 		return -EINVAL;
286faa2dbf0SJosef Bacik 
287b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
288faa2dbf0SJosef Bacik 	if (ret) {
289442244c9SQu Wenruo 		ulist_free(old_roots);
290442244c9SQu Wenruo 		ulist_free(new_roots);
291442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
292442244c9SQu Wenruo 		return ret;
293faa2dbf0SJosef Bacik 	}
294faa2dbf0SJosef Bacik 
295b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
296b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
297faa2dbf0SJosef Bacik 	if (ret) {
298442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
299faa2dbf0SJosef Bacik 		return -EINVAL;
300faa2dbf0SJosef Bacik 	}
301faa2dbf0SJosef Bacik 
302faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) {
303faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
304faa2dbf0SJosef Bacik 		return -EINVAL;
305faa2dbf0SJosef Bacik 	}
306faa2dbf0SJosef Bacik 
307faa2dbf0SJosef Bacik 	return 0;
308faa2dbf0SJosef Bacik }
309faa2dbf0SJosef Bacik 
310faa2dbf0SJosef Bacik /*
311faa2dbf0SJosef Bacik  * Add a ref for two different roots to make sure the shared value comes out
312faa2dbf0SJosef Bacik  * right, also remove one of the roots and make sure the exclusive count is
313faa2dbf0SJosef Bacik  * adjusted properly.
314faa2dbf0SJosef Bacik  */
315b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root,
316b9ef22deSFeifei Xu 		u32 sectorsize, u32 nodesize)
317faa2dbf0SJosef Bacik {
318faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
319faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
320442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
321442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
322faa2dbf0SJosef Bacik 	int ret;
323faa2dbf0SJosef Bacik 
3247c55ee0cSOmar Sandoval 	btrfs_init_dummy_trans(&trans);
325faa2dbf0SJosef Bacik 
326faa2dbf0SJosef Bacik 	test_msg("Qgroup multiple refs test\n");
327faa2dbf0SJosef Bacik 
328faa2dbf0SJosef Bacik 	/* We have 5 created already from the previous test */
3294087cf24SDongsheng Yang 	ret = btrfs_create_qgroup(NULL, fs_info, 256);
330faa2dbf0SJosef Bacik 	if (ret) {
331faa2dbf0SJosef Bacik 		test_msg("Couldn't create a qgroup %d\n", ret);
332faa2dbf0SJosef Bacik 		return ret;
333faa2dbf0SJosef Bacik 	}
334faa2dbf0SJosef Bacik 
335b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
336442244c9SQu Wenruo 	if (ret) {
337442244c9SQu Wenruo 		ulist_free(old_roots);
338442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
339442244c9SQu Wenruo 		return ret;
340442244c9SQu Wenruo 	}
341442244c9SQu Wenruo 
342b9ef22deSFeifei Xu 	ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 5);
343faa2dbf0SJosef Bacik 	if (ret)
344faa2dbf0SJosef Bacik 		return ret;
345faa2dbf0SJosef Bacik 
346b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
347faa2dbf0SJosef Bacik 	if (ret) {
348442244c9SQu Wenruo 		ulist_free(old_roots);
349442244c9SQu Wenruo 		ulist_free(new_roots);
350442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
351faa2dbf0SJosef Bacik 		return ret;
352faa2dbf0SJosef Bacik 	}
353faa2dbf0SJosef Bacik 
354b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
355b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
356faa2dbf0SJosef Bacik 	if (ret) {
357442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
358faa2dbf0SJosef Bacik 		return ret;
359faa2dbf0SJosef Bacik 	}
360faa2dbf0SJosef Bacik 
361b9ef22deSFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, 5,
362b9ef22deSFeifei Xu 				       nodesize, nodesize)) {
363faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
364faa2dbf0SJosef Bacik 		return -EINVAL;
365faa2dbf0SJosef Bacik 	}
366faa2dbf0SJosef Bacik 
367b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
368442244c9SQu Wenruo 	if (ret) {
369442244c9SQu Wenruo 		ulist_free(old_roots);
370442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
371442244c9SQu Wenruo 		return ret;
372442244c9SQu Wenruo 	}
373442244c9SQu Wenruo 
374b9ef22deSFeifei Xu 	ret = add_tree_ref(root, nodesize, nodesize, 0, 256);
375faa2dbf0SJosef Bacik 	if (ret)
376faa2dbf0SJosef Bacik 		return ret;
377faa2dbf0SJosef Bacik 
378b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
379faa2dbf0SJosef Bacik 	if (ret) {
380442244c9SQu Wenruo 		ulist_free(old_roots);
381442244c9SQu Wenruo 		ulist_free(new_roots);
382442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
383faa2dbf0SJosef Bacik 		return ret;
384faa2dbf0SJosef Bacik 	}
385faa2dbf0SJosef Bacik 
386b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
387b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
388faa2dbf0SJosef Bacik 	if (ret) {
389442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
390faa2dbf0SJosef Bacik 		return ret;
391faa2dbf0SJosef Bacik 	}
392faa2dbf0SJosef Bacik 
393b9ef22deSFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, 0)) {
394faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
395faa2dbf0SJosef Bacik 		return -EINVAL;
396faa2dbf0SJosef Bacik 	}
397faa2dbf0SJosef Bacik 
398b9ef22deSFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, 256, nodesize, 0)) {
399faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
400faa2dbf0SJosef Bacik 		return -EINVAL;
401faa2dbf0SJosef Bacik 	}
402faa2dbf0SJosef Bacik 
403b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
404442244c9SQu Wenruo 	if (ret) {
405442244c9SQu Wenruo 		ulist_free(old_roots);
406442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
407442244c9SQu Wenruo 		return ret;
408442244c9SQu Wenruo 	}
409442244c9SQu Wenruo 
410b9ef22deSFeifei Xu 	ret = remove_extent_ref(root, nodesize, nodesize, 0, 256);
411faa2dbf0SJosef Bacik 	if (ret)
412faa2dbf0SJosef Bacik 		return ret;
413faa2dbf0SJosef Bacik 
414b9ef22deSFeifei Xu 	ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
415faa2dbf0SJosef Bacik 	if (ret) {
416442244c9SQu Wenruo 		ulist_free(old_roots);
417442244c9SQu Wenruo 		ulist_free(new_roots);
418442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
419faa2dbf0SJosef Bacik 		return ret;
420faa2dbf0SJosef Bacik 	}
421faa2dbf0SJosef Bacik 
422b9ef22deSFeifei Xu 	ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
423b9ef22deSFeifei Xu 					  nodesize, old_roots, new_roots);
424faa2dbf0SJosef Bacik 	if (ret) {
425442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
426faa2dbf0SJosef Bacik 		return ret;
427faa2dbf0SJosef Bacik 	}
428faa2dbf0SJosef Bacik 
429faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) {
430faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
431faa2dbf0SJosef Bacik 		return -EINVAL;
432faa2dbf0SJosef Bacik 	}
433faa2dbf0SJosef Bacik 
434b9ef22deSFeifei Xu 	if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, nodesize)) {
435faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
436faa2dbf0SJosef Bacik 		return -EINVAL;
437faa2dbf0SJosef Bacik 	}
438faa2dbf0SJosef Bacik 
439faa2dbf0SJosef Bacik 	return 0;
440faa2dbf0SJosef Bacik }
441faa2dbf0SJosef Bacik 
442b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
443faa2dbf0SJosef Bacik {
444faa2dbf0SJosef Bacik 	struct btrfs_root *root;
445faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
446faa2dbf0SJosef Bacik 	int ret = 0;
447faa2dbf0SJosef Bacik 
448b9ef22deSFeifei Xu 	root = btrfs_alloc_dummy_root(sectorsize, nodesize);
449faa2dbf0SJosef Bacik 	if (IS_ERR(root)) {
450faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate root\n");
451faa2dbf0SJosef Bacik 		return PTR_ERR(root);
452faa2dbf0SJosef Bacik 	}
453faa2dbf0SJosef Bacik 
454faa2dbf0SJosef Bacik 	root->fs_info = btrfs_alloc_dummy_fs_info();
455faa2dbf0SJosef Bacik 	if (!root->fs_info) {
456faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate dummy fs info\n");
457faa2dbf0SJosef Bacik 		ret = -ENOMEM;
458faa2dbf0SJosef Bacik 		goto out;
459faa2dbf0SJosef Bacik 	}
4603f556f78SDavid Sterba 	/* We are using this root as our extent root */
4613f556f78SDavid Sterba 	root->fs_info->extent_root = root;
4623f556f78SDavid Sterba 
4633f556f78SDavid Sterba 	/*
4643f556f78SDavid Sterba 	 * Some of the paths we test assume we have a filled out fs_info, so we
4653f556f78SDavid Sterba 	 * just need to add the root in there so we don't panic.
4663f556f78SDavid Sterba 	 */
4673f556f78SDavid Sterba 	root->fs_info->tree_root = root;
4683f556f78SDavid Sterba 	root->fs_info->quota_root = root;
4693f556f78SDavid Sterba 	root->fs_info->quota_enabled = 1;
470faa2dbf0SJosef Bacik 
471faa2dbf0SJosef Bacik 	/*
472faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
473faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
474faa2dbf0SJosef Bacik 	 */
475b9ef22deSFeifei Xu 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize,
476b9ef22deSFeifei Xu 					nodesize);
477faa2dbf0SJosef Bacik 	if (!root->node) {
478faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate dummy buffer\n");
479faa2dbf0SJosef Bacik 		ret = -ENOMEM;
480faa2dbf0SJosef Bacik 		goto out;
481faa2dbf0SJosef Bacik 	}
482b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
483b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
484b9ef22deSFeifei Xu 	root->alloc_bytenr += 2 * nodesize;
485faa2dbf0SJosef Bacik 
486b9ef22deSFeifei Xu 	tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
487faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
488faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
489faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
490faa2dbf0SJosef Bacik 		goto out;
491faa2dbf0SJosef Bacik 	}
492faa2dbf0SJosef Bacik 
493faa2dbf0SJosef Bacik 	tmp_root->root_key.objectid = 5;
494faa2dbf0SJosef Bacik 	root->fs_info->fs_root = tmp_root;
495faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
496faa2dbf0SJosef Bacik 	if (ret) {
497faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
498faa2dbf0SJosef Bacik 		goto out;
499faa2dbf0SJosef Bacik 	}
500faa2dbf0SJosef Bacik 
501b9ef22deSFeifei Xu 	tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
502faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
503faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
504faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
505faa2dbf0SJosef Bacik 		goto out;
506faa2dbf0SJosef Bacik 	}
507faa2dbf0SJosef Bacik 
508faa2dbf0SJosef Bacik 	tmp_root->root_key.objectid = 256;
509faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
510faa2dbf0SJosef Bacik 	if (ret) {
511faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
512faa2dbf0SJosef Bacik 		goto out;
513faa2dbf0SJosef Bacik 	}
514faa2dbf0SJosef Bacik 
515faa2dbf0SJosef Bacik 	test_msg("Running qgroup tests\n");
516b9ef22deSFeifei Xu 	ret = test_no_shared_qgroup(root, sectorsize, nodesize);
517faa2dbf0SJosef Bacik 	if (ret)
518faa2dbf0SJosef Bacik 		goto out;
519b9ef22deSFeifei Xu 	ret = test_multiple_refs(root, sectorsize, nodesize);
520faa2dbf0SJosef Bacik out:
521faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
522faa2dbf0SJosef Bacik 	return ret;
523faa2dbf0SJosef Bacik }
524