xref: /openbmc/linux/fs/btrfs/tests/qgroup-tests.c (revision 442244c9)
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 
19faa2dbf0SJosef Bacik #include "btrfs-tests.h"
20faa2dbf0SJosef Bacik #include "../ctree.h"
21faa2dbf0SJosef Bacik #include "../transaction.h"
22faa2dbf0SJosef Bacik #include "../disk-io.h"
23faa2dbf0SJosef Bacik #include "../qgroup.h"
24442244c9SQu Wenruo #include "../backref.h"
25faa2dbf0SJosef Bacik 
26faa2dbf0SJosef Bacik static void init_dummy_trans(struct btrfs_trans_handle *trans)
27faa2dbf0SJosef Bacik {
28faa2dbf0SJosef Bacik 	memset(trans, 0, sizeof(*trans));
29faa2dbf0SJosef Bacik 	trans->transid = 1;
30faa2dbf0SJosef Bacik 	INIT_LIST_HEAD(&trans->qgroup_ref_list);
31faa2dbf0SJosef Bacik 	trans->type = __TRANS_DUMMY;
32faa2dbf0SJosef Bacik }
33faa2dbf0SJosef Bacik 
34faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
35faa2dbf0SJosef Bacik 				  u64 num_bytes, u64 parent, u64 root_objectid)
36faa2dbf0SJosef Bacik {
37faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
38faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
39faa2dbf0SJosef Bacik 	struct btrfs_extent_inline_ref *iref;
40faa2dbf0SJosef Bacik 	struct btrfs_tree_block_info *block_info;
41faa2dbf0SJosef Bacik 	struct btrfs_path *path;
42faa2dbf0SJosef Bacik 	struct extent_buffer *leaf;
43faa2dbf0SJosef Bacik 	struct btrfs_key ins;
44faa2dbf0SJosef Bacik 	u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
45faa2dbf0SJosef Bacik 	int ret;
46faa2dbf0SJosef Bacik 
47faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
48faa2dbf0SJosef Bacik 
49faa2dbf0SJosef Bacik 	ins.objectid = bytenr;
50faa2dbf0SJosef Bacik 	ins.type = BTRFS_EXTENT_ITEM_KEY;
51faa2dbf0SJosef Bacik 	ins.offset = num_bytes;
52faa2dbf0SJosef Bacik 
53faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
54faa2dbf0SJosef Bacik 	if (!path) {
55faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
56faa2dbf0SJosef Bacik 		return -ENOMEM;
57faa2dbf0SJosef Bacik 	}
58faa2dbf0SJosef Bacik 
59faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
60faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
61faa2dbf0SJosef Bacik 	if (ret) {
62faa2dbf0SJosef Bacik 		test_msg("Couldn't insert ref %d\n", ret);
63faa2dbf0SJosef Bacik 		btrfs_free_path(path);
64faa2dbf0SJosef Bacik 		return ret;
65faa2dbf0SJosef Bacik 	}
66faa2dbf0SJosef Bacik 
67faa2dbf0SJosef Bacik 	leaf = path->nodes[0];
68faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
69faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(leaf, item, 1);
70faa2dbf0SJosef Bacik 	btrfs_set_extent_generation(leaf, item, 1);
71faa2dbf0SJosef Bacik 	btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
72faa2dbf0SJosef Bacik 	block_info = (struct btrfs_tree_block_info *)(item + 1);
73faa2dbf0SJosef Bacik 	btrfs_set_tree_block_level(leaf, block_info, 1);
74faa2dbf0SJosef Bacik 	iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
75faa2dbf0SJosef Bacik 	if (parent > 0) {
76faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref,
77faa2dbf0SJosef Bacik 						 BTRFS_SHARED_BLOCK_REF_KEY);
78faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
79faa2dbf0SJosef Bacik 	} else {
80faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
81faa2dbf0SJosef Bacik 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
82faa2dbf0SJosef Bacik 	}
83faa2dbf0SJosef Bacik 	btrfs_free_path(path);
84faa2dbf0SJosef Bacik 	return 0;
85faa2dbf0SJosef Bacik }
86faa2dbf0SJosef Bacik 
87faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
88faa2dbf0SJosef Bacik 			u64 parent, u64 root_objectid)
89faa2dbf0SJosef Bacik {
90faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
91faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
92faa2dbf0SJosef Bacik 	struct btrfs_path *path;
93faa2dbf0SJosef Bacik 	struct btrfs_key key;
94faa2dbf0SJosef Bacik 	u64 refs;
95faa2dbf0SJosef Bacik 	int ret;
96faa2dbf0SJosef Bacik 
97faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
98faa2dbf0SJosef Bacik 
99faa2dbf0SJosef Bacik 	key.objectid = bytenr;
100faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
101faa2dbf0SJosef Bacik 	key.offset = num_bytes;
102faa2dbf0SJosef Bacik 
103faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
104faa2dbf0SJosef Bacik 	if (!path) {
105faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
106faa2dbf0SJosef Bacik 		return -ENOMEM;
107faa2dbf0SJosef Bacik 	}
108faa2dbf0SJosef Bacik 
109faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
110faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
111faa2dbf0SJosef Bacik 	if (ret) {
112faa2dbf0SJosef Bacik 		test_msg("Couldn't find extent ref\n");
113faa2dbf0SJosef Bacik 		btrfs_free_path(path);
114faa2dbf0SJosef Bacik 		return ret;
115faa2dbf0SJosef Bacik 	}
116faa2dbf0SJosef Bacik 
117faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
118faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
119faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
120faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs + 1);
121faa2dbf0SJosef Bacik 	btrfs_release_path(path);
122faa2dbf0SJosef Bacik 
123faa2dbf0SJosef Bacik 	key.objectid = bytenr;
124faa2dbf0SJosef Bacik 	if (parent) {
125faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
126faa2dbf0SJosef Bacik 		key.offset = parent;
127faa2dbf0SJosef Bacik 	} else {
128faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
129faa2dbf0SJosef Bacik 		key.offset = root_objectid;
130faa2dbf0SJosef Bacik 	}
131faa2dbf0SJosef Bacik 
132faa2dbf0SJosef Bacik 	ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
133faa2dbf0SJosef Bacik 	if (ret)
134faa2dbf0SJosef Bacik 		test_msg("Failed to insert backref\n");
135faa2dbf0SJosef Bacik 	btrfs_free_path(path);
136faa2dbf0SJosef Bacik 	return ret;
137faa2dbf0SJosef Bacik }
138faa2dbf0SJosef Bacik 
139faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
140faa2dbf0SJosef Bacik 			      u64 num_bytes)
141faa2dbf0SJosef Bacik {
142faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
143faa2dbf0SJosef Bacik 	struct btrfs_key key;
144faa2dbf0SJosef Bacik 	struct btrfs_path *path;
145faa2dbf0SJosef Bacik 	int ret;
146faa2dbf0SJosef Bacik 
147faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
148faa2dbf0SJosef Bacik 
149faa2dbf0SJosef Bacik 	key.objectid = bytenr;
150faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
151faa2dbf0SJosef Bacik 	key.offset = num_bytes;
152faa2dbf0SJosef Bacik 
153faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
154faa2dbf0SJosef Bacik 	if (!path) {
155faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
156faa2dbf0SJosef Bacik 		return -ENOMEM;
157faa2dbf0SJosef Bacik 	}
158faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
159faa2dbf0SJosef Bacik 
160faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
161faa2dbf0SJosef Bacik 	if (ret) {
162faa2dbf0SJosef Bacik 		test_msg("Didn't find our key %d\n", ret);
163faa2dbf0SJosef Bacik 		btrfs_free_path(path);
164faa2dbf0SJosef Bacik 		return ret;
165faa2dbf0SJosef Bacik 	}
166faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
167faa2dbf0SJosef Bacik 	btrfs_free_path(path);
168faa2dbf0SJosef Bacik 	return 0;
169faa2dbf0SJosef Bacik }
170faa2dbf0SJosef Bacik 
171faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
172faa2dbf0SJosef Bacik 			     u64 num_bytes, u64 parent, u64 root_objectid)
173faa2dbf0SJosef Bacik {
174faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
175faa2dbf0SJosef Bacik 	struct btrfs_extent_item *item;
176faa2dbf0SJosef Bacik 	struct btrfs_path *path;
177faa2dbf0SJosef Bacik 	struct btrfs_key key;
178faa2dbf0SJosef Bacik 	u64 refs;
179faa2dbf0SJosef Bacik 	int ret;
180faa2dbf0SJosef Bacik 
181faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
182faa2dbf0SJosef Bacik 
183faa2dbf0SJosef Bacik 	key.objectid = bytenr;
184faa2dbf0SJosef Bacik 	key.type = BTRFS_EXTENT_ITEM_KEY;
185faa2dbf0SJosef Bacik 	key.offset = num_bytes;
186faa2dbf0SJosef Bacik 
187faa2dbf0SJosef Bacik 	path = btrfs_alloc_path();
188faa2dbf0SJosef Bacik 	if (!path) {
189faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate path\n");
190faa2dbf0SJosef Bacik 		return -ENOMEM;
191faa2dbf0SJosef Bacik 	}
192faa2dbf0SJosef Bacik 
193faa2dbf0SJosef Bacik 	path->leave_spinning = 1;
194faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
195faa2dbf0SJosef Bacik 	if (ret) {
196faa2dbf0SJosef Bacik 		test_msg("Couldn't find extent ref\n");
197faa2dbf0SJosef Bacik 		btrfs_free_path(path);
198faa2dbf0SJosef Bacik 		return ret;
199faa2dbf0SJosef Bacik 	}
200faa2dbf0SJosef Bacik 
201faa2dbf0SJosef Bacik 	item = btrfs_item_ptr(path->nodes[0], path->slots[0],
202faa2dbf0SJosef Bacik 			      struct btrfs_extent_item);
203faa2dbf0SJosef Bacik 	refs = btrfs_extent_refs(path->nodes[0], item);
204faa2dbf0SJosef Bacik 	btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
205faa2dbf0SJosef Bacik 	btrfs_release_path(path);
206faa2dbf0SJosef Bacik 
207faa2dbf0SJosef Bacik 	key.objectid = bytenr;
208faa2dbf0SJosef Bacik 	if (parent) {
209faa2dbf0SJosef Bacik 		key.type = BTRFS_SHARED_BLOCK_REF_KEY;
210faa2dbf0SJosef Bacik 		key.offset = parent;
211faa2dbf0SJosef Bacik 	} else {
212faa2dbf0SJosef Bacik 		key.type = BTRFS_TREE_BLOCK_REF_KEY;
213faa2dbf0SJosef Bacik 		key.offset = root_objectid;
214faa2dbf0SJosef Bacik 	}
215faa2dbf0SJosef Bacik 
216faa2dbf0SJosef Bacik 	ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
217faa2dbf0SJosef Bacik 	if (ret) {
218faa2dbf0SJosef Bacik 		test_msg("Couldn't find backref %d\n", ret);
219faa2dbf0SJosef Bacik 		btrfs_free_path(path);
220faa2dbf0SJosef Bacik 		return ret;
221faa2dbf0SJosef Bacik 	}
222faa2dbf0SJosef Bacik 	btrfs_del_item(&trans, root, path);
223faa2dbf0SJosef Bacik 	btrfs_free_path(path);
224faa2dbf0SJosef Bacik 	return ret;
225faa2dbf0SJosef Bacik }
226faa2dbf0SJosef Bacik 
227faa2dbf0SJosef Bacik static int test_no_shared_qgroup(struct btrfs_root *root)
228faa2dbf0SJosef Bacik {
229faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
230faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
231442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
232442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
233faa2dbf0SJosef Bacik 	int ret;
234faa2dbf0SJosef Bacik 
235faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
236faa2dbf0SJosef Bacik 
237faa2dbf0SJosef Bacik 	test_msg("Qgroup basic add\n");
2384087cf24SDongsheng Yang 	ret = btrfs_create_qgroup(NULL, fs_info, 5);
239faa2dbf0SJosef Bacik 	if (ret) {
240faa2dbf0SJosef Bacik 		test_msg("Couldn't create a qgroup %d\n", ret);
241faa2dbf0SJosef Bacik 		return ret;
242faa2dbf0SJosef Bacik 	}
243faa2dbf0SJosef Bacik 
244442244c9SQu Wenruo 	/*
245442244c9SQu Wenruo 	 * Since the test trans doesn't havee the complicated delayed refs,
246442244c9SQu Wenruo 	 * we can only call btrfs_qgroup_account_extent() directly to test
247442244c9SQu Wenruo 	 * quota.
248442244c9SQu Wenruo 	 */
249442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
250faa2dbf0SJosef Bacik 	if (ret) {
251442244c9SQu Wenruo 		ulist_free(old_roots);
252442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
253faa2dbf0SJosef Bacik 		return ret;
254faa2dbf0SJosef Bacik 	}
255faa2dbf0SJosef Bacik 
256faa2dbf0SJosef Bacik 	ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5);
257faa2dbf0SJosef Bacik 	if (ret)
258faa2dbf0SJosef Bacik 		return ret;
259faa2dbf0SJosef Bacik 
260442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
261faa2dbf0SJosef Bacik 	if (ret) {
262442244c9SQu Wenruo 		ulist_free(old_roots);
263442244c9SQu Wenruo 		ulist_free(new_roots);
264442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
265442244c9SQu Wenruo 		return ret;
266442244c9SQu Wenruo 	}
267442244c9SQu Wenruo 
268442244c9SQu Wenruo 	ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
269442244c9SQu Wenruo 					  old_roots, new_roots);
270442244c9SQu Wenruo 	if (ret) {
271442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
272faa2dbf0SJosef Bacik 		return ret;
273faa2dbf0SJosef Bacik 	}
274faa2dbf0SJosef Bacik 
275faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
276faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
277faa2dbf0SJosef Bacik 		return -EINVAL;
278faa2dbf0SJosef Bacik 	}
279442244c9SQu Wenruo 	old_roots = NULL;
280442244c9SQu Wenruo 	new_roots = NULL;
281442244c9SQu Wenruo 
282442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
283442244c9SQu Wenruo 	if (ret) {
284442244c9SQu Wenruo 		ulist_free(old_roots);
285442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
286442244c9SQu Wenruo 		return ret;
287442244c9SQu Wenruo 	}
288faa2dbf0SJosef Bacik 
289faa2dbf0SJosef Bacik 	ret = remove_extent_item(root, 4096, 4096);
290faa2dbf0SJosef Bacik 	if (ret)
291faa2dbf0SJosef Bacik 		return -EINVAL;
292faa2dbf0SJosef Bacik 
293442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
294faa2dbf0SJosef Bacik 	if (ret) {
295442244c9SQu Wenruo 		ulist_free(old_roots);
296442244c9SQu Wenruo 		ulist_free(new_roots);
297442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
298442244c9SQu Wenruo 		return ret;
299faa2dbf0SJosef Bacik 	}
300faa2dbf0SJosef Bacik 
301442244c9SQu Wenruo 	ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
302442244c9SQu Wenruo 					  old_roots, new_roots);
303faa2dbf0SJosef Bacik 	if (ret) {
304442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
305faa2dbf0SJosef Bacik 		return -EINVAL;
306faa2dbf0SJosef Bacik 	}
307faa2dbf0SJosef Bacik 
308faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) {
309faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
310faa2dbf0SJosef Bacik 		return -EINVAL;
311faa2dbf0SJosef Bacik 	}
312faa2dbf0SJosef Bacik 
313faa2dbf0SJosef Bacik 	return 0;
314faa2dbf0SJosef Bacik }
315faa2dbf0SJosef Bacik 
316faa2dbf0SJosef Bacik /*
317faa2dbf0SJosef Bacik  * Add a ref for two different roots to make sure the shared value comes out
318faa2dbf0SJosef Bacik  * right, also remove one of the roots and make sure the exclusive count is
319faa2dbf0SJosef Bacik  * adjusted properly.
320faa2dbf0SJosef Bacik  */
321faa2dbf0SJosef Bacik static int test_multiple_refs(struct btrfs_root *root)
322faa2dbf0SJosef Bacik {
323faa2dbf0SJosef Bacik 	struct btrfs_trans_handle trans;
324faa2dbf0SJosef Bacik 	struct btrfs_fs_info *fs_info = root->fs_info;
325442244c9SQu Wenruo 	struct ulist *old_roots = NULL;
326442244c9SQu Wenruo 	struct ulist *new_roots = NULL;
327faa2dbf0SJosef Bacik 	int ret;
328faa2dbf0SJosef Bacik 
329faa2dbf0SJosef Bacik 	init_dummy_trans(&trans);
330faa2dbf0SJosef Bacik 
331faa2dbf0SJosef Bacik 	test_msg("Qgroup multiple refs test\n");
332faa2dbf0SJosef Bacik 
333faa2dbf0SJosef Bacik 	/* We have 5 created already from the previous test */
3344087cf24SDongsheng Yang 	ret = btrfs_create_qgroup(NULL, fs_info, 256);
335faa2dbf0SJosef Bacik 	if (ret) {
336faa2dbf0SJosef Bacik 		test_msg("Couldn't create a qgroup %d\n", ret);
337faa2dbf0SJosef Bacik 		return ret;
338faa2dbf0SJosef Bacik 	}
339faa2dbf0SJosef Bacik 
340442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 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 
347faa2dbf0SJosef Bacik 	ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5);
348faa2dbf0SJosef Bacik 	if (ret)
349faa2dbf0SJosef Bacik 		return ret;
350faa2dbf0SJosef Bacik 
351442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
352faa2dbf0SJosef Bacik 	if (ret) {
353442244c9SQu Wenruo 		ulist_free(old_roots);
354442244c9SQu Wenruo 		ulist_free(new_roots);
355442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
356faa2dbf0SJosef Bacik 		return ret;
357faa2dbf0SJosef Bacik 	}
358faa2dbf0SJosef Bacik 
359442244c9SQu Wenruo 	ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
360442244c9SQu Wenruo 					  old_roots, new_roots);
361faa2dbf0SJosef Bacik 	if (ret) {
362442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
363faa2dbf0SJosef Bacik 		return ret;
364faa2dbf0SJosef Bacik 	}
365faa2dbf0SJosef Bacik 
366faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
367faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
368faa2dbf0SJosef Bacik 		return -EINVAL;
369faa2dbf0SJosef Bacik 	}
370faa2dbf0SJosef Bacik 
371442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
372442244c9SQu Wenruo 	if (ret) {
373442244c9SQu Wenruo 		ulist_free(old_roots);
374442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
375442244c9SQu Wenruo 		return ret;
376442244c9SQu Wenruo 	}
377442244c9SQu Wenruo 
378faa2dbf0SJosef Bacik 	ret = add_tree_ref(root, 4096, 4096, 0, 256);
379faa2dbf0SJosef Bacik 	if (ret)
380faa2dbf0SJosef Bacik 		return ret;
381faa2dbf0SJosef Bacik 
382442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
383faa2dbf0SJosef Bacik 	if (ret) {
384442244c9SQu Wenruo 		ulist_free(old_roots);
385442244c9SQu Wenruo 		ulist_free(new_roots);
386442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
387faa2dbf0SJosef Bacik 		return ret;
388faa2dbf0SJosef Bacik 	}
389faa2dbf0SJosef Bacik 
390442244c9SQu Wenruo 	ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
391442244c9SQu Wenruo 					  old_roots, new_roots);
392faa2dbf0SJosef Bacik 	if (ret) {
393442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
394faa2dbf0SJosef Bacik 		return ret;
395faa2dbf0SJosef Bacik 	}
396faa2dbf0SJosef Bacik 
397faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 0)) {
398faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
399faa2dbf0SJosef Bacik 		return -EINVAL;
400faa2dbf0SJosef Bacik 	}
401faa2dbf0SJosef Bacik 
402faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 256, 4096, 0)) {
403faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
404faa2dbf0SJosef Bacik 		return -EINVAL;
405faa2dbf0SJosef Bacik 	}
406faa2dbf0SJosef Bacik 
407442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
408442244c9SQu Wenruo 	if (ret) {
409442244c9SQu Wenruo 		ulist_free(old_roots);
410442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
411442244c9SQu Wenruo 		return ret;
412442244c9SQu Wenruo 	}
413442244c9SQu Wenruo 
414faa2dbf0SJosef Bacik 	ret = remove_extent_ref(root, 4096, 4096, 0, 256);
415faa2dbf0SJosef Bacik 	if (ret)
416faa2dbf0SJosef Bacik 		return ret;
417faa2dbf0SJosef Bacik 
418442244c9SQu Wenruo 	ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
419faa2dbf0SJosef Bacik 	if (ret) {
420442244c9SQu Wenruo 		ulist_free(old_roots);
421442244c9SQu Wenruo 		ulist_free(new_roots);
422442244c9SQu Wenruo 		test_msg("Couldn't find old roots: %d\n", ret);
423faa2dbf0SJosef Bacik 		return ret;
424faa2dbf0SJosef Bacik 	}
425faa2dbf0SJosef Bacik 
426442244c9SQu Wenruo 	ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
427442244c9SQu Wenruo 					  old_roots, new_roots);
428faa2dbf0SJosef Bacik 	if (ret) {
429442244c9SQu Wenruo 		test_msg("Couldn't account space for a qgroup %d\n", ret);
430faa2dbf0SJosef Bacik 		return ret;
431faa2dbf0SJosef Bacik 	}
432faa2dbf0SJosef Bacik 
433faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) {
434faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
435faa2dbf0SJosef Bacik 		return -EINVAL;
436faa2dbf0SJosef Bacik 	}
437faa2dbf0SJosef Bacik 
438faa2dbf0SJosef Bacik 	if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
439faa2dbf0SJosef Bacik 		test_msg("Qgroup counts didn't match expected values\n");
440faa2dbf0SJosef Bacik 		return -EINVAL;
441faa2dbf0SJosef Bacik 	}
442faa2dbf0SJosef Bacik 
443faa2dbf0SJosef Bacik 	return 0;
444faa2dbf0SJosef Bacik }
445faa2dbf0SJosef Bacik 
446faa2dbf0SJosef Bacik int btrfs_test_qgroups(void)
447faa2dbf0SJosef Bacik {
448faa2dbf0SJosef Bacik 	struct btrfs_root *root;
449faa2dbf0SJosef Bacik 	struct btrfs_root *tmp_root;
450faa2dbf0SJosef Bacik 	int ret = 0;
451faa2dbf0SJosef Bacik 
452faa2dbf0SJosef Bacik 	root = btrfs_alloc_dummy_root();
453faa2dbf0SJosef Bacik 	if (IS_ERR(root)) {
454faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate root\n");
455faa2dbf0SJosef Bacik 		return PTR_ERR(root);
456faa2dbf0SJosef Bacik 	}
457faa2dbf0SJosef Bacik 
458faa2dbf0SJosef Bacik 	root->fs_info = btrfs_alloc_dummy_fs_info();
459faa2dbf0SJosef Bacik 	if (!root->fs_info) {
460faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate dummy fs info\n");
461faa2dbf0SJosef Bacik 		ret = -ENOMEM;
462faa2dbf0SJosef Bacik 		goto out;
463faa2dbf0SJosef Bacik 	}
4643f556f78SDavid Sterba 	/* We are using this root as our extent root */
4653f556f78SDavid Sterba 	root->fs_info->extent_root = 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;
4733f556f78SDavid Sterba 	root->fs_info->quota_enabled = 1;
474faa2dbf0SJosef Bacik 
475faa2dbf0SJosef Bacik 	/*
476faa2dbf0SJosef Bacik 	 * Can't use bytenr 0, some things freak out
477faa2dbf0SJosef Bacik 	 * *cough*backref walking code*cough*
478faa2dbf0SJosef Bacik 	 */
479ce3e6984SDavid Sterba 	root->node = alloc_test_extent_buffer(root->fs_info, 4096);
480faa2dbf0SJosef Bacik 	if (!root->node) {
481faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate dummy buffer\n");
482faa2dbf0SJosef Bacik 		ret = -ENOMEM;
483faa2dbf0SJosef Bacik 		goto out;
484faa2dbf0SJosef Bacik 	}
485b050f9f6SFilipe Manana 	btrfs_set_header_level(root->node, 0);
486b050f9f6SFilipe Manana 	btrfs_set_header_nritems(root->node, 0);
487faa2dbf0SJosef Bacik 	root->alloc_bytenr += 8192;
488faa2dbf0SJosef Bacik 
489faa2dbf0SJosef Bacik 	tmp_root = btrfs_alloc_dummy_root();
490faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
491faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
492faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
493faa2dbf0SJosef Bacik 		goto out;
494faa2dbf0SJosef Bacik 	}
495faa2dbf0SJosef Bacik 
496faa2dbf0SJosef Bacik 	tmp_root->root_key.objectid = 5;
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) {
500faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
501faa2dbf0SJosef Bacik 		goto out;
502faa2dbf0SJosef Bacik 	}
503faa2dbf0SJosef Bacik 
504faa2dbf0SJosef Bacik 	tmp_root = btrfs_alloc_dummy_root();
505faa2dbf0SJosef Bacik 	if (IS_ERR(tmp_root)) {
506faa2dbf0SJosef Bacik 		test_msg("Couldn't allocate a fs root\n");
507faa2dbf0SJosef Bacik 		ret = PTR_ERR(tmp_root);
508faa2dbf0SJosef Bacik 		goto out;
509faa2dbf0SJosef Bacik 	}
510faa2dbf0SJosef Bacik 
511faa2dbf0SJosef Bacik 	tmp_root->root_key.objectid = 256;
512faa2dbf0SJosef Bacik 	ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
513faa2dbf0SJosef Bacik 	if (ret) {
514faa2dbf0SJosef Bacik 		test_msg("Couldn't insert fs root %d\n", ret);
515faa2dbf0SJosef Bacik 		goto out;
516faa2dbf0SJosef Bacik 	}
517faa2dbf0SJosef Bacik 
518faa2dbf0SJosef Bacik 	test_msg("Running qgroup tests\n");
519faa2dbf0SJosef Bacik 	ret = test_no_shared_qgroup(root);
520faa2dbf0SJosef Bacik 	if (ret)
521faa2dbf0SJosef Bacik 		goto out;
522faa2dbf0SJosef Bacik 	ret = test_multiple_refs(root);
523faa2dbf0SJosef Bacik out:
524faa2dbf0SJosef Bacik 	btrfs_free_dummy_root(root);
525faa2dbf0SJosef Bacik 	return ret;
526faa2dbf0SJosef Bacik }
527