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 19faa2dbf0SJosef Bacik #include "btrfs-tests.h" 20faa2dbf0SJosef Bacik #include "../ctree.h" 21faa2dbf0SJosef Bacik #include "../transaction.h" 22faa2dbf0SJosef Bacik #include "../disk-io.h" 23faa2dbf0SJosef Bacik #include "../qgroup.h" 24442244c9SQu Wenruo #include "../backref.h" 25faa2dbf0SJosef Bacik 26faa2dbf0SJosef Bacik static void init_dummy_trans(struct btrfs_trans_handle *trans) 27faa2dbf0SJosef Bacik { 28faa2dbf0SJosef Bacik memset(trans, 0, sizeof(*trans)); 29faa2dbf0SJosef Bacik trans->transid = 1; 30faa2dbf0SJosef Bacik INIT_LIST_HEAD(&trans->qgroup_ref_list); 31faa2dbf0SJosef Bacik trans->type = __TRANS_DUMMY; 32faa2dbf0SJosef Bacik } 33faa2dbf0SJosef Bacik 34faa2dbf0SJosef Bacik static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr, 35faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 36faa2dbf0SJosef Bacik { 37faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 38faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 39faa2dbf0SJosef Bacik struct btrfs_extent_inline_ref *iref; 40faa2dbf0SJosef Bacik struct btrfs_tree_block_info *block_info; 41faa2dbf0SJosef Bacik struct btrfs_path *path; 42faa2dbf0SJosef Bacik struct extent_buffer *leaf; 43faa2dbf0SJosef Bacik struct btrfs_key ins; 44faa2dbf0SJosef Bacik u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info); 45faa2dbf0SJosef Bacik int ret; 46faa2dbf0SJosef Bacik 47faa2dbf0SJosef Bacik init_dummy_trans(&trans); 48faa2dbf0SJosef Bacik 49faa2dbf0SJosef Bacik ins.objectid = bytenr; 50faa2dbf0SJosef Bacik ins.type = BTRFS_EXTENT_ITEM_KEY; 51faa2dbf0SJosef Bacik ins.offset = num_bytes; 52faa2dbf0SJosef Bacik 53faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 54faa2dbf0SJosef Bacik if (!path) { 55faa2dbf0SJosef Bacik test_msg("Couldn't allocate path\n"); 56faa2dbf0SJosef Bacik return -ENOMEM; 57faa2dbf0SJosef Bacik } 58faa2dbf0SJosef Bacik 59faa2dbf0SJosef Bacik path->leave_spinning = 1; 60faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &ins, size); 61faa2dbf0SJosef Bacik if (ret) { 62faa2dbf0SJosef Bacik test_msg("Couldn't insert ref %d\n", ret); 63faa2dbf0SJosef Bacik btrfs_free_path(path); 64faa2dbf0SJosef Bacik return ret; 65faa2dbf0SJosef Bacik } 66faa2dbf0SJosef Bacik 67faa2dbf0SJosef Bacik leaf = path->nodes[0]; 68faa2dbf0SJosef Bacik item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 69faa2dbf0SJosef Bacik btrfs_set_extent_refs(leaf, item, 1); 70faa2dbf0SJosef Bacik btrfs_set_extent_generation(leaf, item, 1); 71faa2dbf0SJosef Bacik btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); 72faa2dbf0SJosef Bacik block_info = (struct btrfs_tree_block_info *)(item + 1); 73faa2dbf0SJosef Bacik btrfs_set_tree_block_level(leaf, block_info, 1); 74faa2dbf0SJosef Bacik iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 75faa2dbf0SJosef Bacik if (parent > 0) { 76faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, 77faa2dbf0SJosef Bacik BTRFS_SHARED_BLOCK_REF_KEY); 78faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 79faa2dbf0SJosef Bacik } else { 80faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY); 81faa2dbf0SJosef Bacik btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 82faa2dbf0SJosef Bacik } 83faa2dbf0SJosef Bacik btrfs_free_path(path); 84faa2dbf0SJosef Bacik return 0; 85faa2dbf0SJosef Bacik } 86faa2dbf0SJosef Bacik 87faa2dbf0SJosef Bacik static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes, 88faa2dbf0SJosef Bacik u64 parent, u64 root_objectid) 89faa2dbf0SJosef Bacik { 90faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 91faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 92faa2dbf0SJosef Bacik struct btrfs_path *path; 93faa2dbf0SJosef Bacik struct btrfs_key key; 94faa2dbf0SJosef Bacik u64 refs; 95faa2dbf0SJosef Bacik int ret; 96faa2dbf0SJosef Bacik 97faa2dbf0SJosef Bacik init_dummy_trans(&trans); 98faa2dbf0SJosef Bacik 99faa2dbf0SJosef Bacik key.objectid = bytenr; 100faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 101faa2dbf0SJosef Bacik key.offset = num_bytes; 102faa2dbf0SJosef Bacik 103faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 104faa2dbf0SJosef Bacik if (!path) { 105faa2dbf0SJosef Bacik test_msg("Couldn't allocate path\n"); 106faa2dbf0SJosef Bacik return -ENOMEM; 107faa2dbf0SJosef Bacik } 108faa2dbf0SJosef Bacik 109faa2dbf0SJosef Bacik path->leave_spinning = 1; 110faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 111faa2dbf0SJosef Bacik if (ret) { 112faa2dbf0SJosef Bacik test_msg("Couldn't find extent ref\n"); 113faa2dbf0SJosef Bacik btrfs_free_path(path); 114faa2dbf0SJosef Bacik return ret; 115faa2dbf0SJosef Bacik } 116faa2dbf0SJosef Bacik 117faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 118faa2dbf0SJosef Bacik struct btrfs_extent_item); 119faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 120faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs + 1); 121faa2dbf0SJosef Bacik btrfs_release_path(path); 122faa2dbf0SJosef Bacik 123faa2dbf0SJosef Bacik key.objectid = bytenr; 124faa2dbf0SJosef Bacik if (parent) { 125faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 126faa2dbf0SJosef Bacik key.offset = parent; 127faa2dbf0SJosef Bacik } else { 128faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 129faa2dbf0SJosef Bacik key.offset = root_objectid; 130faa2dbf0SJosef Bacik } 131faa2dbf0SJosef Bacik 132faa2dbf0SJosef Bacik ret = btrfs_insert_empty_item(&trans, root, path, &key, 0); 133faa2dbf0SJosef Bacik if (ret) 134faa2dbf0SJosef Bacik test_msg("Failed to insert backref\n"); 135faa2dbf0SJosef Bacik btrfs_free_path(path); 136faa2dbf0SJosef Bacik return ret; 137faa2dbf0SJosef Bacik } 138faa2dbf0SJosef Bacik 139faa2dbf0SJosef Bacik static int remove_extent_item(struct btrfs_root *root, u64 bytenr, 140faa2dbf0SJosef Bacik u64 num_bytes) 141faa2dbf0SJosef Bacik { 142faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 143faa2dbf0SJosef Bacik struct btrfs_key key; 144faa2dbf0SJosef Bacik struct btrfs_path *path; 145faa2dbf0SJosef Bacik int ret; 146faa2dbf0SJosef Bacik 147faa2dbf0SJosef Bacik init_dummy_trans(&trans); 148faa2dbf0SJosef Bacik 149faa2dbf0SJosef Bacik key.objectid = bytenr; 150faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 151faa2dbf0SJosef Bacik key.offset = num_bytes; 152faa2dbf0SJosef Bacik 153faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 154faa2dbf0SJosef Bacik if (!path) { 155faa2dbf0SJosef Bacik test_msg("Couldn't allocate path\n"); 156faa2dbf0SJosef Bacik return -ENOMEM; 157faa2dbf0SJosef Bacik } 158faa2dbf0SJosef Bacik path->leave_spinning = 1; 159faa2dbf0SJosef Bacik 160faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 161faa2dbf0SJosef Bacik if (ret) { 162faa2dbf0SJosef Bacik test_msg("Didn't find our key %d\n", ret); 163faa2dbf0SJosef Bacik btrfs_free_path(path); 164faa2dbf0SJosef Bacik return ret; 165faa2dbf0SJosef Bacik } 166faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 167faa2dbf0SJosef Bacik btrfs_free_path(path); 168faa2dbf0SJosef Bacik return 0; 169faa2dbf0SJosef Bacik } 170faa2dbf0SJosef Bacik 171faa2dbf0SJosef Bacik static int remove_extent_ref(struct btrfs_root *root, u64 bytenr, 172faa2dbf0SJosef Bacik u64 num_bytes, u64 parent, u64 root_objectid) 173faa2dbf0SJosef Bacik { 174faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 175faa2dbf0SJosef Bacik struct btrfs_extent_item *item; 176faa2dbf0SJosef Bacik struct btrfs_path *path; 177faa2dbf0SJosef Bacik struct btrfs_key key; 178faa2dbf0SJosef Bacik u64 refs; 179faa2dbf0SJosef Bacik int ret; 180faa2dbf0SJosef Bacik 181faa2dbf0SJosef Bacik init_dummy_trans(&trans); 182faa2dbf0SJosef Bacik 183faa2dbf0SJosef Bacik key.objectid = bytenr; 184faa2dbf0SJosef Bacik key.type = BTRFS_EXTENT_ITEM_KEY; 185faa2dbf0SJosef Bacik key.offset = num_bytes; 186faa2dbf0SJosef Bacik 187faa2dbf0SJosef Bacik path = btrfs_alloc_path(); 188faa2dbf0SJosef Bacik if (!path) { 189faa2dbf0SJosef Bacik test_msg("Couldn't allocate path\n"); 190faa2dbf0SJosef Bacik return -ENOMEM; 191faa2dbf0SJosef Bacik } 192faa2dbf0SJosef Bacik 193faa2dbf0SJosef Bacik path->leave_spinning = 1; 194faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 195faa2dbf0SJosef Bacik if (ret) { 196faa2dbf0SJosef Bacik test_msg("Couldn't find extent ref\n"); 197faa2dbf0SJosef Bacik btrfs_free_path(path); 198faa2dbf0SJosef Bacik return ret; 199faa2dbf0SJosef Bacik } 200faa2dbf0SJosef Bacik 201faa2dbf0SJosef Bacik item = btrfs_item_ptr(path->nodes[0], path->slots[0], 202faa2dbf0SJosef Bacik struct btrfs_extent_item); 203faa2dbf0SJosef Bacik refs = btrfs_extent_refs(path->nodes[0], item); 204faa2dbf0SJosef Bacik btrfs_set_extent_refs(path->nodes[0], item, refs - 1); 205faa2dbf0SJosef Bacik btrfs_release_path(path); 206faa2dbf0SJosef Bacik 207faa2dbf0SJosef Bacik key.objectid = bytenr; 208faa2dbf0SJosef Bacik if (parent) { 209faa2dbf0SJosef Bacik key.type = BTRFS_SHARED_BLOCK_REF_KEY; 210faa2dbf0SJosef Bacik key.offset = parent; 211faa2dbf0SJosef Bacik } else { 212faa2dbf0SJosef Bacik key.type = BTRFS_TREE_BLOCK_REF_KEY; 213faa2dbf0SJosef Bacik key.offset = root_objectid; 214faa2dbf0SJosef Bacik } 215faa2dbf0SJosef Bacik 216faa2dbf0SJosef Bacik ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 217faa2dbf0SJosef Bacik if (ret) { 218faa2dbf0SJosef Bacik test_msg("Couldn't find backref %d\n", ret); 219faa2dbf0SJosef Bacik btrfs_free_path(path); 220faa2dbf0SJosef Bacik return ret; 221faa2dbf0SJosef Bacik } 222faa2dbf0SJosef Bacik btrfs_del_item(&trans, root, path); 223faa2dbf0SJosef Bacik btrfs_free_path(path); 224faa2dbf0SJosef Bacik return ret; 225faa2dbf0SJosef Bacik } 226faa2dbf0SJosef Bacik 227faa2dbf0SJosef Bacik static int test_no_shared_qgroup(struct btrfs_root *root) 228faa2dbf0SJosef Bacik { 229faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 230faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 231442244c9SQu Wenruo struct ulist *old_roots = NULL; 232442244c9SQu Wenruo struct ulist *new_roots = NULL; 233faa2dbf0SJosef Bacik int ret; 234faa2dbf0SJosef Bacik 235faa2dbf0SJosef Bacik init_dummy_trans(&trans); 236faa2dbf0SJosef Bacik 237faa2dbf0SJosef Bacik test_msg("Qgroup basic add\n"); 2384087cf24SDongsheng Yang ret = btrfs_create_qgroup(NULL, fs_info, 5); 239faa2dbf0SJosef Bacik if (ret) { 240faa2dbf0SJosef Bacik test_msg("Couldn't create a qgroup %d\n", ret); 241faa2dbf0SJosef Bacik return ret; 242faa2dbf0SJosef Bacik } 243faa2dbf0SJosef Bacik 244442244c9SQu Wenruo /* 245442244c9SQu Wenruo * Since the test trans doesn't havee the complicated delayed refs, 246442244c9SQu Wenruo * we can only call btrfs_qgroup_account_extent() directly to test 247442244c9SQu Wenruo * quota. 248442244c9SQu Wenruo */ 249442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); 250faa2dbf0SJosef Bacik if (ret) { 251442244c9SQu Wenruo ulist_free(old_roots); 252442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 253faa2dbf0SJosef Bacik return ret; 254faa2dbf0SJosef Bacik } 255faa2dbf0SJosef Bacik 256faa2dbf0SJosef Bacik ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5); 257faa2dbf0SJosef Bacik if (ret) 258faa2dbf0SJosef Bacik return ret; 259faa2dbf0SJosef Bacik 260442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); 261faa2dbf0SJosef Bacik if (ret) { 262442244c9SQu Wenruo ulist_free(old_roots); 263442244c9SQu Wenruo ulist_free(new_roots); 264442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 265442244c9SQu Wenruo return ret; 266442244c9SQu Wenruo } 267442244c9SQu Wenruo 268442244c9SQu Wenruo ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, 269442244c9SQu Wenruo old_roots, new_roots); 270442244c9SQu Wenruo if (ret) { 271442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 272faa2dbf0SJosef Bacik return ret; 273faa2dbf0SJosef Bacik } 274faa2dbf0SJosef Bacik 275faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { 276faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 277faa2dbf0SJosef Bacik return -EINVAL; 278faa2dbf0SJosef Bacik } 279442244c9SQu Wenruo old_roots = NULL; 280442244c9SQu Wenruo new_roots = NULL; 281442244c9SQu Wenruo 282442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); 283442244c9SQu Wenruo if (ret) { 284442244c9SQu Wenruo ulist_free(old_roots); 285442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 286442244c9SQu Wenruo return ret; 287442244c9SQu Wenruo } 288faa2dbf0SJosef Bacik 289faa2dbf0SJosef Bacik ret = remove_extent_item(root, 4096, 4096); 290faa2dbf0SJosef Bacik if (ret) 291faa2dbf0SJosef Bacik return -EINVAL; 292faa2dbf0SJosef Bacik 293442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); 294faa2dbf0SJosef Bacik if (ret) { 295442244c9SQu Wenruo ulist_free(old_roots); 296442244c9SQu Wenruo ulist_free(new_roots); 297442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 298442244c9SQu Wenruo return ret; 299faa2dbf0SJosef Bacik } 300faa2dbf0SJosef Bacik 301442244c9SQu Wenruo ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, 302442244c9SQu Wenruo old_roots, new_roots); 303faa2dbf0SJosef Bacik if (ret) { 304442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 305faa2dbf0SJosef Bacik return -EINVAL; 306faa2dbf0SJosef Bacik } 307faa2dbf0SJosef Bacik 308faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) { 309faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 310faa2dbf0SJosef Bacik return -EINVAL; 311faa2dbf0SJosef Bacik } 312faa2dbf0SJosef Bacik 313faa2dbf0SJosef Bacik return 0; 314faa2dbf0SJosef Bacik } 315faa2dbf0SJosef Bacik 316faa2dbf0SJosef Bacik /* 317faa2dbf0SJosef Bacik * Add a ref for two different roots to make sure the shared value comes out 318faa2dbf0SJosef Bacik * right, also remove one of the roots and make sure the exclusive count is 319faa2dbf0SJosef Bacik * adjusted properly. 320faa2dbf0SJosef Bacik */ 321faa2dbf0SJosef Bacik static int test_multiple_refs(struct btrfs_root *root) 322faa2dbf0SJosef Bacik { 323faa2dbf0SJosef Bacik struct btrfs_trans_handle trans; 324faa2dbf0SJosef Bacik struct btrfs_fs_info *fs_info = root->fs_info; 325442244c9SQu Wenruo struct ulist *old_roots = NULL; 326442244c9SQu Wenruo struct ulist *new_roots = NULL; 327faa2dbf0SJosef Bacik int ret; 328faa2dbf0SJosef Bacik 329faa2dbf0SJosef Bacik init_dummy_trans(&trans); 330faa2dbf0SJosef Bacik 331faa2dbf0SJosef Bacik test_msg("Qgroup multiple refs test\n"); 332faa2dbf0SJosef Bacik 333faa2dbf0SJosef Bacik /* We have 5 created already from the previous test */ 3344087cf24SDongsheng Yang ret = btrfs_create_qgroup(NULL, fs_info, 256); 335faa2dbf0SJosef Bacik if (ret) { 336faa2dbf0SJosef Bacik test_msg("Couldn't create a qgroup %d\n", ret); 337faa2dbf0SJosef Bacik return ret; 338faa2dbf0SJosef Bacik } 339faa2dbf0SJosef Bacik 340442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); 341442244c9SQu Wenruo if (ret) { 342442244c9SQu Wenruo ulist_free(old_roots); 343442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 344442244c9SQu Wenruo return ret; 345442244c9SQu Wenruo } 346442244c9SQu Wenruo 347faa2dbf0SJosef Bacik ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5); 348faa2dbf0SJosef Bacik if (ret) 349faa2dbf0SJosef Bacik return ret; 350faa2dbf0SJosef Bacik 351442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); 352faa2dbf0SJosef Bacik if (ret) { 353442244c9SQu Wenruo ulist_free(old_roots); 354442244c9SQu Wenruo ulist_free(new_roots); 355442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 356faa2dbf0SJosef Bacik return ret; 357faa2dbf0SJosef Bacik } 358faa2dbf0SJosef Bacik 359442244c9SQu Wenruo ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, 360442244c9SQu Wenruo old_roots, new_roots); 361faa2dbf0SJosef Bacik if (ret) { 362442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 363faa2dbf0SJosef Bacik return ret; 364faa2dbf0SJosef Bacik } 365faa2dbf0SJosef Bacik 366faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { 367faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 368faa2dbf0SJosef Bacik return -EINVAL; 369faa2dbf0SJosef Bacik } 370faa2dbf0SJosef Bacik 371442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); 372442244c9SQu Wenruo if (ret) { 373442244c9SQu Wenruo ulist_free(old_roots); 374442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 375442244c9SQu Wenruo return ret; 376442244c9SQu Wenruo } 377442244c9SQu Wenruo 378faa2dbf0SJosef Bacik ret = add_tree_ref(root, 4096, 4096, 0, 256); 379faa2dbf0SJosef Bacik if (ret) 380faa2dbf0SJosef Bacik return ret; 381faa2dbf0SJosef Bacik 382442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); 383faa2dbf0SJosef Bacik if (ret) { 384442244c9SQu Wenruo ulist_free(old_roots); 385442244c9SQu Wenruo ulist_free(new_roots); 386442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 387faa2dbf0SJosef Bacik return ret; 388faa2dbf0SJosef Bacik } 389faa2dbf0SJosef Bacik 390442244c9SQu Wenruo ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, 391442244c9SQu Wenruo old_roots, new_roots); 392faa2dbf0SJosef Bacik if (ret) { 393442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 394faa2dbf0SJosef Bacik return ret; 395faa2dbf0SJosef Bacik } 396faa2dbf0SJosef Bacik 397faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 0)) { 398faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 399faa2dbf0SJosef Bacik return -EINVAL; 400faa2dbf0SJosef Bacik } 401faa2dbf0SJosef Bacik 402faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 256, 4096, 0)) { 403faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 404faa2dbf0SJosef Bacik return -EINVAL; 405faa2dbf0SJosef Bacik } 406faa2dbf0SJosef Bacik 407442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots); 408442244c9SQu Wenruo if (ret) { 409442244c9SQu Wenruo ulist_free(old_roots); 410442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 411442244c9SQu Wenruo return ret; 412442244c9SQu Wenruo } 413442244c9SQu Wenruo 414faa2dbf0SJosef Bacik ret = remove_extent_ref(root, 4096, 4096, 0, 256); 415faa2dbf0SJosef Bacik if (ret) 416faa2dbf0SJosef Bacik return ret; 417faa2dbf0SJosef Bacik 418442244c9SQu Wenruo ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots); 419faa2dbf0SJosef Bacik if (ret) { 420442244c9SQu Wenruo ulist_free(old_roots); 421442244c9SQu Wenruo ulist_free(new_roots); 422442244c9SQu Wenruo test_msg("Couldn't find old roots: %d\n", ret); 423faa2dbf0SJosef Bacik return ret; 424faa2dbf0SJosef Bacik } 425faa2dbf0SJosef Bacik 426442244c9SQu Wenruo ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096, 427442244c9SQu Wenruo old_roots, new_roots); 428faa2dbf0SJosef Bacik if (ret) { 429442244c9SQu Wenruo test_msg("Couldn't account space for a qgroup %d\n", ret); 430faa2dbf0SJosef Bacik return ret; 431faa2dbf0SJosef Bacik } 432faa2dbf0SJosef Bacik 433faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) { 434faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 435faa2dbf0SJosef Bacik return -EINVAL; 436faa2dbf0SJosef Bacik } 437faa2dbf0SJosef Bacik 438faa2dbf0SJosef Bacik if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) { 439faa2dbf0SJosef Bacik test_msg("Qgroup counts didn't match expected values\n"); 440faa2dbf0SJosef Bacik return -EINVAL; 441faa2dbf0SJosef Bacik } 442faa2dbf0SJosef Bacik 443faa2dbf0SJosef Bacik return 0; 444faa2dbf0SJosef Bacik } 445faa2dbf0SJosef Bacik 446faa2dbf0SJosef Bacik int btrfs_test_qgroups(void) 447faa2dbf0SJosef Bacik { 448faa2dbf0SJosef Bacik struct btrfs_root *root; 449faa2dbf0SJosef Bacik struct btrfs_root *tmp_root; 450faa2dbf0SJosef Bacik int ret = 0; 451faa2dbf0SJosef Bacik 452faa2dbf0SJosef Bacik root = btrfs_alloc_dummy_root(); 453faa2dbf0SJosef Bacik if (IS_ERR(root)) { 454faa2dbf0SJosef Bacik test_msg("Couldn't allocate root\n"); 455faa2dbf0SJosef Bacik return PTR_ERR(root); 456faa2dbf0SJosef Bacik } 457faa2dbf0SJosef Bacik 458faa2dbf0SJosef Bacik root->fs_info = btrfs_alloc_dummy_fs_info(); 459faa2dbf0SJosef Bacik if (!root->fs_info) { 460faa2dbf0SJosef Bacik test_msg("Couldn't allocate dummy fs info\n"); 461faa2dbf0SJosef Bacik ret = -ENOMEM; 462faa2dbf0SJosef Bacik goto out; 463faa2dbf0SJosef Bacik } 4643f556f78SDavid Sterba /* We are using this root as our extent root */ 4653f556f78SDavid Sterba root->fs_info->extent_root = 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; 4733f556f78SDavid Sterba root->fs_info->quota_enabled = 1; 474faa2dbf0SJosef Bacik 475faa2dbf0SJosef Bacik /* 476faa2dbf0SJosef Bacik * Can't use bytenr 0, some things freak out 477faa2dbf0SJosef Bacik * *cough*backref walking code*cough* 478faa2dbf0SJosef Bacik */ 479ce3e6984SDavid Sterba root->node = alloc_test_extent_buffer(root->fs_info, 4096); 480faa2dbf0SJosef Bacik if (!root->node) { 481faa2dbf0SJosef Bacik test_msg("Couldn't allocate dummy buffer\n"); 482faa2dbf0SJosef Bacik ret = -ENOMEM; 483faa2dbf0SJosef Bacik goto out; 484faa2dbf0SJosef Bacik } 485b050f9f6SFilipe Manana btrfs_set_header_level(root->node, 0); 486b050f9f6SFilipe Manana btrfs_set_header_nritems(root->node, 0); 487faa2dbf0SJosef Bacik root->alloc_bytenr += 8192; 488faa2dbf0SJosef Bacik 489faa2dbf0SJosef Bacik tmp_root = btrfs_alloc_dummy_root(); 490faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 491faa2dbf0SJosef Bacik test_msg("Couldn't allocate a fs root\n"); 492faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 493faa2dbf0SJosef Bacik goto out; 494faa2dbf0SJosef Bacik } 495faa2dbf0SJosef Bacik 496faa2dbf0SJosef Bacik tmp_root->root_key.objectid = 5; 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) { 500faa2dbf0SJosef Bacik test_msg("Couldn't insert fs root %d\n", ret); 501faa2dbf0SJosef Bacik goto out; 502faa2dbf0SJosef Bacik } 503faa2dbf0SJosef Bacik 504faa2dbf0SJosef Bacik tmp_root = btrfs_alloc_dummy_root(); 505faa2dbf0SJosef Bacik if (IS_ERR(tmp_root)) { 506faa2dbf0SJosef Bacik test_msg("Couldn't allocate a fs root\n"); 507faa2dbf0SJosef Bacik ret = PTR_ERR(tmp_root); 508faa2dbf0SJosef Bacik goto out; 509faa2dbf0SJosef Bacik } 510faa2dbf0SJosef Bacik 511faa2dbf0SJosef Bacik tmp_root->root_key.objectid = 256; 512faa2dbf0SJosef Bacik ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 513faa2dbf0SJosef Bacik if (ret) { 514faa2dbf0SJosef Bacik test_msg("Couldn't insert fs root %d\n", ret); 515faa2dbf0SJosef Bacik goto out; 516faa2dbf0SJosef Bacik } 517faa2dbf0SJosef Bacik 518faa2dbf0SJosef Bacik test_msg("Running qgroup tests\n"); 519faa2dbf0SJosef Bacik ret = test_no_shared_qgroup(root); 520faa2dbf0SJosef Bacik if (ret) 521faa2dbf0SJosef Bacik goto out; 522faa2dbf0SJosef Bacik ret = test_multiple_refs(root); 523faa2dbf0SJosef Bacik out: 524faa2dbf0SJosef Bacik btrfs_free_dummy_root(root); 525faa2dbf0SJosef Bacik return ret; 526faa2dbf0SJosef Bacik } 527