18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013 Facebook. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/types.h> 78c2ecf20Sopenharmony_ci#include "btrfs-tests.h" 88c2ecf20Sopenharmony_ci#include "../ctree.h" 98c2ecf20Sopenharmony_ci#include "../transaction.h" 108c2ecf20Sopenharmony_ci#include "../disk-io.h" 118c2ecf20Sopenharmony_ci#include "../qgroup.h" 128c2ecf20Sopenharmony_ci#include "../backref.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr, 158c2ecf20Sopenharmony_ci u64 num_bytes, u64 parent, u64 root_objectid) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 188c2ecf20Sopenharmony_ci struct btrfs_extent_item *item; 198c2ecf20Sopenharmony_ci struct btrfs_extent_inline_ref *iref; 208c2ecf20Sopenharmony_ci struct btrfs_tree_block_info *block_info; 218c2ecf20Sopenharmony_ci struct btrfs_path *path; 228c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 238c2ecf20Sopenharmony_ci struct btrfs_key ins; 248c2ecf20Sopenharmony_ci u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info); 258c2ecf20Sopenharmony_ci int ret; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, NULL); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci ins.objectid = bytenr; 308c2ecf20Sopenharmony_ci ins.type = BTRFS_EXTENT_ITEM_KEY; 318c2ecf20Sopenharmony_ci ins.offset = num_bytes; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 348c2ecf20Sopenharmony_ci if (!path) { 358c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 368c2ecf20Sopenharmony_ci return -ENOMEM; 378c2ecf20Sopenharmony_ci } 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci path->leave_spinning = 1; 408c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(&trans, root, path, &ins, size); 418c2ecf20Sopenharmony_ci if (ret) { 428c2ecf20Sopenharmony_ci test_err("couldn't insert ref %d", ret); 438c2ecf20Sopenharmony_ci btrfs_free_path(path); 448c2ecf20Sopenharmony_ci return ret; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 488c2ecf20Sopenharmony_ci item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); 498c2ecf20Sopenharmony_ci btrfs_set_extent_refs(leaf, item, 1); 508c2ecf20Sopenharmony_ci btrfs_set_extent_generation(leaf, item, 1); 518c2ecf20Sopenharmony_ci btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); 528c2ecf20Sopenharmony_ci block_info = (struct btrfs_tree_block_info *)(item + 1); 538c2ecf20Sopenharmony_ci btrfs_set_tree_block_level(leaf, block_info, 0); 548c2ecf20Sopenharmony_ci iref = (struct btrfs_extent_inline_ref *)(block_info + 1); 558c2ecf20Sopenharmony_ci if (parent > 0) { 568c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, 578c2ecf20Sopenharmony_ci BTRFS_SHARED_BLOCK_REF_KEY); 588c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, parent); 598c2ecf20Sopenharmony_ci } else { 608c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY); 618c2ecf20Sopenharmony_ci btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid); 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci btrfs_free_path(path); 648c2ecf20Sopenharmony_ci return 0; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes, 688c2ecf20Sopenharmony_ci u64 parent, u64 root_objectid) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 718c2ecf20Sopenharmony_ci struct btrfs_extent_item *item; 728c2ecf20Sopenharmony_ci struct btrfs_path *path; 738c2ecf20Sopenharmony_ci struct btrfs_key key; 748c2ecf20Sopenharmony_ci u64 refs; 758c2ecf20Sopenharmony_ci int ret; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, NULL); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci key.objectid = bytenr; 808c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 818c2ecf20Sopenharmony_ci key.offset = num_bytes; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 848c2ecf20Sopenharmony_ci if (!path) { 858c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 868c2ecf20Sopenharmony_ci return -ENOMEM; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci path->leave_spinning = 1; 908c2ecf20Sopenharmony_ci ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 918c2ecf20Sopenharmony_ci if (ret) { 928c2ecf20Sopenharmony_ci test_err("couldn't find extent ref"); 938c2ecf20Sopenharmony_ci btrfs_free_path(path); 948c2ecf20Sopenharmony_ci return ret; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci item = btrfs_item_ptr(path->nodes[0], path->slots[0], 988c2ecf20Sopenharmony_ci struct btrfs_extent_item); 998c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(path->nodes[0], item); 1008c2ecf20Sopenharmony_ci btrfs_set_extent_refs(path->nodes[0], item, refs + 1); 1018c2ecf20Sopenharmony_ci btrfs_release_path(path); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci key.objectid = bytenr; 1048c2ecf20Sopenharmony_ci if (parent) { 1058c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_BLOCK_REF_KEY; 1068c2ecf20Sopenharmony_ci key.offset = parent; 1078c2ecf20Sopenharmony_ci } else { 1088c2ecf20Sopenharmony_ci key.type = BTRFS_TREE_BLOCK_REF_KEY; 1098c2ecf20Sopenharmony_ci key.offset = root_objectid; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ret = btrfs_insert_empty_item(&trans, root, path, &key, 0); 1138c2ecf20Sopenharmony_ci if (ret) 1148c2ecf20Sopenharmony_ci test_err("failed to insert backref"); 1158c2ecf20Sopenharmony_ci btrfs_free_path(path); 1168c2ecf20Sopenharmony_ci return ret; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int remove_extent_item(struct btrfs_root *root, u64 bytenr, 1208c2ecf20Sopenharmony_ci u64 num_bytes) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 1238c2ecf20Sopenharmony_ci struct btrfs_key key; 1248c2ecf20Sopenharmony_ci struct btrfs_path *path; 1258c2ecf20Sopenharmony_ci int ret; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, NULL); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci key.objectid = bytenr; 1308c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 1318c2ecf20Sopenharmony_ci key.offset = num_bytes; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 1348c2ecf20Sopenharmony_ci if (!path) { 1358c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 1368c2ecf20Sopenharmony_ci return -ENOMEM; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci path->leave_spinning = 1; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 1418c2ecf20Sopenharmony_ci if (ret) { 1428c2ecf20Sopenharmony_ci test_err("didn't find our key %d", ret); 1438c2ecf20Sopenharmony_ci btrfs_free_path(path); 1448c2ecf20Sopenharmony_ci return ret; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci btrfs_del_item(&trans, root, path); 1478c2ecf20Sopenharmony_ci btrfs_free_path(path); 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int remove_extent_ref(struct btrfs_root *root, u64 bytenr, 1528c2ecf20Sopenharmony_ci u64 num_bytes, u64 parent, u64 root_objectid) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 1558c2ecf20Sopenharmony_ci struct btrfs_extent_item *item; 1568c2ecf20Sopenharmony_ci struct btrfs_path *path; 1578c2ecf20Sopenharmony_ci struct btrfs_key key; 1588c2ecf20Sopenharmony_ci u64 refs; 1598c2ecf20Sopenharmony_ci int ret; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, NULL); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci key.objectid = bytenr; 1648c2ecf20Sopenharmony_ci key.type = BTRFS_EXTENT_ITEM_KEY; 1658c2ecf20Sopenharmony_ci key.offset = num_bytes; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 1688c2ecf20Sopenharmony_ci if (!path) { 1698c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 1708c2ecf20Sopenharmony_ci return -ENOMEM; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci path->leave_spinning = 1; 1748c2ecf20Sopenharmony_ci ret = btrfs_search_slot(&trans, root, &key, path, 0, 1); 1758c2ecf20Sopenharmony_ci if (ret) { 1768c2ecf20Sopenharmony_ci test_err("couldn't find extent ref"); 1778c2ecf20Sopenharmony_ci btrfs_free_path(path); 1788c2ecf20Sopenharmony_ci return ret; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci item = btrfs_item_ptr(path->nodes[0], path->slots[0], 1828c2ecf20Sopenharmony_ci struct btrfs_extent_item); 1838c2ecf20Sopenharmony_ci refs = btrfs_extent_refs(path->nodes[0], item); 1848c2ecf20Sopenharmony_ci btrfs_set_extent_refs(path->nodes[0], item, refs - 1); 1858c2ecf20Sopenharmony_ci btrfs_release_path(path); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci key.objectid = bytenr; 1888c2ecf20Sopenharmony_ci if (parent) { 1898c2ecf20Sopenharmony_ci key.type = BTRFS_SHARED_BLOCK_REF_KEY; 1908c2ecf20Sopenharmony_ci key.offset = parent; 1918c2ecf20Sopenharmony_ci } else { 1928c2ecf20Sopenharmony_ci key.type = BTRFS_TREE_BLOCK_REF_KEY; 1938c2ecf20Sopenharmony_ci key.offset = root_objectid; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci ret = btrfs_search_slot(&trans, root, &key, path, -1, 1); 1978c2ecf20Sopenharmony_ci if (ret) { 1988c2ecf20Sopenharmony_ci test_err("couldn't find backref %d", ret); 1998c2ecf20Sopenharmony_ci btrfs_free_path(path); 2008c2ecf20Sopenharmony_ci return ret; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci btrfs_del_item(&trans, root, path); 2038c2ecf20Sopenharmony_ci btrfs_free_path(path); 2048c2ecf20Sopenharmony_ci return ret; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic int test_no_shared_qgroup(struct btrfs_root *root, 2088c2ecf20Sopenharmony_ci u32 sectorsize, u32 nodesize) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 2118c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 2128c2ecf20Sopenharmony_ci struct ulist *old_roots = NULL; 2138c2ecf20Sopenharmony_ci struct ulist *new_roots = NULL; 2148c2ecf20Sopenharmony_ci int ret; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, fs_info); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci test_msg("running qgroup add/remove tests"); 2198c2ecf20Sopenharmony_ci ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID); 2208c2ecf20Sopenharmony_ci if (ret) { 2218c2ecf20Sopenharmony_ci test_err("couldn't create a qgroup %d", ret); 2228c2ecf20Sopenharmony_ci return ret; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* 2268c2ecf20Sopenharmony_ci * Since the test trans doesn't have the complicated delayed refs, 2278c2ecf20Sopenharmony_ci * we can only call btrfs_qgroup_account_extent() directly to test 2288c2ecf20Sopenharmony_ci * quota. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 2318c2ecf20Sopenharmony_ci false); 2328c2ecf20Sopenharmony_ci if (ret) { 2338c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 2348c2ecf20Sopenharmony_ci return ret; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 2388c2ecf20Sopenharmony_ci BTRFS_FS_TREE_OBJECTID); 2398c2ecf20Sopenharmony_ci if (ret) { 2408c2ecf20Sopenharmony_ci ulist_free(old_roots); 2418c2ecf20Sopenharmony_ci return ret; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 2458c2ecf20Sopenharmony_ci false); 2468c2ecf20Sopenharmony_ci if (ret) { 2478c2ecf20Sopenharmony_ci ulist_free(old_roots); 2488c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 2498c2ecf20Sopenharmony_ci return ret; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2538c2ecf20Sopenharmony_ci new_roots); 2548c2ecf20Sopenharmony_ci if (ret) { 2558c2ecf20Sopenharmony_ci test_err("couldn't account space for a qgroup %d", ret); 2568c2ecf20Sopenharmony_ci return ret; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* btrfs_qgroup_account_extent() always frees the ulists passed to it. */ 2608c2ecf20Sopenharmony_ci old_roots = NULL; 2618c2ecf20Sopenharmony_ci new_roots = NULL; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 2648c2ecf20Sopenharmony_ci nodesize, nodesize)) { 2658c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 2668c2ecf20Sopenharmony_ci return -EINVAL; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 2708c2ecf20Sopenharmony_ci false); 2718c2ecf20Sopenharmony_ci if (ret) { 2728c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 2738c2ecf20Sopenharmony_ci return ret; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci ret = remove_extent_item(root, nodesize, nodesize); 2778c2ecf20Sopenharmony_ci if (ret) { 2788c2ecf20Sopenharmony_ci ulist_free(old_roots); 2798c2ecf20Sopenharmony_ci return -EINVAL; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 2838c2ecf20Sopenharmony_ci false); 2848c2ecf20Sopenharmony_ci if (ret) { 2858c2ecf20Sopenharmony_ci ulist_free(old_roots); 2868c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 2878c2ecf20Sopenharmony_ci return ret; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 2918c2ecf20Sopenharmony_ci new_roots); 2928c2ecf20Sopenharmony_ci if (ret) { 2938c2ecf20Sopenharmony_ci test_err("couldn't account space for a qgroup %d", ret); 2948c2ecf20Sopenharmony_ci return -EINVAL; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) { 2988c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 2998c2ecf20Sopenharmony_ci return -EINVAL; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci/* 3068c2ecf20Sopenharmony_ci * Add a ref for two different roots to make sure the shared value comes out 3078c2ecf20Sopenharmony_ci * right, also remove one of the roots and make sure the exclusive count is 3088c2ecf20Sopenharmony_ci * adjusted properly. 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_cistatic int test_multiple_refs(struct btrfs_root *root, 3118c2ecf20Sopenharmony_ci u32 sectorsize, u32 nodesize) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct btrfs_trans_handle trans; 3148c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 3158c2ecf20Sopenharmony_ci struct ulist *old_roots = NULL; 3168c2ecf20Sopenharmony_ci struct ulist *new_roots = NULL; 3178c2ecf20Sopenharmony_ci int ret; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci btrfs_init_dummy_trans(&trans, fs_info); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci test_msg("running qgroup multiple refs test"); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* 3248c2ecf20Sopenharmony_ci * We have BTRFS_FS_TREE_OBJECTID created already from the 3258c2ecf20Sopenharmony_ci * previous test. 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_ci ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID); 3288c2ecf20Sopenharmony_ci if (ret) { 3298c2ecf20Sopenharmony_ci test_err("couldn't create a qgroup %d", ret); 3308c2ecf20Sopenharmony_ci return ret; 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 3348c2ecf20Sopenharmony_ci false); 3358c2ecf20Sopenharmony_ci if (ret) { 3368c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 3378c2ecf20Sopenharmony_ci return ret; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci ret = insert_normal_tree_ref(root, nodesize, nodesize, 0, 3418c2ecf20Sopenharmony_ci BTRFS_FS_TREE_OBJECTID); 3428c2ecf20Sopenharmony_ci if (ret) { 3438c2ecf20Sopenharmony_ci ulist_free(old_roots); 3448c2ecf20Sopenharmony_ci return ret; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 3488c2ecf20Sopenharmony_ci false); 3498c2ecf20Sopenharmony_ci if (ret) { 3508c2ecf20Sopenharmony_ci ulist_free(old_roots); 3518c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 3528c2ecf20Sopenharmony_ci return ret; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3568c2ecf20Sopenharmony_ci new_roots); 3578c2ecf20Sopenharmony_ci if (ret) { 3588c2ecf20Sopenharmony_ci test_err("couldn't account space for a qgroup %d", ret); 3598c2ecf20Sopenharmony_ci return ret; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 3638c2ecf20Sopenharmony_ci nodesize, nodesize)) { 3648c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 3658c2ecf20Sopenharmony_ci return -EINVAL; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 3698c2ecf20Sopenharmony_ci false); 3708c2ecf20Sopenharmony_ci if (ret) { 3718c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 3728c2ecf20Sopenharmony_ci return ret; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci ret = add_tree_ref(root, nodesize, nodesize, 0, 3768c2ecf20Sopenharmony_ci BTRFS_FIRST_FREE_OBJECTID); 3778c2ecf20Sopenharmony_ci if (ret) { 3788c2ecf20Sopenharmony_ci ulist_free(old_roots); 3798c2ecf20Sopenharmony_ci return ret; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 3838c2ecf20Sopenharmony_ci false); 3848c2ecf20Sopenharmony_ci if (ret) { 3858c2ecf20Sopenharmony_ci ulist_free(old_roots); 3868c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 3878c2ecf20Sopenharmony_ci return ret; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 3918c2ecf20Sopenharmony_ci new_roots); 3928c2ecf20Sopenharmony_ci if (ret) { 3938c2ecf20Sopenharmony_ci test_err("couldn't account space for a qgroup %d", ret); 3948c2ecf20Sopenharmony_ci return ret; 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 3988c2ecf20Sopenharmony_ci nodesize, 0)) { 3998c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 4008c2ecf20Sopenharmony_ci return -EINVAL; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 4048c2ecf20Sopenharmony_ci nodesize, 0)) { 4058c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 4068c2ecf20Sopenharmony_ci return -EINVAL; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, 4108c2ecf20Sopenharmony_ci false); 4118c2ecf20Sopenharmony_ci if (ret) { 4128c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 4138c2ecf20Sopenharmony_ci return ret; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci ret = remove_extent_ref(root, nodesize, nodesize, 0, 4178c2ecf20Sopenharmony_ci BTRFS_FIRST_FREE_OBJECTID); 4188c2ecf20Sopenharmony_ci if (ret) { 4198c2ecf20Sopenharmony_ci ulist_free(old_roots); 4208c2ecf20Sopenharmony_ci return ret; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, 4248c2ecf20Sopenharmony_ci false); 4258c2ecf20Sopenharmony_ci if (ret) { 4268c2ecf20Sopenharmony_ci ulist_free(old_roots); 4278c2ecf20Sopenharmony_ci test_err("couldn't find old roots: %d", ret); 4288c2ecf20Sopenharmony_ci return ret; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots, 4328c2ecf20Sopenharmony_ci new_roots); 4338c2ecf20Sopenharmony_ci if (ret) { 4348c2ecf20Sopenharmony_ci test_err("couldn't account space for a qgroup %d", ret); 4358c2ecf20Sopenharmony_ci return ret; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID, 4398c2ecf20Sopenharmony_ci 0, 0)) { 4408c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 4418c2ecf20Sopenharmony_ci return -EINVAL; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 4458c2ecf20Sopenharmony_ci nodesize, nodesize)) { 4468c2ecf20Sopenharmony_ci test_err("qgroup counts didn't match expected values"); 4478c2ecf20Sopenharmony_ci return -EINVAL; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci return 0; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ciint btrfs_test_qgroups(u32 sectorsize, u32 nodesize) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = NULL; 4568c2ecf20Sopenharmony_ci struct btrfs_root *root; 4578c2ecf20Sopenharmony_ci struct btrfs_root *tmp_root; 4588c2ecf20Sopenharmony_ci int ret = 0; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize); 4618c2ecf20Sopenharmony_ci if (!fs_info) { 4628c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_FS_INFO); 4638c2ecf20Sopenharmony_ci return -ENOMEM; 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci root = btrfs_alloc_dummy_root(fs_info); 4678c2ecf20Sopenharmony_ci if (IS_ERR(root)) { 4688c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 4698c2ecf20Sopenharmony_ci ret = PTR_ERR(root); 4708c2ecf20Sopenharmony_ci goto out; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* We are using this root as our extent root */ 4748c2ecf20Sopenharmony_ci root->fs_info->extent_root = root; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci /* 4778c2ecf20Sopenharmony_ci * Some of the paths we test assume we have a filled out fs_info, so we 4788c2ecf20Sopenharmony_ci * just need to add the root in there so we don't panic. 4798c2ecf20Sopenharmony_ci */ 4808c2ecf20Sopenharmony_ci root->fs_info->tree_root = root; 4818c2ecf20Sopenharmony_ci root->fs_info->quota_root = root; 4828c2ecf20Sopenharmony_ci set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci /* 4858c2ecf20Sopenharmony_ci * Can't use bytenr 0, some things freak out 4868c2ecf20Sopenharmony_ci * *cough*backref walking code*cough* 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_ci root->node = alloc_test_extent_buffer(root->fs_info, nodesize); 4898c2ecf20Sopenharmony_ci if (IS_ERR(root->node)) { 4908c2ecf20Sopenharmony_ci test_err("couldn't allocate dummy buffer"); 4918c2ecf20Sopenharmony_ci ret = PTR_ERR(root->node); 4928c2ecf20Sopenharmony_ci goto out; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci btrfs_set_header_level(root->node, 0); 4958c2ecf20Sopenharmony_ci btrfs_set_header_nritems(root->node, 0); 4968c2ecf20Sopenharmony_ci root->alloc_bytenr += 2 * nodesize; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci tmp_root = btrfs_alloc_dummy_root(fs_info); 4998c2ecf20Sopenharmony_ci if (IS_ERR(tmp_root)) { 5008c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 5018c2ecf20Sopenharmony_ci ret = PTR_ERR(tmp_root); 5028c2ecf20Sopenharmony_ci goto out; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID; 5068c2ecf20Sopenharmony_ci root->fs_info->fs_root = tmp_root; 5078c2ecf20Sopenharmony_ci ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 5088c2ecf20Sopenharmony_ci if (ret) { 5098c2ecf20Sopenharmony_ci test_err("couldn't insert fs root %d", ret); 5108c2ecf20Sopenharmony_ci goto out; 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci btrfs_put_root(tmp_root); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci tmp_root = btrfs_alloc_dummy_root(fs_info); 5158c2ecf20Sopenharmony_ci if (IS_ERR(tmp_root)) { 5168c2ecf20Sopenharmony_ci test_std_err(TEST_ALLOC_ROOT); 5178c2ecf20Sopenharmony_ci ret = PTR_ERR(tmp_root); 5188c2ecf20Sopenharmony_ci goto out; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID; 5228c2ecf20Sopenharmony_ci ret = btrfs_insert_fs_root(root->fs_info, tmp_root); 5238c2ecf20Sopenharmony_ci if (ret) { 5248c2ecf20Sopenharmony_ci test_err("couldn't insert fs root %d", ret); 5258c2ecf20Sopenharmony_ci goto out; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci btrfs_put_root(tmp_root); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci test_msg("running qgroup tests"); 5308c2ecf20Sopenharmony_ci ret = test_no_shared_qgroup(root, sectorsize, nodesize); 5318c2ecf20Sopenharmony_ci if (ret) 5328c2ecf20Sopenharmony_ci goto out; 5338c2ecf20Sopenharmony_ci ret = test_multiple_refs(root, sectorsize, nodesize); 5348c2ecf20Sopenharmony_ciout: 5358c2ecf20Sopenharmony_ci btrfs_free_dummy_root(root); 5368c2ecf20Sopenharmony_ci btrfs_free_dummy_fs_info(fs_info); 5378c2ecf20Sopenharmony_ci return ret; 5388c2ecf20Sopenharmony_ci} 539