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) { 353c7251f2SDavid Sterba test_err("couldn't allocate path"); 36faa2dbf0SJosef Bacik return -ENOMEM; 37faa2dbf0SJosef Bacik } 38faa2dbf0SJosef Bacik 39faa2dbf0SJosef Bacik path->leave_spinning = 1; 40faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &ins, size); 41faa2dbf0SJosef Bacik if (ret) { 423c7251f2SDavid Sterba test_err("couldn't insert ref %d", ret); 43faa2dbf0SJosef Bacik btrfs_free_path(path); 44faa2dbf0SJosef Bacik return ret; 45faa2dbf0SJosef Bacik } 46faa2dbf0SJosef Bacik 47faa2dbf0SJosef Bacik leaf = path->nodes[0]; 48faa2dbf0SJosef Bacik item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 49faa2dbf0SJosef Bacik btrfs_set_extent_refs(leaf, item, 1); 50faa2dbf0SJosef Bacik btrfs_set_extent_generation(leaf, item, 1); 51faa2dbf0SJosef Bacik btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); 52faa2dbf0SJosef Bacik block_info = (struct btrfs_tree_block_info *)(item + 1); 533c0efdf0SQu Wenruo btrfs_set_tree_block_level(leaf, block_info, 0); 54faa2dbf0SJosef Bacik iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 55faa2dbf0SJosef Bacik if (parent > 0) { 56faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, 57faa2dbf0SJosef Bacik BTRFS_SHARED_BLOCK_REF_KEY); 58faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 59faa2dbf0SJosef Bacik } else { 60faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY); 61faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 62faa2dbf0SJosef Bacik } 63faa2dbf0SJosef Bacik btrfs_free_path(path); 64faa2dbf0SJosef Bacik return 0; 65faa2dbf0SJosef Bacik } 66faa2dbf0SJosef Bacik 67faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes, 68faa2dbf0SJosef Bacik u64 parent, u64 root_objectid) 69faa2dbf0SJosef Bacik { 70faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 71faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 72faa2dbf0SJosef Bacik struct btrfs_path *path; 73faa2dbf0SJosef Bacik struct btrfs_key key; 74faa2dbf0SJosef Bacik u64 refs; 75faa2dbf0SJosef Bacik int ret; 76faa2dbf0SJosef Bacik 77483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 78faa2dbf0SJosef Bacik 79faa2dbf0SJosef Bacik key.objectid = bytenr; 80faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 81faa2dbf0SJosef Bacik key.offset = num_bytes; 82faa2dbf0SJosef Bacik 83faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 84faa2dbf0SJosef Bacik if (!path) { 853c7251f2SDavid Sterba test_err("couldn't allocate path"); 86faa2dbf0SJosef Bacik return -ENOMEM; 87faa2dbf0SJosef Bacik } 88faa2dbf0SJosef Bacik 89faa2dbf0SJosef Bacik path->leave_spinning = 1; 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) { 1353c7251f2SDavid Sterba test_err("couldn't allocate path"); 136faa2dbf0SJosef Bacik return -ENOMEM; 137faa2dbf0SJosef Bacik } 138faa2dbf0SJosef Bacik path->leave_spinning = 1; 139faa2dbf0SJosef Bacik 140faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 141faa2dbf0SJosef Bacik if (ret) { 1423c7251f2SDavid Sterba test_err("didn't find our key %d", ret); 143faa2dbf0SJosef Bacik btrfs_free_path(path); 144faa2dbf0SJosef Bacik return ret; 145faa2dbf0SJosef Bacik } 146faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 147faa2dbf0SJosef Bacik btrfs_free_path(path); 148faa2dbf0SJosef Bacik return 0; 149faa2dbf0SJosef Bacik } 150faa2dbf0SJosef Bacik 151faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr, 152faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 153faa2dbf0SJosef Bacik { 154faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 155faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 156faa2dbf0SJosef Bacik struct btrfs_path *path; 157faa2dbf0SJosef Bacik struct btrfs_key key; 158faa2dbf0SJosef Bacik u64 refs; 159faa2dbf0SJosef Bacik int ret; 160faa2dbf0SJosef Bacik 161483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, NULL); 162faa2dbf0SJosef Bacik 163faa2dbf0SJosef Bacik key.objectid = bytenr; 164faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 165faa2dbf0SJosef Bacik key.offset = num_bytes; 166faa2dbf0SJosef Bacik 167faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 168faa2dbf0SJosef Bacik if (!path) { 1693c7251f2SDavid Sterba test_err("couldn't allocate path"); 170faa2dbf0SJosef Bacik return -ENOMEM; 171faa2dbf0SJosef Bacik } 172faa2dbf0SJosef Bacik 173faa2dbf0SJosef Bacik path->leave_spinning = 1; 174faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 175faa2dbf0SJosef Bacik if (ret) { 1763c7251f2SDavid Sterba test_err("couldn't find extent ref"); 177faa2dbf0SJosef Bacik btrfs_free_path(path); 178faa2dbf0SJosef Bacik return ret; 179faa2dbf0SJosef Bacik } 180faa2dbf0SJosef Bacik 181faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 182faa2dbf0SJosef Bacik struct btrfs_extent_item); 183faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 184faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs - 1); 185faa2dbf0SJosef Bacik btrfs_release_path(path); 186faa2dbf0SJosef Bacik 187faa2dbf0SJosef Bacik key.objectid = bytenr; 188faa2dbf0SJosef Bacik if (parent) { 189faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 190faa2dbf0SJosef Bacik key.offset = parent; 191faa2dbf0SJosef Bacik } else { 192faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 193faa2dbf0SJosef Bacik key.offset = root_objectid; 194faa2dbf0SJosef Bacik } 195faa2dbf0SJosef Bacik 196faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 197faa2dbf0SJosef Bacik if (ret) { 1983c7251f2SDavid Sterba test_err("couldn't find backref %d", ret); 199faa2dbf0SJosef Bacik btrfs_free_path(path); 200faa2dbf0SJosef Bacik return ret; 201faa2dbf0SJosef Bacik } 202faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 203faa2dbf0SJosef Bacik btrfs_free_path(path); 204faa2dbf0SJosef Bacik return ret; 205faa2dbf0SJosef Bacik } 206faa2dbf0SJosef Bacik 207b9ef22deSFeifei Xu static int test_no_shared_qgroup(struct btrfs_root *root, 208b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 209faa2dbf0SJosef Bacik { 210faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 211faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 212442244c9SQu Wenruo struct ulist *old_roots = NULL; 213442244c9SQu Wenruo struct ulist *new_roots = NULL; 214faa2dbf0SJosef Bacik int ret; 215faa2dbf0SJosef Bacik 216483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, fs_info); 217faa2dbf0SJosef Bacik 218315b76b4SDavid Sterba test_msg("qgroup basic add"); 21949a05ecdSLu Fengqi ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID); 220faa2dbf0SJosef Bacik if (ret) { 2213c7251f2SDavid Sterba test_err("couldn't create a qgroup %d", ret); 222faa2dbf0SJosef Bacik return ret; 223faa2dbf0SJosef Bacik } 224faa2dbf0SJosef Bacik 225442244c9SQu Wenruo /* 22601327610SNicholas D Steeves * Since the test trans doesn't have the complicated delayed refs, 227442244c9SQu Wenruo * we can only call btrfs_qgroup_account_extent() directly to test 228442244c9SQu Wenruo * quota. 229442244c9SQu Wenruo */ 230c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 231c995ab3cSZygo Blaxell false); 232faa2dbf0SJosef Bacik if (ret) { 233442244c9SQu Wenruo ulist_free(old_roots); 2343c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 235faa2dbf0SJosef Bacik return ret; 236faa2dbf0SJosef Bacik } 237faa2dbf0SJosef Bacik 238ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 239ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 240faa2dbf0SJosef Bacik if (ret) 241faa2dbf0SJosef Bacik return ret; 242faa2dbf0SJosef Bacik 243c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 244c995ab3cSZygo Blaxell false); 245faa2dbf0SJosef Bacik if (ret) { 246442244c9SQu Wenruo ulist_free(old_roots); 247442244c9SQu Wenruo ulist_free(new_roots); 2483c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 249442244c9SQu Wenruo return ret; 250442244c9SQu Wenruo } 251442244c9SQu Wenruo 2528696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2538696d760SLu Fengqi new_roots); 254442244c9SQu Wenruo if (ret) { 2553c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 256faa2dbf0SJosef Bacik return ret; 257faa2dbf0SJosef Bacik } 258faa2dbf0SJosef Bacik 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 old_roots = NULL; 265442244c9SQu Wenruo new_roots = NULL; 266442244c9SQu Wenruo 267c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 268c995ab3cSZygo Blaxell false); 269442244c9SQu Wenruo if (ret) { 270442244c9SQu Wenruo ulist_free(old_roots); 2713c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 272442244c9SQu Wenruo return ret; 273442244c9SQu Wenruo } 274faa2dbf0SJosef Bacik 275b9ef22deSFeifei Xu ret = remove_extent_item(root, nodesize, nodesize); 276faa2dbf0SJosef Bacik if (ret) 277faa2dbf0SJosef Bacik return -EINVAL; 278faa2dbf0SJosef Bacik 279c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 280c995ab3cSZygo Blaxell false); 281faa2dbf0SJosef Bacik if (ret) { 282442244c9SQu Wenruo ulist_free(old_roots); 283442244c9SQu Wenruo ulist_free(new_roots); 2843c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 285442244c9SQu Wenruo return ret; 286faa2dbf0SJosef Bacik } 287faa2dbf0SJosef Bacik 2888696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2898696d760SLu Fengqi new_roots); 290faa2dbf0SJosef Bacik if (ret) { 2913c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 292faa2dbf0SJosef Bacik return -EINVAL; 293faa2dbf0SJosef Bacik } 294faa2dbf0SJosef Bacik 295ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) { 2963c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 297faa2dbf0SJosef Bacik return -EINVAL; 298faa2dbf0SJosef Bacik } 299faa2dbf0SJosef Bacik 300faa2dbf0SJosef Bacik return 0; 301faa2dbf0SJosef Bacik } 302faa2dbf0SJosef Bacik 303faa2dbf0SJosef Bacik /* 304faa2dbf0SJosef Bacik * Add a ref for two different roots to make sure the shared value comes out 305faa2dbf0SJosef Bacik * right, also remove one of the roots and make sure the exclusive count is 306faa2dbf0SJosef Bacik * adjusted properly. 307faa2dbf0SJosef Bacik */ 308b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root, 309b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 310faa2dbf0SJosef Bacik { 311faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 312faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 313442244c9SQu Wenruo struct ulist *old_roots = NULL; 314442244c9SQu Wenruo struct ulist *new_roots = NULL; 315faa2dbf0SJosef Bacik int ret; 316faa2dbf0SJosef Bacik 317483bce06SNikolay Borisov btrfs_init_dummy_trans(&trans, fs_info); 318faa2dbf0SJosef Bacik 319315b76b4SDavid Sterba test_msg("qgroup multiple refs test"); 320faa2dbf0SJosef Bacik 321ef9f2db3SFeifei Xu /* 322ef9f2db3SFeifei Xu * We have BTRFS_FS_TREE_OBJECTID created already from the 323ef9f2db3SFeifei Xu * previous test. 324ef9f2db3SFeifei Xu */ 32549a05ecdSLu Fengqi ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID); 326faa2dbf0SJosef Bacik if (ret) { 3273c7251f2SDavid Sterba test_err("couldn't create a qgroup %d", ret); 328faa2dbf0SJosef Bacik return ret; 329faa2dbf0SJosef Bacik } 330faa2dbf0SJosef Bacik 331c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 332c995ab3cSZygo Blaxell false); 333442244c9SQu Wenruo if (ret) { 334442244c9SQu Wenruo ulist_free(old_roots); 3353c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 336442244c9SQu Wenruo return ret; 337442244c9SQu Wenruo } 338442244c9SQu Wenruo 339ef9f2db3SFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 340ef9f2db3SFeifei Xu BTRFS_FS_TREE_OBJECTID); 341faa2dbf0SJosef Bacik if (ret) 342faa2dbf0SJosef Bacik return ret; 343faa2dbf0SJosef Bacik 344c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 345c995ab3cSZygo Blaxell false); 346faa2dbf0SJosef Bacik if (ret) { 347442244c9SQu Wenruo ulist_free(old_roots); 348442244c9SQu Wenruo ulist_free(new_roots); 3493c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 350faa2dbf0SJosef Bacik return ret; 351faa2dbf0SJosef Bacik } 352faa2dbf0SJosef Bacik 3538696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3548696d760SLu Fengqi new_roots); 355faa2dbf0SJosef Bacik if (ret) { 3563c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 357faa2dbf0SJosef Bacik return ret; 358faa2dbf0SJosef Bacik } 359faa2dbf0SJosef Bacik 360ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 361b9ef22deSFeifei Xu nodesize, nodesize)) { 3623c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 363faa2dbf0SJosef Bacik return -EINVAL; 364faa2dbf0SJosef Bacik } 365faa2dbf0SJosef Bacik 366c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 367c995ab3cSZygo Blaxell false); 368442244c9SQu Wenruo if (ret) { 369442244c9SQu Wenruo ulist_free(old_roots); 3703c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 371442244c9SQu Wenruo return ret; 372442244c9SQu Wenruo } 373442244c9SQu Wenruo 374ef9f2db3SFeifei Xu ret = add_tree_ref(root, nodesize, nodesize, 0, 375ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 376faa2dbf0SJosef Bacik if (ret) 377faa2dbf0SJosef Bacik return ret; 378faa2dbf0SJosef Bacik 379c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 380c995ab3cSZygo Blaxell false); 381faa2dbf0SJosef Bacik if (ret) { 382442244c9SQu Wenruo ulist_free(old_roots); 383442244c9SQu Wenruo ulist_free(new_roots); 3843c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 385faa2dbf0SJosef Bacik return ret; 386faa2dbf0SJosef Bacik } 387faa2dbf0SJosef Bacik 3888696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3898696d760SLu Fengqi new_roots); 390faa2dbf0SJosef Bacik if (ret) { 3913c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 392faa2dbf0SJosef Bacik return ret; 393faa2dbf0SJosef Bacik } 394faa2dbf0SJosef Bacik 395ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 396ef9f2db3SFeifei Xu nodesize, 0)) { 3973c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 398faa2dbf0SJosef Bacik return -EINVAL; 399faa2dbf0SJosef Bacik } 400faa2dbf0SJosef Bacik 401ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 402ef9f2db3SFeifei Xu nodesize, 0)) { 4033c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 404faa2dbf0SJosef Bacik return -EINVAL; 405faa2dbf0SJosef Bacik } 406faa2dbf0SJosef Bacik 407c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 408c995ab3cSZygo Blaxell false); 409442244c9SQu Wenruo if (ret) { 410442244c9SQu Wenruo ulist_free(old_roots); 4113c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 412442244c9SQu Wenruo return ret; 413442244c9SQu Wenruo } 414442244c9SQu Wenruo 415ef9f2db3SFeifei Xu ret = remove_extent_ref(root, nodesize, nodesize, 0, 416ef9f2db3SFeifei Xu BTRFS_FIRST_FREE_OBJECTID); 417faa2dbf0SJosef Bacik if (ret) 418faa2dbf0SJosef Bacik return ret; 419faa2dbf0SJosef Bacik 420c995ab3cSZygo Blaxell ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 421c995ab3cSZygo Blaxell false); 422faa2dbf0SJosef Bacik if (ret) { 423442244c9SQu Wenruo ulist_free(old_roots); 424442244c9SQu Wenruo ulist_free(new_roots); 4253c7251f2SDavid Sterba test_err("couldn't find old roots: %d", ret); 426faa2dbf0SJosef Bacik return ret; 427faa2dbf0SJosef Bacik } 428faa2dbf0SJosef Bacik 4298696d760SLu Fengqi ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 4308696d760SLu Fengqi new_roots); 431faa2dbf0SJosef Bacik if (ret) { 4323c7251f2SDavid Sterba test_err("couldn't account space for a qgroup %d", ret); 433faa2dbf0SJosef Bacik return ret; 434faa2dbf0SJosef Bacik } 435faa2dbf0SJosef Bacik 436ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 437ef9f2db3SFeifei Xu 0, 0)) { 4383c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 439faa2dbf0SJosef Bacik return -EINVAL; 440faa2dbf0SJosef Bacik } 441faa2dbf0SJosef Bacik 442ef9f2db3SFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 443ef9f2db3SFeifei Xu nodesize, nodesize)) { 4443c7251f2SDavid Sterba test_err("qgroup counts didn't match expected values"); 445faa2dbf0SJosef Bacik return -EINVAL; 446faa2dbf0SJosef Bacik } 447faa2dbf0SJosef Bacik 448faa2dbf0SJosef Bacik return 0; 449faa2dbf0SJosef Bacik } 450faa2dbf0SJosef Bacik 451b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) 452faa2dbf0SJosef Bacik { 4537c0260eeSJeff Mahoney struct btrfs_fs_info *fs_info = NULL; 454faa2dbf0SJosef Bacik struct btrfs_root *root; 455faa2dbf0SJosef Bacik struct btrfs_root *tmp_root; 456faa2dbf0SJosef Bacik int ret = 0; 457faa2dbf0SJosef Bacik 458da17066cSJeff Mahoney fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 4597c0260eeSJeff Mahoney if (!fs_info) { 46037b2a7bcSDavid Sterba test_std_err(TEST_ALLOC_FS_INFO); 4617c0260eeSJeff Mahoney return -ENOMEM; 462faa2dbf0SJosef Bacik } 463faa2dbf0SJosef Bacik 464da17066cSJeff Mahoney root = btrfs_alloc_dummy_root(fs_info); 4657c0260eeSJeff Mahoney if (IS_ERR(root)) { 4663c7251f2SDavid Sterba test_err("couldn't allocate root"); 4677c0260eeSJeff Mahoney ret = PTR_ERR(root); 468faa2dbf0SJosef Bacik goto out; 469faa2dbf0SJosef Bacik } 4707c0260eeSJeff Mahoney 4713f556f78SDavid Sterba /* We are using this root as our extent root */ 4723f556f78SDavid Sterba root->fs_info->extent_root = root; 4733f556f78SDavid Sterba 4743f556f78SDavid Sterba /* 4753f556f78SDavid Sterba * Some of the paths we test assume we have a filled out fs_info, so we 4763f556f78SDavid Sterba * just need to add the root in there so we don't panic. 4773f556f78SDavid Sterba */ 4783f556f78SDavid Sterba root->fs_info->tree_root = root; 4793f556f78SDavid Sterba root->fs_info->quota_root = root; 480afcdd129SJosef Bacik set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); 481faa2dbf0SJosef Bacik 482faa2dbf0SJosef Bacik /* 483faa2dbf0SJosef Bacik * Can't use bytenr 0, some things freak out 484faa2dbf0SJosef Bacik * *cough*backref walking code*cough* 485faa2dbf0SJosef Bacik */ 486da17066cSJeff Mahoney root->node = alloc_test_extent_buffer(root->fs_info, nodesize); 487faa2dbf0SJosef Bacik if (!root->node) { 4883c7251f2SDavid Sterba test_err("couldn't allocate dummy buffer"); 489faa2dbf0SJosef Bacik ret = -ENOMEM; 490faa2dbf0SJosef Bacik goto out; 491faa2dbf0SJosef Bacik } 492b050f9f6SFilipe Manana btrfs_set_header_level(root->node, 0); 493b050f9f6SFilipe Manana btrfs_set_header_nritems(root->node, 0); 494b9ef22deSFeifei Xu root->alloc_bytenr += 2 * nodesize; 495faa2dbf0SJosef Bacik 496da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 497faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 4983c7251f2SDavid Sterba test_err("couldn't allocate a fs root"); 499faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 500faa2dbf0SJosef Bacik goto out; 501faa2dbf0SJosef Bacik } 502faa2dbf0SJosef Bacik 503ef9f2db3SFeifei Xu tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID; 504faa2dbf0SJosef Bacik root->fs_info->fs_root = tmp_root; 505faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 506faa2dbf0SJosef Bacik if (ret) { 5073c7251f2SDavid Sterba test_err("couldn't insert fs root %d", ret); 508faa2dbf0SJosef Bacik goto out; 509faa2dbf0SJosef Bacik } 510faa2dbf0SJosef Bacik 511da17066cSJeff Mahoney tmp_root = btrfs_alloc_dummy_root(fs_info); 512faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 5133c7251f2SDavid Sterba test_err("couldn't allocate a fs 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 } 524faa2dbf0SJosef Bacik 525315b76b4SDavid Sterba test_msg("running qgroup tests"); 526b9ef22deSFeifei Xu ret = test_no_shared_qgroup(root, sectorsize, nodesize); 527faa2dbf0SJosef Bacik if (ret) 528faa2dbf0SJosef Bacik goto out; 529b9ef22deSFeifei Xu ret = test_multiple_refs(root, sectorsize, nodesize); 530faa2dbf0SJosef Bacik out: 531faa2dbf0SJosef Bacik btrfs_free_dummy_root(root); 5327c0260eeSJeff Mahoney btrfs_free_dummy_fs_info(fs_info); 533faa2dbf0SJosef Bacik return ret; 534faa2dbf0SJosef Bacik } 535