1*7c55ee0cSOmar Sandoval /* 2*7c55ee0cSOmar Sandoval * Copyright (C) 2015 Facebook. All rights reserved. 3*7c55ee0cSOmar Sandoval * 4*7c55ee0cSOmar Sandoval * This program is free software; you can redistribute it and/or 5*7c55ee0cSOmar Sandoval * modify it under the terms of the GNU General Public 6*7c55ee0cSOmar Sandoval * License v2 as published by the Free Software Foundation. 7*7c55ee0cSOmar Sandoval * 8*7c55ee0cSOmar Sandoval * This program is distributed in the hope that it will be useful, 9*7c55ee0cSOmar Sandoval * but WITHOUT ANY WARRANTY; without even the implied warranty of 10*7c55ee0cSOmar Sandoval * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11*7c55ee0cSOmar Sandoval * General Public License for more details. 12*7c55ee0cSOmar Sandoval * 13*7c55ee0cSOmar Sandoval * You should have received a copy of the GNU General Public 14*7c55ee0cSOmar Sandoval * License along with this program; if not, write to the 15*7c55ee0cSOmar Sandoval * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16*7c55ee0cSOmar Sandoval * Boston, MA 021110-1307, USA. 17*7c55ee0cSOmar Sandoval */ 18*7c55ee0cSOmar Sandoval 19*7c55ee0cSOmar Sandoval #include "btrfs-tests.h" 20*7c55ee0cSOmar Sandoval #include "../ctree.h" 21*7c55ee0cSOmar Sandoval #include "../disk-io.h" 22*7c55ee0cSOmar Sandoval #include "../free-space-tree.h" 23*7c55ee0cSOmar Sandoval #include "../transaction.h" 24*7c55ee0cSOmar Sandoval 25*7c55ee0cSOmar Sandoval struct free_space_extent { 26*7c55ee0cSOmar Sandoval u64 start, length; 27*7c55ee0cSOmar Sandoval }; 28*7c55ee0cSOmar Sandoval 29*7c55ee0cSOmar Sandoval /* 30*7c55ee0cSOmar Sandoval * The test cases align their operations to this in order to hit some of the 31*7c55ee0cSOmar Sandoval * edge cases in the bitmap code. 32*7c55ee0cSOmar Sandoval */ 33*7c55ee0cSOmar Sandoval #define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * 4096) 34*7c55ee0cSOmar Sandoval 35*7c55ee0cSOmar Sandoval static int __check_free_space_extents(struct btrfs_trans_handle *trans, 36*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 37*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 38*7c55ee0cSOmar Sandoval struct btrfs_path *path, 39*7c55ee0cSOmar Sandoval struct free_space_extent *extents, 40*7c55ee0cSOmar Sandoval unsigned int num_extents) 41*7c55ee0cSOmar Sandoval { 42*7c55ee0cSOmar Sandoval struct btrfs_free_space_info *info; 43*7c55ee0cSOmar Sandoval struct btrfs_key key; 44*7c55ee0cSOmar Sandoval int prev_bit = 0, bit; 45*7c55ee0cSOmar Sandoval u64 extent_start = 0, offset, end; 46*7c55ee0cSOmar Sandoval u32 flags, extent_count; 47*7c55ee0cSOmar Sandoval unsigned int i; 48*7c55ee0cSOmar Sandoval int ret; 49*7c55ee0cSOmar Sandoval 50*7c55ee0cSOmar Sandoval info = search_free_space_info(trans, fs_info, cache, path, 0); 51*7c55ee0cSOmar Sandoval if (IS_ERR(info)) { 52*7c55ee0cSOmar Sandoval test_msg("Could not find free space info\n"); 53*7c55ee0cSOmar Sandoval ret = PTR_ERR(info); 54*7c55ee0cSOmar Sandoval goto out; 55*7c55ee0cSOmar Sandoval } 56*7c55ee0cSOmar Sandoval flags = btrfs_free_space_flags(path->nodes[0], info); 57*7c55ee0cSOmar Sandoval extent_count = btrfs_free_space_extent_count(path->nodes[0], info); 58*7c55ee0cSOmar Sandoval 59*7c55ee0cSOmar Sandoval if (extent_count != num_extents) { 60*7c55ee0cSOmar Sandoval test_msg("Extent count is wrong\n"); 61*7c55ee0cSOmar Sandoval ret = -EINVAL; 62*7c55ee0cSOmar Sandoval goto out; 63*7c55ee0cSOmar Sandoval } 64*7c55ee0cSOmar Sandoval if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) { 65*7c55ee0cSOmar Sandoval if (path->slots[0] != 0) 66*7c55ee0cSOmar Sandoval goto invalid; 67*7c55ee0cSOmar Sandoval end = cache->key.objectid + cache->key.offset; 68*7c55ee0cSOmar Sandoval i = 0; 69*7c55ee0cSOmar Sandoval while (++path->slots[0] < btrfs_header_nritems(path->nodes[0])) { 70*7c55ee0cSOmar Sandoval btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 71*7c55ee0cSOmar Sandoval if (key.type != BTRFS_FREE_SPACE_BITMAP_KEY) 72*7c55ee0cSOmar Sandoval goto invalid; 73*7c55ee0cSOmar Sandoval offset = key.objectid; 74*7c55ee0cSOmar Sandoval while (offset < key.objectid + key.offset) { 75*7c55ee0cSOmar Sandoval bit = free_space_test_bit(cache, path, offset); 76*7c55ee0cSOmar Sandoval if (prev_bit == 0 && bit == 1) { 77*7c55ee0cSOmar Sandoval extent_start = offset; 78*7c55ee0cSOmar Sandoval } else if (prev_bit == 1 && bit == 0) { 79*7c55ee0cSOmar Sandoval if (i >= num_extents) 80*7c55ee0cSOmar Sandoval goto invalid; 81*7c55ee0cSOmar Sandoval if (i >= num_extents || 82*7c55ee0cSOmar Sandoval extent_start != extents[i].start || 83*7c55ee0cSOmar Sandoval offset - extent_start != extents[i].length) 84*7c55ee0cSOmar Sandoval goto invalid; 85*7c55ee0cSOmar Sandoval i++; 86*7c55ee0cSOmar Sandoval } 87*7c55ee0cSOmar Sandoval prev_bit = bit; 88*7c55ee0cSOmar Sandoval offset += cache->sectorsize; 89*7c55ee0cSOmar Sandoval } 90*7c55ee0cSOmar Sandoval } 91*7c55ee0cSOmar Sandoval if (prev_bit == 1) { 92*7c55ee0cSOmar Sandoval if (i >= num_extents || 93*7c55ee0cSOmar Sandoval extent_start != extents[i].start || 94*7c55ee0cSOmar Sandoval end - extent_start != extents[i].length) 95*7c55ee0cSOmar Sandoval goto invalid; 96*7c55ee0cSOmar Sandoval i++; 97*7c55ee0cSOmar Sandoval } 98*7c55ee0cSOmar Sandoval if (i != num_extents) 99*7c55ee0cSOmar Sandoval goto invalid; 100*7c55ee0cSOmar Sandoval } else { 101*7c55ee0cSOmar Sandoval if (btrfs_header_nritems(path->nodes[0]) != num_extents + 1 || 102*7c55ee0cSOmar Sandoval path->slots[0] != 0) 103*7c55ee0cSOmar Sandoval goto invalid; 104*7c55ee0cSOmar Sandoval for (i = 0; i < num_extents; i++) { 105*7c55ee0cSOmar Sandoval path->slots[0]++; 106*7c55ee0cSOmar Sandoval btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); 107*7c55ee0cSOmar Sandoval if (key.type != BTRFS_FREE_SPACE_EXTENT_KEY || 108*7c55ee0cSOmar Sandoval key.objectid != extents[i].start || 109*7c55ee0cSOmar Sandoval key.offset != extents[i].length) 110*7c55ee0cSOmar Sandoval goto invalid; 111*7c55ee0cSOmar Sandoval } 112*7c55ee0cSOmar Sandoval } 113*7c55ee0cSOmar Sandoval 114*7c55ee0cSOmar Sandoval ret = 0; 115*7c55ee0cSOmar Sandoval out: 116*7c55ee0cSOmar Sandoval btrfs_release_path(path); 117*7c55ee0cSOmar Sandoval return ret; 118*7c55ee0cSOmar Sandoval invalid: 119*7c55ee0cSOmar Sandoval test_msg("Free space tree is invalid\n"); 120*7c55ee0cSOmar Sandoval ret = -EINVAL; 121*7c55ee0cSOmar Sandoval goto out; 122*7c55ee0cSOmar Sandoval } 123*7c55ee0cSOmar Sandoval 124*7c55ee0cSOmar Sandoval static int check_free_space_extents(struct btrfs_trans_handle *trans, 125*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 126*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 127*7c55ee0cSOmar Sandoval struct btrfs_path *path, 128*7c55ee0cSOmar Sandoval struct free_space_extent *extents, 129*7c55ee0cSOmar Sandoval unsigned int num_extents) 130*7c55ee0cSOmar Sandoval { 131*7c55ee0cSOmar Sandoval struct btrfs_free_space_info *info; 132*7c55ee0cSOmar Sandoval u32 flags; 133*7c55ee0cSOmar Sandoval int ret; 134*7c55ee0cSOmar Sandoval 135*7c55ee0cSOmar Sandoval info = search_free_space_info(trans, fs_info, cache, path, 0); 136*7c55ee0cSOmar Sandoval if (IS_ERR(info)) { 137*7c55ee0cSOmar Sandoval test_msg("Could not find free space info\n"); 138*7c55ee0cSOmar Sandoval btrfs_release_path(path); 139*7c55ee0cSOmar Sandoval return PTR_ERR(info); 140*7c55ee0cSOmar Sandoval } 141*7c55ee0cSOmar Sandoval flags = btrfs_free_space_flags(path->nodes[0], info); 142*7c55ee0cSOmar Sandoval btrfs_release_path(path); 143*7c55ee0cSOmar Sandoval 144*7c55ee0cSOmar Sandoval ret = __check_free_space_extents(trans, fs_info, cache, path, extents, 145*7c55ee0cSOmar Sandoval num_extents); 146*7c55ee0cSOmar Sandoval if (ret) 147*7c55ee0cSOmar Sandoval return ret; 148*7c55ee0cSOmar Sandoval 149*7c55ee0cSOmar Sandoval /* Flip it to the other format and check that for good measure. */ 150*7c55ee0cSOmar Sandoval if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) { 151*7c55ee0cSOmar Sandoval ret = convert_free_space_to_extents(trans, fs_info, cache, path); 152*7c55ee0cSOmar Sandoval if (ret) { 153*7c55ee0cSOmar Sandoval test_msg("Could not convert to extents\n"); 154*7c55ee0cSOmar Sandoval return ret; 155*7c55ee0cSOmar Sandoval } 156*7c55ee0cSOmar Sandoval } else { 157*7c55ee0cSOmar Sandoval ret = convert_free_space_to_bitmaps(trans, fs_info, cache, path); 158*7c55ee0cSOmar Sandoval if (ret) { 159*7c55ee0cSOmar Sandoval test_msg("Could not convert to bitmaps\n"); 160*7c55ee0cSOmar Sandoval return ret; 161*7c55ee0cSOmar Sandoval } 162*7c55ee0cSOmar Sandoval } 163*7c55ee0cSOmar Sandoval return __check_free_space_extents(trans, fs_info, cache, path, extents, 164*7c55ee0cSOmar Sandoval num_extents); 165*7c55ee0cSOmar Sandoval } 166*7c55ee0cSOmar Sandoval 167*7c55ee0cSOmar Sandoval static int test_empty_block_group(struct btrfs_trans_handle *trans, 168*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 169*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 170*7c55ee0cSOmar Sandoval struct btrfs_path *path) 171*7c55ee0cSOmar Sandoval { 172*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 173*7c55ee0cSOmar Sandoval {cache->key.objectid, cache->key.offset}, 174*7c55ee0cSOmar Sandoval }; 175*7c55ee0cSOmar Sandoval 176*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 177*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 178*7c55ee0cSOmar Sandoval } 179*7c55ee0cSOmar Sandoval 180*7c55ee0cSOmar Sandoval static int test_remove_all(struct btrfs_trans_handle *trans, 181*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 182*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 183*7c55ee0cSOmar Sandoval struct btrfs_path *path) 184*7c55ee0cSOmar Sandoval { 185*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = {}; 186*7c55ee0cSOmar Sandoval int ret; 187*7c55ee0cSOmar Sandoval 188*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 189*7c55ee0cSOmar Sandoval cache->key.objectid, 190*7c55ee0cSOmar Sandoval cache->key.offset); 191*7c55ee0cSOmar Sandoval if (ret) { 192*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 193*7c55ee0cSOmar Sandoval return ret; 194*7c55ee0cSOmar Sandoval } 195*7c55ee0cSOmar Sandoval 196*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 197*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 198*7c55ee0cSOmar Sandoval } 199*7c55ee0cSOmar Sandoval 200*7c55ee0cSOmar Sandoval static int test_remove_beginning(struct btrfs_trans_handle *trans, 201*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 202*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 203*7c55ee0cSOmar Sandoval struct btrfs_path *path) 204*7c55ee0cSOmar Sandoval { 205*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 206*7c55ee0cSOmar Sandoval {cache->key.objectid + BITMAP_RANGE, 207*7c55ee0cSOmar Sandoval cache->key.offset - BITMAP_RANGE}, 208*7c55ee0cSOmar Sandoval }; 209*7c55ee0cSOmar Sandoval int ret; 210*7c55ee0cSOmar Sandoval 211*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 212*7c55ee0cSOmar Sandoval cache->key.objectid, BITMAP_RANGE); 213*7c55ee0cSOmar Sandoval if (ret) { 214*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 215*7c55ee0cSOmar Sandoval return ret; 216*7c55ee0cSOmar Sandoval } 217*7c55ee0cSOmar Sandoval 218*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 219*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 220*7c55ee0cSOmar Sandoval 221*7c55ee0cSOmar Sandoval } 222*7c55ee0cSOmar Sandoval 223*7c55ee0cSOmar Sandoval static int test_remove_end(struct btrfs_trans_handle *trans, 224*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 225*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 226*7c55ee0cSOmar Sandoval struct btrfs_path *path) 227*7c55ee0cSOmar Sandoval { 228*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 229*7c55ee0cSOmar Sandoval {cache->key.objectid, cache->key.offset - BITMAP_RANGE}, 230*7c55ee0cSOmar Sandoval }; 231*7c55ee0cSOmar Sandoval int ret; 232*7c55ee0cSOmar Sandoval 233*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 234*7c55ee0cSOmar Sandoval cache->key.objectid + 235*7c55ee0cSOmar Sandoval cache->key.offset - BITMAP_RANGE, 236*7c55ee0cSOmar Sandoval BITMAP_RANGE); 237*7c55ee0cSOmar Sandoval if (ret) { 238*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 239*7c55ee0cSOmar Sandoval return ret; 240*7c55ee0cSOmar Sandoval } 241*7c55ee0cSOmar Sandoval 242*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 243*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 244*7c55ee0cSOmar Sandoval } 245*7c55ee0cSOmar Sandoval 246*7c55ee0cSOmar Sandoval static int test_remove_middle(struct btrfs_trans_handle *trans, 247*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 248*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 249*7c55ee0cSOmar Sandoval struct btrfs_path *path) 250*7c55ee0cSOmar Sandoval { 251*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 252*7c55ee0cSOmar Sandoval {cache->key.objectid, BITMAP_RANGE}, 253*7c55ee0cSOmar Sandoval {cache->key.objectid + 2 * BITMAP_RANGE, 254*7c55ee0cSOmar Sandoval cache->key.offset - 2 * BITMAP_RANGE}, 255*7c55ee0cSOmar Sandoval }; 256*7c55ee0cSOmar Sandoval int ret; 257*7c55ee0cSOmar Sandoval 258*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 259*7c55ee0cSOmar Sandoval cache->key.objectid + BITMAP_RANGE, 260*7c55ee0cSOmar Sandoval BITMAP_RANGE); 261*7c55ee0cSOmar Sandoval if (ret) { 262*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 263*7c55ee0cSOmar Sandoval return ret; 264*7c55ee0cSOmar Sandoval } 265*7c55ee0cSOmar Sandoval 266*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 267*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 268*7c55ee0cSOmar Sandoval } 269*7c55ee0cSOmar Sandoval 270*7c55ee0cSOmar Sandoval static int test_merge_left(struct btrfs_trans_handle *trans, 271*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 272*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 273*7c55ee0cSOmar Sandoval struct btrfs_path *path) 274*7c55ee0cSOmar Sandoval { 275*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 276*7c55ee0cSOmar Sandoval {cache->key.objectid, 2 * BITMAP_RANGE}, 277*7c55ee0cSOmar Sandoval }; 278*7c55ee0cSOmar Sandoval int ret; 279*7c55ee0cSOmar Sandoval 280*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 281*7c55ee0cSOmar Sandoval cache->key.objectid, 282*7c55ee0cSOmar Sandoval cache->key.offset); 283*7c55ee0cSOmar Sandoval if (ret) { 284*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 285*7c55ee0cSOmar Sandoval return ret; 286*7c55ee0cSOmar Sandoval } 287*7c55ee0cSOmar Sandoval 288*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 289*7c55ee0cSOmar Sandoval cache->key.objectid, BITMAP_RANGE); 290*7c55ee0cSOmar Sandoval if (ret) { 291*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 292*7c55ee0cSOmar Sandoval return ret; 293*7c55ee0cSOmar Sandoval } 294*7c55ee0cSOmar Sandoval 295*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 296*7c55ee0cSOmar Sandoval cache->key.objectid + BITMAP_RANGE, 297*7c55ee0cSOmar Sandoval BITMAP_RANGE); 298*7c55ee0cSOmar Sandoval if (ret) { 299*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 300*7c55ee0cSOmar Sandoval return ret; 301*7c55ee0cSOmar Sandoval } 302*7c55ee0cSOmar Sandoval 303*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 304*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 305*7c55ee0cSOmar Sandoval } 306*7c55ee0cSOmar Sandoval 307*7c55ee0cSOmar Sandoval static int test_merge_right(struct btrfs_trans_handle *trans, 308*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 309*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 310*7c55ee0cSOmar Sandoval struct btrfs_path *path) 311*7c55ee0cSOmar Sandoval { 312*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 313*7c55ee0cSOmar Sandoval {cache->key.objectid + BITMAP_RANGE, 2 * BITMAP_RANGE}, 314*7c55ee0cSOmar Sandoval }; 315*7c55ee0cSOmar Sandoval int ret; 316*7c55ee0cSOmar Sandoval 317*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 318*7c55ee0cSOmar Sandoval cache->key.objectid, 319*7c55ee0cSOmar Sandoval cache->key.offset); 320*7c55ee0cSOmar Sandoval if (ret) { 321*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 322*7c55ee0cSOmar Sandoval return ret; 323*7c55ee0cSOmar Sandoval } 324*7c55ee0cSOmar Sandoval 325*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 326*7c55ee0cSOmar Sandoval cache->key.objectid + 2 * BITMAP_RANGE, 327*7c55ee0cSOmar Sandoval BITMAP_RANGE); 328*7c55ee0cSOmar Sandoval if (ret) { 329*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 330*7c55ee0cSOmar Sandoval return ret; 331*7c55ee0cSOmar Sandoval } 332*7c55ee0cSOmar Sandoval 333*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 334*7c55ee0cSOmar Sandoval cache->key.objectid + BITMAP_RANGE, 335*7c55ee0cSOmar Sandoval BITMAP_RANGE); 336*7c55ee0cSOmar Sandoval if (ret) { 337*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 338*7c55ee0cSOmar Sandoval return ret; 339*7c55ee0cSOmar Sandoval } 340*7c55ee0cSOmar Sandoval 341*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 342*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 343*7c55ee0cSOmar Sandoval } 344*7c55ee0cSOmar Sandoval 345*7c55ee0cSOmar Sandoval static int test_merge_both(struct btrfs_trans_handle *trans, 346*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 347*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 348*7c55ee0cSOmar Sandoval struct btrfs_path *path) 349*7c55ee0cSOmar Sandoval { 350*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 351*7c55ee0cSOmar Sandoval {cache->key.objectid, 3 * BITMAP_RANGE}, 352*7c55ee0cSOmar Sandoval }; 353*7c55ee0cSOmar Sandoval int ret; 354*7c55ee0cSOmar Sandoval 355*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 356*7c55ee0cSOmar Sandoval cache->key.objectid, 357*7c55ee0cSOmar Sandoval cache->key.offset); 358*7c55ee0cSOmar Sandoval if (ret) { 359*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 360*7c55ee0cSOmar Sandoval return ret; 361*7c55ee0cSOmar Sandoval } 362*7c55ee0cSOmar Sandoval 363*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 364*7c55ee0cSOmar Sandoval cache->key.objectid, BITMAP_RANGE); 365*7c55ee0cSOmar Sandoval if (ret) { 366*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 367*7c55ee0cSOmar Sandoval return ret; 368*7c55ee0cSOmar Sandoval } 369*7c55ee0cSOmar Sandoval 370*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 371*7c55ee0cSOmar Sandoval cache->key.objectid + 2 * BITMAP_RANGE, 372*7c55ee0cSOmar Sandoval BITMAP_RANGE); 373*7c55ee0cSOmar Sandoval if (ret) { 374*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 375*7c55ee0cSOmar Sandoval return ret; 376*7c55ee0cSOmar Sandoval } 377*7c55ee0cSOmar Sandoval 378*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 379*7c55ee0cSOmar Sandoval cache->key.objectid + BITMAP_RANGE, 380*7c55ee0cSOmar Sandoval BITMAP_RANGE); 381*7c55ee0cSOmar Sandoval if (ret) { 382*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 383*7c55ee0cSOmar Sandoval return ret; 384*7c55ee0cSOmar Sandoval } 385*7c55ee0cSOmar Sandoval 386*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 387*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 388*7c55ee0cSOmar Sandoval } 389*7c55ee0cSOmar Sandoval 390*7c55ee0cSOmar Sandoval static int test_merge_none(struct btrfs_trans_handle *trans, 391*7c55ee0cSOmar Sandoval struct btrfs_fs_info *fs_info, 392*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache, 393*7c55ee0cSOmar Sandoval struct btrfs_path *path) 394*7c55ee0cSOmar Sandoval { 395*7c55ee0cSOmar Sandoval struct free_space_extent extents[] = { 396*7c55ee0cSOmar Sandoval {cache->key.objectid, BITMAP_RANGE}, 397*7c55ee0cSOmar Sandoval {cache->key.objectid + 2 * BITMAP_RANGE, BITMAP_RANGE}, 398*7c55ee0cSOmar Sandoval {cache->key.objectid + 4 * BITMAP_RANGE, BITMAP_RANGE}, 399*7c55ee0cSOmar Sandoval }; 400*7c55ee0cSOmar Sandoval int ret; 401*7c55ee0cSOmar Sandoval 402*7c55ee0cSOmar Sandoval ret = __remove_from_free_space_tree(trans, fs_info, cache, path, 403*7c55ee0cSOmar Sandoval cache->key.objectid, 404*7c55ee0cSOmar Sandoval cache->key.offset); 405*7c55ee0cSOmar Sandoval if (ret) { 406*7c55ee0cSOmar Sandoval test_msg("Could not remove free space\n"); 407*7c55ee0cSOmar Sandoval return ret; 408*7c55ee0cSOmar Sandoval } 409*7c55ee0cSOmar Sandoval 410*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 411*7c55ee0cSOmar Sandoval cache->key.objectid, BITMAP_RANGE); 412*7c55ee0cSOmar Sandoval if (ret) { 413*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 414*7c55ee0cSOmar Sandoval return ret; 415*7c55ee0cSOmar Sandoval } 416*7c55ee0cSOmar Sandoval 417*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 418*7c55ee0cSOmar Sandoval cache->key.objectid + 4 * BITMAP_RANGE, 419*7c55ee0cSOmar Sandoval BITMAP_RANGE); 420*7c55ee0cSOmar Sandoval if (ret) { 421*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 422*7c55ee0cSOmar Sandoval return ret; 423*7c55ee0cSOmar Sandoval } 424*7c55ee0cSOmar Sandoval 425*7c55ee0cSOmar Sandoval ret = __add_to_free_space_tree(trans, fs_info, cache, path, 426*7c55ee0cSOmar Sandoval cache->key.objectid + 2 * BITMAP_RANGE, 427*7c55ee0cSOmar Sandoval BITMAP_RANGE); 428*7c55ee0cSOmar Sandoval if (ret) { 429*7c55ee0cSOmar Sandoval test_msg("Could not add free space\n"); 430*7c55ee0cSOmar Sandoval return ret; 431*7c55ee0cSOmar Sandoval } 432*7c55ee0cSOmar Sandoval 433*7c55ee0cSOmar Sandoval return check_free_space_extents(trans, fs_info, cache, path, 434*7c55ee0cSOmar Sandoval extents, ARRAY_SIZE(extents)); 435*7c55ee0cSOmar Sandoval } 436*7c55ee0cSOmar Sandoval 437*7c55ee0cSOmar Sandoval typedef int (*test_func_t)(struct btrfs_trans_handle *, 438*7c55ee0cSOmar Sandoval struct btrfs_fs_info *, 439*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *, 440*7c55ee0cSOmar Sandoval struct btrfs_path *); 441*7c55ee0cSOmar Sandoval 442*7c55ee0cSOmar Sandoval static int run_test(test_func_t test_func, int bitmaps) 443*7c55ee0cSOmar Sandoval { 444*7c55ee0cSOmar Sandoval struct btrfs_root *root = NULL; 445*7c55ee0cSOmar Sandoval struct btrfs_block_group_cache *cache = NULL; 446*7c55ee0cSOmar Sandoval struct btrfs_trans_handle trans; 447*7c55ee0cSOmar Sandoval struct btrfs_path *path = NULL; 448*7c55ee0cSOmar Sandoval int ret; 449*7c55ee0cSOmar Sandoval 450*7c55ee0cSOmar Sandoval root = btrfs_alloc_dummy_root(); 451*7c55ee0cSOmar Sandoval if (IS_ERR(root)) { 452*7c55ee0cSOmar Sandoval test_msg("Couldn't allocate dummy root\n"); 453*7c55ee0cSOmar Sandoval ret = PTR_ERR(root); 454*7c55ee0cSOmar Sandoval goto out; 455*7c55ee0cSOmar Sandoval } 456*7c55ee0cSOmar Sandoval 457*7c55ee0cSOmar Sandoval root->fs_info = btrfs_alloc_dummy_fs_info(); 458*7c55ee0cSOmar Sandoval if (!root->fs_info) { 459*7c55ee0cSOmar Sandoval test_msg("Couldn't allocate dummy fs info\n"); 460*7c55ee0cSOmar Sandoval ret = -ENOMEM; 461*7c55ee0cSOmar Sandoval goto out; 462*7c55ee0cSOmar Sandoval } 463*7c55ee0cSOmar Sandoval 464*7c55ee0cSOmar Sandoval btrfs_set_super_compat_ro_flags(root->fs_info->super_copy, 465*7c55ee0cSOmar Sandoval BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE); 466*7c55ee0cSOmar Sandoval root->fs_info->free_space_root = root; 467*7c55ee0cSOmar Sandoval root->fs_info->tree_root = root; 468*7c55ee0cSOmar Sandoval 469*7c55ee0cSOmar Sandoval root->node = alloc_test_extent_buffer(root->fs_info, 4096); 470*7c55ee0cSOmar Sandoval if (!root->node) { 471*7c55ee0cSOmar Sandoval test_msg("Couldn't allocate dummy buffer\n"); 472*7c55ee0cSOmar Sandoval ret = -ENOMEM; 473*7c55ee0cSOmar Sandoval goto out; 474*7c55ee0cSOmar Sandoval } 475*7c55ee0cSOmar Sandoval btrfs_set_header_level(root->node, 0); 476*7c55ee0cSOmar Sandoval btrfs_set_header_nritems(root->node, 0); 477*7c55ee0cSOmar Sandoval root->alloc_bytenr += 8192; 478*7c55ee0cSOmar Sandoval 479*7c55ee0cSOmar Sandoval cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE); 480*7c55ee0cSOmar Sandoval if (!cache) { 481*7c55ee0cSOmar Sandoval test_msg("Couldn't allocate dummy block group cache\n"); 482*7c55ee0cSOmar Sandoval ret = -ENOMEM; 483*7c55ee0cSOmar Sandoval goto out; 484*7c55ee0cSOmar Sandoval } 485*7c55ee0cSOmar Sandoval cache->bitmap_low_thresh = 0; 486*7c55ee0cSOmar Sandoval cache->bitmap_high_thresh = (u32)-1; 487*7c55ee0cSOmar Sandoval cache->needs_free_space = 1; 488*7c55ee0cSOmar Sandoval 489*7c55ee0cSOmar Sandoval btrfs_init_dummy_trans(&trans); 490*7c55ee0cSOmar Sandoval 491*7c55ee0cSOmar Sandoval path = btrfs_alloc_path(); 492*7c55ee0cSOmar Sandoval if (!path) { 493*7c55ee0cSOmar Sandoval test_msg("Couldn't allocate path\n"); 494*7c55ee0cSOmar Sandoval return -ENOMEM; 495*7c55ee0cSOmar Sandoval } 496*7c55ee0cSOmar Sandoval 497*7c55ee0cSOmar Sandoval ret = add_block_group_free_space(&trans, root->fs_info, cache); 498*7c55ee0cSOmar Sandoval if (ret) { 499*7c55ee0cSOmar Sandoval test_msg("Could not add block group free space\n"); 500*7c55ee0cSOmar Sandoval goto out; 501*7c55ee0cSOmar Sandoval } 502*7c55ee0cSOmar Sandoval 503*7c55ee0cSOmar Sandoval if (bitmaps) { 504*7c55ee0cSOmar Sandoval ret = convert_free_space_to_bitmaps(&trans, root->fs_info, 505*7c55ee0cSOmar Sandoval cache, path); 506*7c55ee0cSOmar Sandoval if (ret) { 507*7c55ee0cSOmar Sandoval test_msg("Could not convert block group to bitmaps\n"); 508*7c55ee0cSOmar Sandoval goto out; 509*7c55ee0cSOmar Sandoval } 510*7c55ee0cSOmar Sandoval } 511*7c55ee0cSOmar Sandoval 512*7c55ee0cSOmar Sandoval ret = test_func(&trans, root->fs_info, cache, path); 513*7c55ee0cSOmar Sandoval if (ret) 514*7c55ee0cSOmar Sandoval goto out; 515*7c55ee0cSOmar Sandoval 516*7c55ee0cSOmar Sandoval ret = remove_block_group_free_space(&trans, root->fs_info, cache); 517*7c55ee0cSOmar Sandoval if (ret) { 518*7c55ee0cSOmar Sandoval test_msg("Could not remove block group free space\n"); 519*7c55ee0cSOmar Sandoval goto out; 520*7c55ee0cSOmar Sandoval } 521*7c55ee0cSOmar Sandoval 522*7c55ee0cSOmar Sandoval if (btrfs_header_nritems(root->node) != 0) { 523*7c55ee0cSOmar Sandoval test_msg("Free space tree has leftover items\n"); 524*7c55ee0cSOmar Sandoval ret = -EINVAL; 525*7c55ee0cSOmar Sandoval goto out; 526*7c55ee0cSOmar Sandoval } 527*7c55ee0cSOmar Sandoval 528*7c55ee0cSOmar Sandoval ret = 0; 529*7c55ee0cSOmar Sandoval out: 530*7c55ee0cSOmar Sandoval btrfs_free_path(path); 531*7c55ee0cSOmar Sandoval btrfs_free_dummy_block_group(cache); 532*7c55ee0cSOmar Sandoval btrfs_free_dummy_root(root); 533*7c55ee0cSOmar Sandoval return ret; 534*7c55ee0cSOmar Sandoval } 535*7c55ee0cSOmar Sandoval 536*7c55ee0cSOmar Sandoval static int run_test_both_formats(test_func_t test_func) 537*7c55ee0cSOmar Sandoval { 538*7c55ee0cSOmar Sandoval int ret; 539*7c55ee0cSOmar Sandoval 540*7c55ee0cSOmar Sandoval ret = run_test(test_func, 0); 541*7c55ee0cSOmar Sandoval if (ret) 542*7c55ee0cSOmar Sandoval return ret; 543*7c55ee0cSOmar Sandoval return run_test(test_func, 1); 544*7c55ee0cSOmar Sandoval } 545*7c55ee0cSOmar Sandoval 546*7c55ee0cSOmar Sandoval int btrfs_test_free_space_tree(void) 547*7c55ee0cSOmar Sandoval { 548*7c55ee0cSOmar Sandoval test_func_t tests[] = { 549*7c55ee0cSOmar Sandoval test_empty_block_group, 550*7c55ee0cSOmar Sandoval test_remove_all, 551*7c55ee0cSOmar Sandoval test_remove_beginning, 552*7c55ee0cSOmar Sandoval test_remove_end, 553*7c55ee0cSOmar Sandoval test_remove_middle, 554*7c55ee0cSOmar Sandoval test_merge_left, 555*7c55ee0cSOmar Sandoval test_merge_right, 556*7c55ee0cSOmar Sandoval test_merge_both, 557*7c55ee0cSOmar Sandoval test_merge_none, 558*7c55ee0cSOmar Sandoval }; 559*7c55ee0cSOmar Sandoval int i; 560*7c55ee0cSOmar Sandoval 561*7c55ee0cSOmar Sandoval test_msg("Running free space tree tests\n"); 562*7c55ee0cSOmar Sandoval for (i = 0; i < ARRAY_SIZE(tests); i++) { 563*7c55ee0cSOmar Sandoval int ret = run_test_both_formats(tests[i]); 564*7c55ee0cSOmar Sandoval if (ret) { 565*7c55ee0cSOmar Sandoval test_msg("%pf failed\n", tests[i]); 566*7c55ee0cSOmar Sandoval return ret; 567*7c55ee0cSOmar Sandoval } 568*7c55ee0cSOmar Sandoval } 569*7c55ee0cSOmar Sandoval 570*7c55ee0cSOmar Sandoval return 0; 571*7c55ee0cSOmar Sandoval } 572