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