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"); 2324087cf24SDongsheng Yang ret = btrfs_create_qgroup(NULL, fs_info, 5); 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 250b9ef22deSFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 5); 251faa2dbf0SJosef Bacik if (ret) 252faa2dbf0SJosef Bacik return ret; 253faa2dbf0SJosef Bacik 254b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); 255faa2dbf0SJosef Bacik if (ret) { 256442244c9SQu Wenruo ulist_free(old_roots); 257442244c9SQu Wenruo ulist_free(new_roots); 258442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 259442244c9SQu Wenruo return ret; 260442244c9SQu Wenruo } 261442244c9SQu Wenruo 262b9ef22deSFeifei Xu ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, 263b9ef22deSFeifei Xu nodesize, old_roots, new_roots); 264442244c9SQu Wenruo if (ret) { 265442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 266faa2dbf0SJosef Bacik return ret; 267faa2dbf0SJosef Bacik } 268faa2dbf0SJosef Bacik 269b9ef22deSFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, nodesize)) { 270faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 271faa2dbf0SJosef Bacik return -EINVAL; 272faa2dbf0SJosef Bacik } 273442244c9SQu Wenruo old_roots = NULL; 274442244c9SQu Wenruo new_roots = NULL; 275442244c9SQu Wenruo 276b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); 277442244c9SQu Wenruo if (ret) { 278442244c9SQu Wenruo ulist_free(old_roots); 279442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 280442244c9SQu Wenruo return ret; 281442244c9SQu Wenruo } 282faa2dbf0SJosef Bacik 283b9ef22deSFeifei Xu ret = remove_extent_item(root, nodesize, nodesize); 284faa2dbf0SJosef Bacik if (ret) 285faa2dbf0SJosef Bacik return -EINVAL; 286faa2dbf0SJosef Bacik 287b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); 288faa2dbf0SJosef Bacik if (ret) { 289442244c9SQu Wenruo ulist_free(old_roots); 290442244c9SQu Wenruo ulist_free(new_roots); 291442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 292442244c9SQu Wenruo return ret; 293faa2dbf0SJosef Bacik } 294faa2dbf0SJosef Bacik 295b9ef22deSFeifei Xu ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, 296b9ef22deSFeifei Xu nodesize, old_roots, new_roots); 297faa2dbf0SJosef Bacik if (ret) { 298442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 299faa2dbf0SJosef Bacik return -EINVAL; 300faa2dbf0SJosef Bacik } 301faa2dbf0SJosef Bacik 302faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) { 303faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 304faa2dbf0SJosef Bacik return -EINVAL; 305faa2dbf0SJosef Bacik } 306faa2dbf0SJosef Bacik 307faa2dbf0SJosef Bacik return 0; 308faa2dbf0SJosef Bacik } 309faa2dbf0SJosef Bacik 310faa2dbf0SJosef Bacik /* 311faa2dbf0SJosef Bacik * Add a ref for two different roots to make sure the shared value comes out 312faa2dbf0SJosef Bacik * right, also remove one of the roots and make sure the exclusive count is 313faa2dbf0SJosef Bacik * adjusted properly. 314faa2dbf0SJosef Bacik */ 315b9ef22deSFeifei Xu static int test_multiple_refs(struct btrfs_root *root, 316b9ef22deSFeifei Xu u32 sectorsize, u32 nodesize) 317faa2dbf0SJosef Bacik { 318faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 319faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 320442244c9SQu Wenruo struct ulist *old_roots = NULL; 321442244c9SQu Wenruo struct ulist *new_roots = NULL; 322faa2dbf0SJosef Bacik int ret; 323faa2dbf0SJosef Bacik 3247c55ee0cSOmar Sandoval btrfs_init_dummy_trans(&trans); 325faa2dbf0SJosef Bacik 326faa2dbf0SJosef Bacik test_msg("Qgroup multiple refs test\n"); 327faa2dbf0SJosef Bacik 328faa2dbf0SJosef Bacik /* We have 5 created already from the previous test */ 3294087cf24SDongsheng Yang ret = btrfs_create_qgroup(NULL, fs_info, 256); 330faa2dbf0SJosef Bacik if (ret) { 331faa2dbf0SJosef Bacik test_msg("Couldn't create a qgroup %d\n", ret); 332faa2dbf0SJosef Bacik return ret; 333faa2dbf0SJosef Bacik } 334faa2dbf0SJosef Bacik 335b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); 336442244c9SQu Wenruo if (ret) { 337442244c9SQu Wenruo ulist_free(old_roots); 338442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 339442244c9SQu Wenruo return ret; 340442244c9SQu Wenruo } 341442244c9SQu Wenruo 342b9ef22deSFeifei Xu ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 5); 343faa2dbf0SJosef Bacik if (ret) 344faa2dbf0SJosef Bacik return ret; 345faa2dbf0SJosef Bacik 346b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); 347faa2dbf0SJosef Bacik if (ret) { 348442244c9SQu Wenruo ulist_free(old_roots); 349442244c9SQu Wenruo ulist_free(new_roots); 350442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 351faa2dbf0SJosef Bacik return ret; 352faa2dbf0SJosef Bacik } 353faa2dbf0SJosef Bacik 354b9ef22deSFeifei Xu ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, 355b9ef22deSFeifei Xu nodesize, old_roots, new_roots); 356faa2dbf0SJosef Bacik if (ret) { 357442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 358faa2dbf0SJosef Bacik return ret; 359faa2dbf0SJosef Bacik } 360faa2dbf0SJosef Bacik 361b9ef22deSFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, 5, 362b9ef22deSFeifei Xu nodesize, nodesize)) { 363faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 364faa2dbf0SJosef Bacik return -EINVAL; 365faa2dbf0SJosef Bacik } 366faa2dbf0SJosef Bacik 367b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); 368442244c9SQu Wenruo if (ret) { 369442244c9SQu Wenruo ulist_free(old_roots); 370442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 371442244c9SQu Wenruo return ret; 372442244c9SQu Wenruo } 373442244c9SQu Wenruo 374b9ef22deSFeifei Xu ret = add_tree_ref(root, nodesize, nodesize, 0, 256); 375faa2dbf0SJosef Bacik if (ret) 376faa2dbf0SJosef Bacik return ret; 377faa2dbf0SJosef Bacik 378b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); 379faa2dbf0SJosef Bacik if (ret) { 380442244c9SQu Wenruo ulist_free(old_roots); 381442244c9SQu Wenruo ulist_free(new_roots); 382442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 383faa2dbf0SJosef Bacik return ret; 384faa2dbf0SJosef Bacik } 385faa2dbf0SJosef Bacik 386b9ef22deSFeifei Xu ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, 387b9ef22deSFeifei Xu nodesize, old_roots, new_roots); 388faa2dbf0SJosef Bacik if (ret) { 389442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 390faa2dbf0SJosef Bacik return ret; 391faa2dbf0SJosef Bacik } 392faa2dbf0SJosef Bacik 393b9ef22deSFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, 0)) { 394faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 395faa2dbf0SJosef Bacik return -EINVAL; 396faa2dbf0SJosef Bacik } 397faa2dbf0SJosef Bacik 398b9ef22deSFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, 256, nodesize, 0)) { 399faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 400faa2dbf0SJosef Bacik return -EINVAL; 401faa2dbf0SJosef Bacik } 402faa2dbf0SJosef Bacik 403b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots); 404442244c9SQu Wenruo if (ret) { 405442244c9SQu Wenruo ulist_free(old_roots); 406442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 407442244c9SQu Wenruo return ret; 408442244c9SQu Wenruo } 409442244c9SQu Wenruo 410b9ef22deSFeifei Xu ret = remove_extent_ref(root, nodesize, nodesize, 0, 256); 411faa2dbf0SJosef Bacik if (ret) 412faa2dbf0SJosef Bacik return ret; 413faa2dbf0SJosef Bacik 414b9ef22deSFeifei Xu ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots); 415faa2dbf0SJosef Bacik if (ret) { 416442244c9SQu Wenruo ulist_free(old_roots); 417442244c9SQu Wenruo ulist_free(new_roots); 418442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 419faa2dbf0SJosef Bacik return ret; 420faa2dbf0SJosef Bacik } 421faa2dbf0SJosef Bacik 422b9ef22deSFeifei Xu ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize, 423b9ef22deSFeifei Xu nodesize, old_roots, new_roots); 424faa2dbf0SJosef Bacik if (ret) { 425442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 426faa2dbf0SJosef Bacik return ret; 427faa2dbf0SJosef Bacik } 428faa2dbf0SJosef Bacik 429faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) { 430faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 431faa2dbf0SJosef Bacik return -EINVAL; 432faa2dbf0SJosef Bacik } 433faa2dbf0SJosef Bacik 434b9ef22deSFeifei Xu if (btrfs_verify_qgroup_counts(fs_info, 5, nodesize, nodesize)) { 435faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 436faa2dbf0SJosef Bacik return -EINVAL; 437faa2dbf0SJosef Bacik } 438faa2dbf0SJosef Bacik 439faa2dbf0SJosef Bacik return 0; 440faa2dbf0SJosef Bacik } 441faa2dbf0SJosef Bacik 442b9ef22deSFeifei Xu int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) 443faa2dbf0SJosef Bacik { 444faa2dbf0SJosef Bacik struct btrfs_root *root; 445faa2dbf0SJosef Bacik struct btrfs_root *tmp_root; 446faa2dbf0SJosef Bacik int ret = 0; 447faa2dbf0SJosef Bacik 448b9ef22deSFeifei Xu root = btrfs_alloc_dummy_root(sectorsize, nodesize); 449faa2dbf0SJosef Bacik if (IS_ERR(root)) { 450faa2dbf0SJosef Bacik test_msg("Couldn't allocate root\n"); 451faa2dbf0SJosef Bacik return PTR_ERR(root); 452faa2dbf0SJosef Bacik } 453faa2dbf0SJosef Bacik 454faa2dbf0SJosef Bacik root->fs_info = btrfs_alloc_dummy_fs_info(); 455faa2dbf0SJosef Bacik if (!root->fs_info) { 456faa2dbf0SJosef Bacik test_msg("Couldn't allocate dummy fs info\n"); 457faa2dbf0SJosef Bacik ret = -ENOMEM; 458faa2dbf0SJosef Bacik goto out; 459faa2dbf0SJosef Bacik } 4603f556f78SDavid Sterba /* We are using this root as our extent root */ 4613f556f78SDavid Sterba root->fs_info->extent_root = root; 4623f556f78SDavid Sterba 4633f556f78SDavid Sterba /* 4643f556f78SDavid Sterba * Some of the paths we test assume we have a filled out fs_info, so we 4653f556f78SDavid Sterba * just need to add the root in there so we don't panic. 4663f556f78SDavid Sterba */ 4673f556f78SDavid Sterba root->fs_info->tree_root = root; 4683f556f78SDavid Sterba root->fs_info->quota_root = root; 4693f556f78SDavid Sterba root->fs_info->quota_enabled = 1; 470faa2dbf0SJosef Bacik 471faa2dbf0SJosef Bacik /* 472faa2dbf0SJosef Bacik * Can't use bytenr 0, some things freak out 473faa2dbf0SJosef Bacik * *cough*backref walking code*cough* 474faa2dbf0SJosef Bacik */ 475b9ef22deSFeifei Xu root->node = alloc_test_extent_buffer(root->fs_info, nodesize, 476b9ef22deSFeifei Xu nodesize); 477faa2dbf0SJosef Bacik if (!root->node) { 478faa2dbf0SJosef Bacik test_msg("Couldn't allocate dummy buffer\n"); 479faa2dbf0SJosef Bacik ret = -ENOMEM; 480faa2dbf0SJosef Bacik goto out; 481faa2dbf0SJosef Bacik } 482b050f9f6SFilipe Manana btrfs_set_header_level(root->node, 0); 483b050f9f6SFilipe Manana btrfs_set_header_nritems(root->node, 0); 484b9ef22deSFeifei Xu root->alloc_bytenr += 2 * nodesize; 485faa2dbf0SJosef Bacik 486b9ef22deSFeifei Xu tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize); 487faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 488faa2dbf0SJosef Bacik test_msg("Couldn't allocate a fs root\n"); 489faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 490faa2dbf0SJosef Bacik goto out; 491faa2dbf0SJosef Bacik } 492faa2dbf0SJosef Bacik 493faa2dbf0SJosef Bacik tmp_root->root_key.objectid = 5; 494faa2dbf0SJosef Bacik root->fs_info->fs_root = tmp_root; 495faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 496faa2dbf0SJosef Bacik if (ret) { 497faa2dbf0SJosef Bacik test_msg("Couldn't insert fs root %d\n", ret); 498faa2dbf0SJosef Bacik goto out; 499faa2dbf0SJosef Bacik } 500faa2dbf0SJosef Bacik 501b9ef22deSFeifei Xu tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize); 502faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 503faa2dbf0SJosef Bacik test_msg("Couldn't allocate a fs root\n"); 504faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 505faa2dbf0SJosef Bacik goto out; 506faa2dbf0SJosef Bacik } 507faa2dbf0SJosef Bacik 508faa2dbf0SJosef Bacik tmp_root->root_key.objectid = 256; 509faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 510faa2dbf0SJosef Bacik if (ret) { 511faa2dbf0SJosef Bacik test_msg("Couldn't insert fs root %d\n", ret); 512faa2dbf0SJosef Bacik goto out; 513faa2dbf0SJosef Bacik } 514faa2dbf0SJosef Bacik 515faa2dbf0SJosef Bacik test_msg("Running qgroup tests\n"); 516b9ef22deSFeifei Xu ret = test_no_shared_qgroup(root, sectorsize, nodesize); 517faa2dbf0SJosef Bacik if (ret) 518faa2dbf0SJosef Bacik goto out; 519b9ef22deSFeifei Xu ret = test_multiple_refs(root, sectorsize, nodesize); 520faa2dbf0SJosef Bacik out: 521faa2dbf0SJosef Bacik btrfs_free_dummy_root(root); 522faa2dbf0SJosef Bacik return ret; 523faa2dbf0SJosef Bacik } 524