1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 2faa2dbf0SJosef Bacik /* 3faa2dbf0SJosef Bacik * Copyright (C) 2013 Facebook. All rights reserved. 4faa2dbf0SJosef Bacik */ 5faa2dbf0SJosef Bacik 6b9ef22deSFeifei Xu #include <linux/types.h> 7faa2dbf0SJosef Bacik #include "btrfs-tests.h" 8faa2dbf0SJosef Bacik #include "../ctree.h" 9faa2dbf0SJosef Bacik #include "../transaction.h" 10faa2dbf0SJosef Bacik #include "../disk-io.h" 11faa2dbf0SJosef Bacik #include "../qgroup.h" 12442244c9SQu Wenruo #include "../backref.h" 13faa2dbf0SJosef Bacik 14faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr, 15faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 16faa2dbf0SJosef Bacik { 17faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 18faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 19faa2dbf0SJosef Bacik struct btrfs_extent_inline_ref *iref; 20faa2dbf0SJosef Bacik struct btrfs_tree_block_info *block_info; 21faa2dbf0SJosef Bacik struct btrfs_path *path; 22faa2dbf0SJosef Bacik struct extent_buffer *leaf; 23faa2dbf0SJosef Bacik struct btrfs_key ins; 24faa2dbf0SJosef Bacik u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info); 25faa2dbf0SJosef Bacik int ret; 26faa2dbf0SJosef Bacik 27483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 28faa2dbf0SJosef Bacik 29faa2dbf0SJosef Bacik ins.objectid = bytenr; 30faa2dbf0SJosef Bacik ins.type = BTRFS_EXTENT_ITEM_KEY; 31faa2dbf0SJosef Bacik ins.offset = num_bytes; 32faa2dbf0SJosef Bacik 33faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 34faa2dbf0SJosef Bacik if (!path) { 35770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 36faa2dbf0SJosef Bacik return -ENOMEM; 37faa2dbf0SJosef Bacik } 38faa2dbf0SJosef Bacik 39faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &ins, size); 40faa2dbf0SJosef Bacik if (ret) { 413c7251f2SDavid Sterba test_err("couldn't insert ref %d", ret); 42faa2dbf0SJosef Bacik btrfs_free_path(path); 43faa2dbf0SJosef Bacik return ret; 44faa2dbf0SJosef Bacik } 45faa2dbf0SJosef Bacik 46faa2dbf0SJosef Bacik leaf = path->nodes[0]; 47faa2dbf0SJosef Bacik item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 48faa2dbf0SJosef Bacik btrfs_set_extent_refs(leaf, item, 1); 49faa2dbf0SJosef Bacik btrfs_set_extent_generation(leaf, item, 1); 50faa2dbf0SJosef Bacik btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); 51faa2dbf0SJosef Bacik block_info = (struct btrfs_tree_block_info *)(item + 1); 523c0efdf0SQu Wenruo btrfs_set_tree_block_level(leaf, block_info, 0); 53faa2dbf0SJosef Bacik iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 54faa2dbf0SJosef Bacik if (parent > 0) { 55faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, 56faa2dbf0SJosef Bacik BTRFS_SHARED_BLOCK_REF_KEY); 57faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 58faa2dbf0SJosef Bacik } else { 59faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY); 60faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 61faa2dbf0SJosef Bacik } 62faa2dbf0SJosef Bacik btrfs_free_path(path); 63faa2dbf0SJosef Bacik return 0; 64faa2dbf0SJosef Bacik } 65faa2dbf0SJosef Bacik 66faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes, 67faa2dbf0SJosef Bacik u64 parent, u64 root_objectid) 68faa2dbf0SJosef Bacik { 69faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 70faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 71faa2dbf0SJosef Bacik struct btrfs_path *path; 72faa2dbf0SJosef Bacik struct btrfs_key key; 73faa2dbf0SJosef Bacik u64 refs; 74faa2dbf0SJosef Bacik int ret; 75faa2dbf0SJosef Bacik 76483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 77faa2dbf0SJosef Bacik 78faa2dbf0SJosef Bacik key.objectid = bytenr; 79faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 80faa2dbf0SJosef Bacik key.offset = num_bytes; 81faa2dbf0SJosef Bacik 82faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 83faa2dbf0SJosef Bacik if (!path) { 84770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 85faa2dbf0SJosef Bacik return -ENOMEM; 86faa2dbf0SJosef Bacik } 87faa2dbf0SJosef Bacik 88faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 89faa2dbf0SJosef Bacik if (ret) { 903c7251f2SDavid Sterba test_err("couldn't find extent ref"); 91faa2dbf0SJosef Bacik btrfs_free_path(path); 92faa2dbf0SJosef Bacik return ret; 93faa2dbf0SJosef Bacik } 94faa2dbf0SJosef Bacik 95faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 96faa2dbf0SJosef Bacik struct btrfs_extent_item); 97faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 98faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs + 1); 99faa2dbf0SJosef Bacik btrfs_release_path(path); 100faa2dbf0SJosef Bacik 101faa2dbf0SJosef Bacik key.objectid = bytenr; 102faa2dbf0SJosef Bacik if (parent) { 103faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 104faa2dbf0SJosef Bacik key.offset = parent; 105faa2dbf0SJosef Bacik } else { 106faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 107faa2dbf0SJosef Bacik key.offset = root_objectid; 108faa2dbf0SJosef Bacik } 109faa2dbf0SJosef Bacik 110faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &key, 0); 111faa2dbf0SJosef Bacik if (ret) 1123c7251f2SDavid Sterba test_err("failed to insert backref"); 113faa2dbf0SJosef Bacik btrfs_free_path(path); 114faa2dbf0SJosef Bacik return ret; 115faa2dbf0SJosef Bacik } 116faa2dbf0SJosef Bacik 117faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr, 118faa2dbf0SJosef Bacik u64 num_bytes) 119faa2dbf0SJosef Bacik { 120faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 121faa2dbf0SJosef Bacik struct btrfs_key key; 122faa2dbf0SJosef Bacik struct btrfs_path *path; 123faa2dbf0SJosef Bacik int ret; 124faa2dbf0SJosef Bacik 125483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 126faa2dbf0SJosef Bacik 127faa2dbf0SJosef Bacik key.objectid = bytenr; 128faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 129faa2dbf0SJosef Bacik key.offset = num_bytes; 130faa2dbf0SJosef Bacik 131faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 132faa2dbf0SJosef Bacik if (!path) { 133770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 134faa2dbf0SJosef Bacik return -ENOMEM; 135faa2dbf0SJosef Bacik } 136faa2dbf0SJosef Bacik 137faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 138faa2dbf0SJosef Bacik if (ret) { 1393c7251f2SDavid Sterba test_err("didn't find our key %d", ret); 140faa2dbf0SJosef Bacik btrfs_free_path(path); 141faa2dbf0SJosef Bacik return ret; 142faa2dbf0SJosef Bacik } 143faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 144faa2dbf0SJosef Bacik btrfs_free_path(path); 145faa2dbf0SJosef Bacik return 0; 146faa2dbf0SJosef Bacik } 147faa2dbf0SJosef Bacik 148faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr, 149faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 150faa2dbf0SJosef Bacik { 151faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 152faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 153faa2dbf0SJosef Bacik struct btrfs_path *path; 154faa2dbf0SJosef Bacik struct btrfs_key key; 155faa2dbf0SJosef Bacik u64 refs; 156faa2dbf0SJosef Bacik int ret; 157faa2dbf0SJosef Bacik 158483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 159faa2dbf0SJosef Bacik 160faa2dbf0SJosef Bacik key.objectid = bytenr; 161faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 162faa2dbf0SJosef Bacik key.offset = num_bytes; 163faa2dbf0SJosef Bacik 164faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 165faa2dbf0SJosef Bacik if (!path) { 166770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 167faa2dbf0SJosef Bacik return -ENOMEM; 168faa2dbf0SJosef Bacik } 169faa2dbf0SJosef Bacik 170faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 171faa2dbf0SJosef Bacik if (ret) { 1723c7251f2SDavid Sterba test_err("couldn't find extent ref"); 173faa2dbf0SJosef Bacik btrfs_free_path(path); 174faa2dbf0SJosef Bacik return ret; 175faa2dbf0SJosef Bacik } 176faa2dbf0SJosef Bacik 177faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 178faa2dbf0SJosef Bacik struct btrfs_extent_item); 179faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 180faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs - 1); 181faa2dbf0SJosef Bacik btrfs_release_path(path); 182faa2dbf0SJosef Bacik 183faa2dbf0SJosef Bacik key.objectid = bytenr; 184faa2dbf0SJosef Bacik if (parent) { 185faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 186faa2dbf0SJosef Bacik key.offset = parent; 187faa2dbf0SJosef Bacik } else { 188faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 189faa2dbf0SJosef Bacik key.offset = root_objectid; 190faa2dbf0SJosef Bacik } 191faa2dbf0SJosef Bacik 192faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 193faa2dbf0SJosef Bacik if (ret) { 1943c7251f2SDavid Sterba test_err("couldn't find backref %d", ret); 195faa2dbf0SJosef Bacik btrfs_free_path(path); 196faa2dbf0SJosef Bacik return ret; 197faa2dbf0SJosef Bacik } 198faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 199faa2dbf0SJosef Bacik btrfs_free_path(path); 200faa2dbf0SJosef Bacik return ret; 201faa2dbf0SJosef Bacik } 202faa2dbf0SJosef Bacik 203b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root, 204b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 205faa2dbf0SJosef Bacik { 206faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 207faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 208442244c9SQu Wenruo struct ulist *old_roots = NULL; 209442244c9SQu Wenruo struct ulist *new_roots = NULL; 210faa2dbf0SJosef Bacik int ret; 211faa2dbf0SJosef Bacik 212483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, fs_info); 213faa2dbf0SJosef Bacik 214e4fa7469SDavid Sterba test_msg("running qgroup add/remove tests"); 21549a05ecdSLu Fengqi ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID); 216faa2dbf0SJosef Bacik if (ret) { 2173c7251f2SDavid Sterba test_err("couldn't create a qgroup %d", ret); 218faa2dbf0SJosef Bacik return ret; 219faa2dbf0SJosef Bacik } 220faa2dbf0SJosef Bacik 221442244c9SQu Wenruo /* 22201327610SNicholas D Steeves * Since the test trans doesn't have the complicated delayed refs, 223442244c9SQu Wenruo * we can only call btrfs_qgroup_account_extent() directly to test 224442244c9SQu Wenruo * quota. 225442244c9SQu Wenruo */ 226c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 227faa2dbf0SJosef Bacik if (ret) { 228442244c9SQu Wenruo ulist_free(old_roots); 2293c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 230faa2dbf0SJosef Bacik return ret; 231faa2dbf0SJosef Bacik } 232faa2dbf0SJosef Bacik 233ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 234ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 235*d37de92bSFilipe Manana if (ret) { 236*d37de92bSFilipe Manana ulist_free(old_roots); 237faa2dbf0SJosef Bacik return ret; 238*d37de92bSFilipe Manana } 239faa2dbf0SJosef Bacik 240c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 241faa2dbf0SJosef Bacik if (ret) { 242442244c9SQu Wenruo ulist_free(old_roots); 243442244c9SQu Wenruo ulist_free(new_roots); 2443c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 245442244c9SQu Wenruo return ret; 246442244c9SQu Wenruo } 247442244c9SQu Wenruo 2488696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2498696d760SLu Fengqi new_roots); 250442244c9SQu Wenruo if (ret) { 2513c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 252faa2dbf0SJosef Bacik return ret; 253faa2dbf0SJosef Bacik } 254faa2dbf0SJosef Bacik 255ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 256ef9f2db3SFeifei Xu nodesize, nodesize)) { 2573c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 258faa2dbf0SJosef Bacik return -EINVAL; 259faa2dbf0SJosef Bacik } 260442244c9SQu Wenruo old_roots = NULL; 261442244c9SQu Wenruo new_roots = NULL; 262442244c9SQu Wenruo 263c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 264442244c9SQu Wenruo if (ret) { 265442244c9SQu Wenruo ulist_free(old_roots); 2663c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 267442244c9SQu Wenruo return ret; 268442244c9SQu Wenruo } 269faa2dbf0SJosef Bacik 270b9ef22deSFeifei Xu ret = remove_extent_item(root, nodesize, nodesize); 271*d37de92bSFilipe Manana if (ret) { 272*d37de92bSFilipe Manana ulist_free(old_roots); 273faa2dbf0SJosef Bacik return -EINVAL; 274*d37de92bSFilipe Manana } 275faa2dbf0SJosef Bacik 276c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 277faa2dbf0SJosef Bacik if (ret) { 278442244c9SQu Wenruo ulist_free(old_roots); 279442244c9SQu Wenruo ulist_free(new_roots); 2803c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 281442244c9SQu Wenruo return ret; 282faa2dbf0SJosef Bacik } 283faa2dbf0SJosef Bacik 2848696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2858696d760SLu Fengqi new_roots); 286faa2dbf0SJosef Bacik if (ret) { 2873c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 288faa2dbf0SJosef Bacik return -EINVAL; 289faa2dbf0SJosef Bacik } 290faa2dbf0SJosef Bacik 291ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) { 2923c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 293faa2dbf0SJosef Bacik return -EINVAL; 294faa2dbf0SJosef Bacik } 295faa2dbf0SJosef Bacik 296faa2dbf0SJosef Bacik return 0; 297faa2dbf0SJosef Bacik } 298faa2dbf0SJosef Bacik 299faa2dbf0SJosef Bacik /* 300faa2dbf0SJosef Bacik * Add a ref for two different roots to make sure the shared value comes out 301faa2dbf0SJosef Bacik * right, also remove one of the roots and make sure the exclusive count is 302faa2dbf0SJosef Bacik * adjusted properly. 303faa2dbf0SJosef Bacik */ 304b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root, 305b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 306faa2dbf0SJosef Bacik { 307faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 308faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 309442244c9SQu Wenruo struct ulist *old_roots = NULL; 310442244c9SQu Wenruo struct ulist *new_roots = NULL; 311faa2dbf0SJosef Bacik int ret; 312faa2dbf0SJosef Bacik 313483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, fs_info); 314faa2dbf0SJosef Bacik 315e4fa7469SDavid Sterba test_msg("running qgroup multiple refs test"); 316faa2dbf0SJosef Bacik 317ef9f2db3SFeifei Xu /* 318ef9f2db3SFeifei Xu * We have BTRFS_FS_TREE_OBJECTID created already from the 319ef9f2db3SFeifei Xu * previous test. 320ef9f2db3SFeifei Xu */ 32149a05ecdSLu Fengqi ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID); 322faa2dbf0SJosef Bacik if (ret) { 3233c7251f2SDavid Sterba test_err("couldn't create a qgroup %d", ret); 324faa2dbf0SJosef Bacik return ret; 325faa2dbf0SJosef Bacik } 326faa2dbf0SJosef Bacik 327c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 328442244c9SQu Wenruo if (ret) { 329442244c9SQu Wenruo ulist_free(old_roots); 3303c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 331442244c9SQu Wenruo return ret; 332442244c9SQu Wenruo } 333442244c9SQu Wenruo 334ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 335ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 336*d37de92bSFilipe Manana if (ret) { 337*d37de92bSFilipe Manana ulist_free(old_roots); 338faa2dbf0SJosef Bacik return ret; 339*d37de92bSFilipe Manana } 340faa2dbf0SJosef Bacik 341c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 342faa2dbf0SJosef Bacik if (ret) { 343442244c9SQu Wenruo ulist_free(old_roots); 344442244c9SQu Wenruo ulist_free(new_roots); 3453c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 346faa2dbf0SJosef Bacik return ret; 347faa2dbf0SJosef Bacik } 348faa2dbf0SJosef Bacik 3498696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3508696d760SLu Fengqi new_roots); 351faa2dbf0SJosef Bacik if (ret) { 3523c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 353faa2dbf0SJosef Bacik return ret; 354faa2dbf0SJosef Bacik } 355faa2dbf0SJosef Bacik 356ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 357b9ef22deSFeifei Xu nodesize, nodesize)) { 3583c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 359faa2dbf0SJosef Bacik return -EINVAL; 360faa2dbf0SJosef Bacik } 361faa2dbf0SJosef Bacik 362c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 363442244c9SQu Wenruo if (ret) { 364442244c9SQu Wenruo ulist_free(old_roots); 3653c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 366442244c9SQu Wenruo return ret; 367442244c9SQu Wenruo } 368442244c9SQu Wenruo 369ef9f2db3SFeifei Xu ret = add_tree_ref(root, nodesize, nodesize, 0, 370ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 371*d37de92bSFilipe Manana if (ret) { 372*d37de92bSFilipe Manana ulist_free(old_roots); 373faa2dbf0SJosef Bacik return ret; 374*d37de92bSFilipe Manana } 375faa2dbf0SJosef Bacik 376c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 377faa2dbf0SJosef Bacik if (ret) { 378442244c9SQu Wenruo ulist_free(old_roots); 379442244c9SQu Wenruo ulist_free(new_roots); 3803c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 381faa2dbf0SJosef Bacik return ret; 382faa2dbf0SJosef Bacik } 383faa2dbf0SJosef Bacik 3848696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3858696d760SLu Fengqi new_roots); 386faa2dbf0SJosef Bacik if (ret) { 3873c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 388faa2dbf0SJosef Bacik return ret; 389faa2dbf0SJosef Bacik } 390faa2dbf0SJosef Bacik 391ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 392ef9f2db3SFeifei Xu nodesize, 0)) { 3933c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 394faa2dbf0SJosef Bacik return -EINVAL; 395faa2dbf0SJosef Bacik } 396faa2dbf0SJosef Bacik 397ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 398ef9f2db3SFeifei Xu nodesize, 0)) { 3993c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 400faa2dbf0SJosef Bacik return -EINVAL; 401faa2dbf0SJosef Bacik } 402faa2dbf0SJosef Bacik 403c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 404442244c9SQu Wenruo if (ret) { 405442244c9SQu Wenruo ulist_free(old_roots); 4063c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 407442244c9SQu Wenruo return ret; 408442244c9SQu Wenruo } 409442244c9SQu Wenruo 410ef9f2db3SFeifei Xu ret = remove_extent_ref(root, nodesize, nodesize, 0, 411ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 412*d37de92bSFilipe Manana if (ret) { 413*d37de92bSFilipe Manana ulist_free(old_roots); 414faa2dbf0SJosef Bacik return ret; 415*d37de92bSFilipe Manana } 416faa2dbf0SJosef Bacik 417c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 418faa2dbf0SJosef Bacik if (ret) { 419442244c9SQu Wenruo ulist_free(old_roots); 420442244c9SQu Wenruo ulist_free(new_roots); 4213c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 422faa2dbf0SJosef Bacik return ret; 423faa2dbf0SJosef Bacik } 424faa2dbf0SJosef Bacik 4258696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 4268696d760SLu Fengqi new_roots); 427faa2dbf0SJosef Bacik if (ret) { 4283c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 429faa2dbf0SJosef Bacik return ret; 430faa2dbf0SJosef Bacik } 431faa2dbf0SJosef Bacik 432ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 433ef9f2db3SFeifei Xu 0, 0)) { 4343c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 435faa2dbf0SJosef Bacik return -EINVAL; 436faa2dbf0SJosef Bacik } 437faa2dbf0SJosef Bacik 438ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 439ef9f2db3SFeifei Xu nodesize, nodesize)) { 4403c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 441faa2dbf0SJosef Bacik return -EINVAL; 442faa2dbf0SJosef Bacik } 443faa2dbf0SJosef Bacik 444faa2dbf0SJosef Bacik return 0; 445faa2dbf0SJosef Bacik } 446faa2dbf0SJosef Bacik 447b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) 448faa2dbf0SJosef Bacik { 4497c0260eeSJeff Mahoney struct btrfs_fs_info *fs_info = NULL; 450faa2dbf0SJosef Bacik struct btrfs_root *root; 451faa2dbf0SJosef Bacik struct btrfs_root *tmp_root; 452faa2dbf0SJosef Bacik int ret = 0; 453faa2dbf0SJosef Bacik 454da17066cSJeff Mahoney fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 4557c0260eeSJeff Mahoney if (!fs_info) { 45637b2a7bcSDavid Sterba test_std_err(TEST_ALLOC_FS_INFO); 4577c0260eeSJeff Mahoney return -ENOMEM; 458faa2dbf0SJosef Bacik } 459faa2dbf0SJosef Bacik 460da17066cSJeff Mahoney root = btrfs_alloc_dummy_root(fs_info); 4617c0260eeSJeff Mahoney if (IS_ERR(root)) { 46252ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 4637c0260eeSJeff Mahoney ret = PTR_ERR(root); 464faa2dbf0SJosef Bacik goto out; 465faa2dbf0SJosef Bacik } 4667c0260eeSJeff Mahoney 4673f556f78SDavid Sterba /* We are using this root as our extent root */ 468abed4aaaSJosef Bacik root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID; 469abed4aaaSJosef Bacik root->root_key.type = BTRFS_ROOT_ITEM_KEY; 470abed4aaaSJosef Bacik root->root_key.offset = 0; 471abed4aaaSJosef Bacik btrfs_global_root_insert(root); 4723f556f78SDavid Sterba 4733f556f78SDavid Sterba /* 4743f556f78SDavid Sterba * Some of the paths we test assume we have a filled out fs_info, so we 4753f556f78SDavid Sterba * just need to add the root in there so we don't panic. 4763f556f78SDavid Sterba */ 4773f556f78SDavid Sterba root->fs_info->tree_root = root; 4783f556f78SDavid Sterba root->fs_info->quota_root = root; 479afcdd129SJosef Bacik set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); 480faa2dbf0SJosef Bacik 481faa2dbf0SJosef Bacik /* 482faa2dbf0SJosef Bacik * Can't use bytenr 0, some things freak out 483faa2dbf0SJosef Bacik * *cough*backref walking code*cough* 484faa2dbf0SJosef Bacik */ 485da17066cSJeff Mahoney root->node = alloc_test_extent_buffer(root->fs_info, nodesize); 486b6293c82SDan Carpenter if (IS_ERR(root->node)) { 4873c7251f2SDavid Sterba test_err("couldn't allocate dummy buffer"); 488b6293c82SDan Carpenter ret = PTR_ERR(root->node); 489faa2dbf0SJosef Bacik goto out; 490faa2dbf0SJosef Bacik } 491b050f9f6SFilipe Manana btrfs_set_header_level(root->node, 0); 492b050f9f6SFilipe Manana btrfs_set_header_nritems(root->node, 0); 493b9ef22deSFeifei Xu root->alloc_bytenr += 2 * nodesize; 494faa2dbf0SJosef Bacik 495da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 496faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 49752ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 498faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 499faa2dbf0SJosef Bacik goto out; 500faa2dbf0SJosef Bacik } 501faa2dbf0SJosef Bacik 502ef9f2db3SFeifei Xu tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID; 503faa2dbf0SJosef Bacik root->fs_info->fs_root = tmp_root; 504faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 505faa2dbf0SJosef Bacik if (ret) { 5063c7251f2SDavid Sterba test_err("couldn't insert fs root %d", ret); 507faa2dbf0SJosef Bacik goto out; 508faa2dbf0SJosef Bacik } 5094785e24fSJosef Bacik btrfs_put_root(tmp_root); 510faa2dbf0SJosef Bacik 511da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 512faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 51352ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 514faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 515faa2dbf0SJosef Bacik goto out; 516faa2dbf0SJosef Bacik } 517faa2dbf0SJosef Bacik 518ef9f2db3SFeifei Xu tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID; 519faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 520faa2dbf0SJosef Bacik if (ret) { 5213c7251f2SDavid Sterba test_err("couldn't insert fs root %d", ret); 522faa2dbf0SJosef Bacik goto out; 523faa2dbf0SJosef Bacik } 5244785e24fSJosef Bacik btrfs_put_root(tmp_root); 525faa2dbf0SJosef Bacik 526315b76b4SDavid Sterba test_msg("running qgroup tests"); 527b9ef22deSFeifei Xu ret = test_no_shared_qgroup(root, sectorsize, nodesize); 528faa2dbf0SJosef Bacik if (ret) 529faa2dbf0SJosef Bacik goto out; 530b9ef22deSFeifei Xu ret = test_multiple_refs(root, sectorsize, nodesize); 531faa2dbf0SJosef Bacik out: 532faa2dbf0SJosef Bacik btrfs_free_dummy_root(root); 5337c0260eeSJeff Mahoney btrfs_free_dummy_fs_info(fs_info); 534faa2dbf0SJosef Bacik return ret; 535faa2dbf0SJosef Bacik } 536