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" 137966a6b5SJosef Bacik #include "../fs.h" 14*07e81dc9SJosef Bacik #include "../accessors.h" 15faa2dbf0SJosef Bacik 16faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr, 17faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 18faa2dbf0SJosef Bacik { 19faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 20faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 21faa2dbf0SJosef Bacik struct btrfs_extent_inline_ref *iref; 22faa2dbf0SJosef Bacik struct btrfs_tree_block_info *block_info; 23faa2dbf0SJosef Bacik struct btrfs_path *path; 24faa2dbf0SJosef Bacik struct extent_buffer *leaf; 25faa2dbf0SJosef Bacik struct btrfs_key ins; 26faa2dbf0SJosef Bacik u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info); 27faa2dbf0SJosef Bacik int ret; 28faa2dbf0SJosef Bacik 29483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 30faa2dbf0SJosef Bacik 31faa2dbf0SJosef Bacik ins.objectid = bytenr; 32faa2dbf0SJosef Bacik ins.type = BTRFS_EXTENT_ITEM_KEY; 33faa2dbf0SJosef Bacik ins.offset = num_bytes; 34faa2dbf0SJosef Bacik 35faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 36faa2dbf0SJosef Bacik if (!path) { 37770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 38faa2dbf0SJosef Bacik return -ENOMEM; 39faa2dbf0SJosef Bacik } 40faa2dbf0SJosef Bacik 41faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &ins, size); 42faa2dbf0SJosef Bacik if (ret) { 433c7251f2SDavid Sterba test_err("couldn't insert ref %d", ret); 44faa2dbf0SJosef Bacik btrfs_free_path(path); 45faa2dbf0SJosef Bacik return ret; 46faa2dbf0SJosef Bacik } 47faa2dbf0SJosef Bacik 48faa2dbf0SJosef Bacik leaf = path->nodes[0]; 49faa2dbf0SJosef Bacik item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 50faa2dbf0SJosef Bacik btrfs_set_extent_refs(leaf, item, 1); 51faa2dbf0SJosef Bacik btrfs_set_extent_generation(leaf, item, 1); 52faa2dbf0SJosef Bacik btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); 53faa2dbf0SJosef Bacik block_info = (struct btrfs_tree_block_info *)(item + 1); 543c0efdf0SQu Wenruo btrfs_set_tree_block_level(leaf, block_info, 0); 55faa2dbf0SJosef Bacik iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 56faa2dbf0SJosef Bacik if (parent > 0) { 57faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, 58faa2dbf0SJosef Bacik BTRFS_SHARED_BLOCK_REF_KEY); 59faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 60faa2dbf0SJosef Bacik } else { 61faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY); 62faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 63faa2dbf0SJosef Bacik } 64faa2dbf0SJosef Bacik btrfs_free_path(path); 65faa2dbf0SJosef Bacik return 0; 66faa2dbf0SJosef Bacik } 67faa2dbf0SJosef Bacik 68faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes, 69faa2dbf0SJosef Bacik u64 parent, u64 root_objectid) 70faa2dbf0SJosef Bacik { 71faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 72faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 73faa2dbf0SJosef Bacik struct btrfs_path *path; 74faa2dbf0SJosef Bacik struct btrfs_key key; 75faa2dbf0SJosef Bacik u64 refs; 76faa2dbf0SJosef Bacik int ret; 77faa2dbf0SJosef Bacik 78483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 79faa2dbf0SJosef Bacik 80faa2dbf0SJosef Bacik key.objectid = bytenr; 81faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 82faa2dbf0SJosef Bacik key.offset = num_bytes; 83faa2dbf0SJosef Bacik 84faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 85faa2dbf0SJosef Bacik if (!path) { 86770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 87faa2dbf0SJosef Bacik return -ENOMEM; 88faa2dbf0SJosef Bacik } 89faa2dbf0SJosef Bacik 90faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 91faa2dbf0SJosef Bacik if (ret) { 923c7251f2SDavid Sterba test_err("couldn't find extent ref"); 93faa2dbf0SJosef Bacik btrfs_free_path(path); 94faa2dbf0SJosef Bacik return ret; 95faa2dbf0SJosef Bacik } 96faa2dbf0SJosef Bacik 97faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 98faa2dbf0SJosef Bacik struct btrfs_extent_item); 99faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 100faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs + 1); 101faa2dbf0SJosef Bacik btrfs_release_path(path); 102faa2dbf0SJosef Bacik 103faa2dbf0SJosef Bacik key.objectid = bytenr; 104faa2dbf0SJosef Bacik if (parent) { 105faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 106faa2dbf0SJosef Bacik key.offset = parent; 107faa2dbf0SJosef Bacik } else { 108faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 109faa2dbf0SJosef Bacik key.offset = root_objectid; 110faa2dbf0SJosef Bacik } 111faa2dbf0SJosef Bacik 112faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &key, 0); 113faa2dbf0SJosef Bacik if (ret) 1143c7251f2SDavid Sterba test_err("failed to insert backref"); 115faa2dbf0SJosef Bacik btrfs_free_path(path); 116faa2dbf0SJosef Bacik return ret; 117faa2dbf0SJosef Bacik } 118faa2dbf0SJosef Bacik 119faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr, 120faa2dbf0SJosef Bacik u64 num_bytes) 121faa2dbf0SJosef Bacik { 122faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 123faa2dbf0SJosef Bacik struct btrfs_key key; 124faa2dbf0SJosef Bacik struct btrfs_path *path; 125faa2dbf0SJosef Bacik int ret; 126faa2dbf0SJosef Bacik 127483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 128faa2dbf0SJosef Bacik 129faa2dbf0SJosef Bacik key.objectid = bytenr; 130faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 131faa2dbf0SJosef Bacik key.offset = num_bytes; 132faa2dbf0SJosef Bacik 133faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 134faa2dbf0SJosef Bacik if (!path) { 135770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 136faa2dbf0SJosef Bacik return -ENOMEM; 137faa2dbf0SJosef Bacik } 138faa2dbf0SJosef Bacik 139faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 140faa2dbf0SJosef Bacik if (ret) { 1413c7251f2SDavid Sterba test_err("didn't find our key %d", ret); 142faa2dbf0SJosef Bacik btrfs_free_path(path); 143faa2dbf0SJosef Bacik return ret; 144faa2dbf0SJosef Bacik } 145faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 146faa2dbf0SJosef Bacik btrfs_free_path(path); 147faa2dbf0SJosef Bacik return 0; 148faa2dbf0SJosef Bacik } 149faa2dbf0SJosef Bacik 150faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr, 151faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 152faa2dbf0SJosef Bacik { 153faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 154faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 155faa2dbf0SJosef Bacik struct btrfs_path *path; 156faa2dbf0SJosef Bacik struct btrfs_key key; 157faa2dbf0SJosef Bacik u64 refs; 158faa2dbf0SJosef Bacik int ret; 159faa2dbf0SJosef Bacik 160483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 161faa2dbf0SJosef Bacik 162faa2dbf0SJosef Bacik key.objectid = bytenr; 163faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 164faa2dbf0SJosef Bacik key.offset = num_bytes; 165faa2dbf0SJosef Bacik 166faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 167faa2dbf0SJosef Bacik if (!path) { 168770e0cc0SDavid Sterba test_std_err(TEST_ALLOC_ROOT); 169faa2dbf0SJosef Bacik return -ENOMEM; 170faa2dbf0SJosef Bacik } 171faa2dbf0SJosef Bacik 172faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 173faa2dbf0SJosef Bacik if (ret) { 1743c7251f2SDavid Sterba test_err("couldn't find extent ref"); 175faa2dbf0SJosef Bacik btrfs_free_path(path); 176faa2dbf0SJosef Bacik return ret; 177faa2dbf0SJosef Bacik } 178faa2dbf0SJosef Bacik 179faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 180faa2dbf0SJosef Bacik struct btrfs_extent_item); 181faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 182faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs - 1); 183faa2dbf0SJosef Bacik btrfs_release_path(path); 184faa2dbf0SJosef Bacik 185faa2dbf0SJosef Bacik key.objectid = bytenr; 186faa2dbf0SJosef Bacik if (parent) { 187faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 188faa2dbf0SJosef Bacik key.offset = parent; 189faa2dbf0SJosef Bacik } else { 190faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 191faa2dbf0SJosef Bacik key.offset = root_objectid; 192faa2dbf0SJosef Bacik } 193faa2dbf0SJosef Bacik 194faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 195faa2dbf0SJosef Bacik if (ret) { 1963c7251f2SDavid Sterba test_err("couldn't find backref %d", ret); 197faa2dbf0SJosef Bacik btrfs_free_path(path); 198faa2dbf0SJosef Bacik return ret; 199faa2dbf0SJosef Bacik } 200faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 201faa2dbf0SJosef Bacik btrfs_free_path(path); 202faa2dbf0SJosef Bacik return ret; 203faa2dbf0SJosef Bacik } 204faa2dbf0SJosef Bacik 205b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root, 206b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 207faa2dbf0SJosef Bacik { 208faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 209faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 210442244c9SQu Wenruo struct ulist *old_roots = NULL; 211442244c9SQu Wenruo struct ulist *new_roots = NULL; 212faa2dbf0SJosef Bacik int ret; 213faa2dbf0SJosef Bacik 214483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, fs_info); 215faa2dbf0SJosef Bacik 216e4fa7469SDavid Sterba test_msg("running qgroup add/remove tests"); 21749a05ecdSLu Fengqi ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID); 218faa2dbf0SJosef Bacik if (ret) { 2193c7251f2SDavid Sterba test_err("couldn't create a qgroup %d", ret); 220faa2dbf0SJosef Bacik return ret; 221faa2dbf0SJosef Bacik } 222faa2dbf0SJosef Bacik 223442244c9SQu Wenruo /* 22401327610SNicholas D Steeves * Since the test trans doesn't have the complicated delayed refs, 225442244c9SQu Wenruo * we can only call btrfs_qgroup_account_extent() directly to test 226442244c9SQu Wenruo * quota. 227442244c9SQu Wenruo */ 228c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 229faa2dbf0SJosef Bacik if (ret) { 2303c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 231faa2dbf0SJosef Bacik return ret; 232faa2dbf0SJosef Bacik } 233faa2dbf0SJosef Bacik 234ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 235ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 236d37de92bSFilipe Manana if (ret) { 237d37de92bSFilipe Manana ulist_free(old_roots); 238faa2dbf0SJosef Bacik return ret; 239d37de92bSFilipe Manana } 240faa2dbf0SJosef Bacik 241c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 242faa2dbf0SJosef Bacik if (ret) { 243442244c9SQu Wenruo ulist_free(old_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 255d0ea17aeSFilipe Manana /* btrfs_qgroup_account_extent() always frees the ulists passed to it. */ 256d0ea17aeSFilipe Manana old_roots = NULL; 257d0ea17aeSFilipe Manana new_roots = NULL; 258d0ea17aeSFilipe Manana 259ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 260ef9f2db3SFeifei Xu nodesize, nodesize)) { 2613c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 262faa2dbf0SJosef Bacik return -EINVAL; 263faa2dbf0SJosef Bacik } 264442244c9SQu Wenruo 265c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 266442244c9SQu Wenruo if (ret) { 2673c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 268442244c9SQu Wenruo return ret; 269442244c9SQu Wenruo } 270faa2dbf0SJosef Bacik 271b9ef22deSFeifei Xu ret = remove_extent_item(root, nodesize, nodesize); 272d37de92bSFilipe Manana if (ret) { 273d37de92bSFilipe Manana ulist_free(old_roots); 274faa2dbf0SJosef Bacik return -EINVAL; 275d37de92bSFilipe Manana } 276faa2dbf0SJosef Bacik 277c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 278faa2dbf0SJosef Bacik if (ret) { 279442244c9SQu Wenruo ulist_free(old_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) { 3293c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 330442244c9SQu Wenruo return ret; 331442244c9SQu Wenruo } 332442244c9SQu Wenruo 333ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 334ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 335d37de92bSFilipe Manana if (ret) { 336d37de92bSFilipe Manana ulist_free(old_roots); 337faa2dbf0SJosef Bacik return ret; 338d37de92bSFilipe Manana } 339faa2dbf0SJosef Bacik 340c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 341faa2dbf0SJosef Bacik if (ret) { 342442244c9SQu Wenruo ulist_free(old_roots); 3433c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 344faa2dbf0SJosef Bacik return ret; 345faa2dbf0SJosef Bacik } 346faa2dbf0SJosef Bacik 3478696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3488696d760SLu Fengqi new_roots); 349faa2dbf0SJosef Bacik if (ret) { 3503c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 351faa2dbf0SJosef Bacik return ret; 352faa2dbf0SJosef Bacik } 353faa2dbf0SJosef Bacik 354ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 355b9ef22deSFeifei Xu nodesize, nodesize)) { 3563c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 357faa2dbf0SJosef Bacik return -EINVAL; 358faa2dbf0SJosef Bacik } 359faa2dbf0SJosef Bacik 360c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 361442244c9SQu Wenruo if (ret) { 3623c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 363442244c9SQu Wenruo return ret; 364442244c9SQu Wenruo } 365442244c9SQu Wenruo 366ef9f2db3SFeifei Xu ret = add_tree_ref(root, nodesize, nodesize, 0, 367ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 368d37de92bSFilipe Manana if (ret) { 369d37de92bSFilipe Manana ulist_free(old_roots); 370faa2dbf0SJosef Bacik return ret; 371d37de92bSFilipe Manana } 372faa2dbf0SJosef Bacik 373c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 374faa2dbf0SJosef Bacik if (ret) { 375442244c9SQu Wenruo ulist_free(old_roots); 3763c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 377faa2dbf0SJosef Bacik return ret; 378faa2dbf0SJosef Bacik } 379faa2dbf0SJosef Bacik 3808696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3818696d760SLu Fengqi new_roots); 382faa2dbf0SJosef Bacik if (ret) { 3833c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 384faa2dbf0SJosef Bacik return ret; 385faa2dbf0SJosef Bacik } 386faa2dbf0SJosef Bacik 387ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 388ef9f2db3SFeifei Xu nodesize, 0)) { 3893c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 390faa2dbf0SJosef Bacik return -EINVAL; 391faa2dbf0SJosef Bacik } 392faa2dbf0SJosef Bacik 393ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 394ef9f2db3SFeifei Xu nodesize, 0)) { 3953c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 396faa2dbf0SJosef Bacik return -EINVAL; 397faa2dbf0SJosef Bacik } 398faa2dbf0SJosef Bacik 399c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false); 400442244c9SQu Wenruo if (ret) { 4013c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 402442244c9SQu Wenruo return ret; 403442244c9SQu Wenruo } 404442244c9SQu Wenruo 405ef9f2db3SFeifei Xu ret = remove_extent_ref(root, nodesize, nodesize, 0, 406ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 407d37de92bSFilipe Manana if (ret) { 408d37de92bSFilipe Manana ulist_free(old_roots); 409faa2dbf0SJosef Bacik return ret; 410d37de92bSFilipe Manana } 411faa2dbf0SJosef Bacik 412c7bcbb21SFilipe Manana ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false); 413faa2dbf0SJosef Bacik if (ret) { 414442244c9SQu Wenruo ulist_free(old_roots); 4153c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 416faa2dbf0SJosef Bacik return ret; 417faa2dbf0SJosef Bacik } 418faa2dbf0SJosef Bacik 4198696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 4208696d760SLu Fengqi new_roots); 421faa2dbf0SJosef Bacik if (ret) { 4223c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 423faa2dbf0SJosef Bacik return ret; 424faa2dbf0SJosef Bacik } 425faa2dbf0SJosef Bacik 426ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 427ef9f2db3SFeifei Xu 0, 0)) { 4283c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 429faa2dbf0SJosef Bacik return -EINVAL; 430faa2dbf0SJosef Bacik } 431faa2dbf0SJosef Bacik 432ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 433ef9f2db3SFeifei Xu nodesize, nodesize)) { 4343c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 435faa2dbf0SJosef Bacik return -EINVAL; 436faa2dbf0SJosef Bacik } 437faa2dbf0SJosef Bacik 438faa2dbf0SJosef Bacik return 0; 439faa2dbf0SJosef Bacik } 440faa2dbf0SJosef Bacik 441b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) 442faa2dbf0SJosef Bacik { 4437c0260eeSJeff Mahoney struct btrfs_fs_info *fs_info = NULL; 444faa2dbf0SJosef Bacik struct btrfs_root *root; 445faa2dbf0SJosef Bacik struct btrfs_root *tmp_root; 446faa2dbf0SJosef Bacik int ret = 0; 447faa2dbf0SJosef Bacik 448da17066cSJeff Mahoney fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 4497c0260eeSJeff Mahoney if (!fs_info) { 45037b2a7bcSDavid Sterba test_std_err(TEST_ALLOC_FS_INFO); 4517c0260eeSJeff Mahoney return -ENOMEM; 452faa2dbf0SJosef Bacik } 453faa2dbf0SJosef Bacik 454da17066cSJeff Mahoney root = btrfs_alloc_dummy_root(fs_info); 4557c0260eeSJeff Mahoney if (IS_ERR(root)) { 45652ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 4577c0260eeSJeff Mahoney ret = PTR_ERR(root); 458faa2dbf0SJosef Bacik goto out; 459faa2dbf0SJosef Bacik } 4607c0260eeSJeff Mahoney 4613f556f78SDavid Sterba /* We are using this root as our extent root */ 462abed4aaaSJosef Bacik root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID; 463abed4aaaSJosef Bacik root->root_key.type = BTRFS_ROOT_ITEM_KEY; 464abed4aaaSJosef Bacik root->root_key.offset = 0; 465abed4aaaSJosef Bacik btrfs_global_root_insert(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; 473afcdd129SJosef Bacik set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); 474faa2dbf0SJosef Bacik 475faa2dbf0SJosef Bacik /* 476faa2dbf0SJosef Bacik * Can't use bytenr 0, some things freak out 477faa2dbf0SJosef Bacik * *cough*backref walking code*cough* 478faa2dbf0SJosef Bacik */ 479da17066cSJeff Mahoney root->node = alloc_test_extent_buffer(root->fs_info, nodesize); 480b6293c82SDan Carpenter if (IS_ERR(root->node)) { 4813c7251f2SDavid Sterba test_err("couldn't allocate dummy buffer"); 482b6293c82SDan Carpenter ret = PTR_ERR(root->node); 483faa2dbf0SJosef Bacik goto out; 484faa2dbf0SJosef Bacik } 485b050f9f6SFilipe Manana btrfs_set_header_level(root->node, 0); 486b050f9f6SFilipe Manana btrfs_set_header_nritems(root->node, 0); 487b9ef22deSFeifei Xu root->alloc_bytenr += 2 * nodesize; 488faa2dbf0SJosef Bacik 489da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 490faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 49152ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 492faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 493faa2dbf0SJosef Bacik goto out; 494faa2dbf0SJosef Bacik } 495faa2dbf0SJosef Bacik 496ef9f2db3SFeifei Xu tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID; 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) { 5003c7251f2SDavid Sterba test_err("couldn't insert fs root %d", ret); 501faa2dbf0SJosef Bacik goto out; 502faa2dbf0SJosef Bacik } 5034785e24fSJosef Bacik btrfs_put_root(tmp_root); 504faa2dbf0SJosef Bacik 505da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 506faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 50752ab7bcaSDavid Sterba test_std_err(TEST_ALLOC_ROOT); 508faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 509faa2dbf0SJosef Bacik goto out; 510faa2dbf0SJosef Bacik } 511faa2dbf0SJosef Bacik 512ef9f2db3SFeifei Xu tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID; 513faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 514faa2dbf0SJosef Bacik if (ret) { 5153c7251f2SDavid Sterba test_err("couldn't insert fs root %d", ret); 516faa2dbf0SJosef Bacik goto out; 517faa2dbf0SJosef Bacik } 5184785e24fSJosef Bacik btrfs_put_root(tmp_root); 519faa2dbf0SJosef Bacik 520315b76b4SDavid Sterba test_msg("running qgroup tests"); 521b9ef22deSFeifei Xu ret = test_no_shared_qgroup(root, sectorsize, nodesize); 522faa2dbf0SJosef Bacik if (ret) 523faa2dbf0SJosef Bacik goto out; 524b9ef22deSFeifei Xu ret = test_multiple_refs(root, sectorsize, nodesize); 525faa2dbf0SJosef Bacik out: 526faa2dbf0SJosef Bacik btrfs_free_dummy_root(root); 5277c0260eeSJeff Mahoney btrfs_free_dummy_fs_info(fs_info); 528faa2dbf0SJosef Bacik return ret; 529faa2dbf0SJosef Bacik } 530