| .. | .. |
|---|
| 10 | 10 | #include "locking.h" |
|---|
| 11 | 11 | #include "free-space-tree.h" |
|---|
| 12 | 12 | #include "transaction.h" |
|---|
| 13 | +#include "block-group.h" |
|---|
| 13 | 14 | |
|---|
| 14 | 15 | static int __add_block_group_free_space(struct btrfs_trans_handle *trans, |
|---|
| 15 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 16 | + struct btrfs_block_group *block_group, |
|---|
| 16 | 17 | struct btrfs_path *path); |
|---|
| 17 | 18 | |
|---|
| 18 | | -void set_free_space_tree_thresholds(struct btrfs_block_group_cache *cache) |
|---|
| 19 | +void set_free_space_tree_thresholds(struct btrfs_block_group *cache) |
|---|
| 19 | 20 | { |
|---|
| 20 | 21 | u32 bitmap_range; |
|---|
| 21 | 22 | size_t bitmap_size; |
|---|
| 22 | 23 | u64 num_bitmaps, total_bitmap_size; |
|---|
| 24 | + |
|---|
| 25 | + if (WARN_ON(cache->length == 0)) |
|---|
| 26 | + btrfs_warn(cache->fs_info, "block group %llu length is zero", |
|---|
| 27 | + cache->start); |
|---|
| 23 | 28 | |
|---|
| 24 | 29 | /* |
|---|
| 25 | 30 | * We convert to bitmaps when the disk space required for using extents |
|---|
| 26 | 31 | * exceeds that required for using bitmaps. |
|---|
| 27 | 32 | */ |
|---|
| 28 | 33 | bitmap_range = cache->fs_info->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS; |
|---|
| 29 | | - num_bitmaps = div_u64(cache->key.offset + bitmap_range - 1, |
|---|
| 30 | | - bitmap_range); |
|---|
| 34 | + num_bitmaps = div_u64(cache->length + bitmap_range - 1, bitmap_range); |
|---|
| 31 | 35 | bitmap_size = sizeof(struct btrfs_item) + BTRFS_FREE_SPACE_BITMAP_SIZE; |
|---|
| 32 | 36 | total_bitmap_size = num_bitmaps * bitmap_size; |
|---|
| 33 | 37 | cache->bitmap_high_thresh = div_u64(total_bitmap_size, |
|---|
| .. | .. |
|---|
| 44 | 48 | } |
|---|
| 45 | 49 | |
|---|
| 46 | 50 | static int add_new_free_space_info(struct btrfs_trans_handle *trans, |
|---|
| 47 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 51 | + struct btrfs_block_group *block_group, |
|---|
| 48 | 52 | struct btrfs_path *path) |
|---|
| 49 | 53 | { |
|---|
| 50 | 54 | struct btrfs_root *root = trans->fs_info->free_space_root; |
|---|
| .. | .. |
|---|
| 53 | 57 | struct extent_buffer *leaf; |
|---|
| 54 | 58 | int ret; |
|---|
| 55 | 59 | |
|---|
| 56 | | - key.objectid = block_group->key.objectid; |
|---|
| 60 | + key.objectid = block_group->start; |
|---|
| 57 | 61 | key.type = BTRFS_FREE_SPACE_INFO_KEY; |
|---|
| 58 | | - key.offset = block_group->key.offset; |
|---|
| 62 | + key.offset = block_group->length; |
|---|
| 59 | 63 | |
|---|
| 60 | 64 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*info)); |
|---|
| 61 | 65 | if (ret) |
|---|
| .. | .. |
|---|
| 74 | 78 | return ret; |
|---|
| 75 | 79 | } |
|---|
| 76 | 80 | |
|---|
| 77 | | -struct btrfs_free_space_info * |
|---|
| 78 | | -search_free_space_info(struct btrfs_trans_handle *trans, |
|---|
| 79 | | - struct btrfs_fs_info *fs_info, |
|---|
| 80 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 81 | | - struct btrfs_path *path, int cow) |
|---|
| 81 | +EXPORT_FOR_TESTS |
|---|
| 82 | +struct btrfs_free_space_info *search_free_space_info( |
|---|
| 83 | + struct btrfs_trans_handle *trans, |
|---|
| 84 | + struct btrfs_block_group *block_group, |
|---|
| 85 | + struct btrfs_path *path, int cow) |
|---|
| 82 | 86 | { |
|---|
| 87 | + struct btrfs_fs_info *fs_info = block_group->fs_info; |
|---|
| 83 | 88 | struct btrfs_root *root = fs_info->free_space_root; |
|---|
| 84 | 89 | struct btrfs_key key; |
|---|
| 85 | 90 | int ret; |
|---|
| 86 | 91 | |
|---|
| 87 | | - key.objectid = block_group->key.objectid; |
|---|
| 92 | + key.objectid = block_group->start; |
|---|
| 88 | 93 | key.type = BTRFS_FREE_SPACE_INFO_KEY; |
|---|
| 89 | | - key.offset = block_group->key.offset; |
|---|
| 94 | + key.offset = block_group->length; |
|---|
| 90 | 95 | |
|---|
| 91 | 96 | ret = btrfs_search_slot(trans, root, &key, path, 0, cow); |
|---|
| 92 | 97 | if (ret < 0) |
|---|
| 93 | 98 | return ERR_PTR(ret); |
|---|
| 94 | 99 | if (ret != 0) { |
|---|
| 95 | 100 | btrfs_warn(fs_info, "missing free space info for %llu", |
|---|
| 96 | | - block_group->key.objectid); |
|---|
| 101 | + block_group->start); |
|---|
| 97 | 102 | ASSERT(0); |
|---|
| 98 | 103 | return ERR_PTR(-ENOENT); |
|---|
| 99 | 104 | } |
|---|
| .. | .. |
|---|
| 176 | 181 | } |
|---|
| 177 | 182 | } |
|---|
| 178 | 183 | |
|---|
| 184 | +EXPORT_FOR_TESTS |
|---|
| 179 | 185 | int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans, |
|---|
| 180 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 186 | + struct btrfs_block_group *block_group, |
|---|
| 181 | 187 | struct btrfs_path *path) |
|---|
| 182 | 188 | { |
|---|
| 183 | 189 | struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| .. | .. |
|---|
| 194 | 200 | int done = 0, nr; |
|---|
| 195 | 201 | int ret; |
|---|
| 196 | 202 | |
|---|
| 197 | | - bitmap_size = free_space_bitmap_size(block_group->key.offset, |
|---|
| 203 | + bitmap_size = free_space_bitmap_size(block_group->length, |
|---|
| 198 | 204 | fs_info->sectorsize); |
|---|
| 199 | 205 | bitmap = alloc_bitmap(bitmap_size); |
|---|
| 200 | 206 | if (!bitmap) { |
|---|
| .. | .. |
|---|
| 202 | 208 | goto out; |
|---|
| 203 | 209 | } |
|---|
| 204 | 210 | |
|---|
| 205 | | - start = block_group->key.objectid; |
|---|
| 206 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 211 | + start = block_group->start; |
|---|
| 212 | + end = block_group->start + block_group->length; |
|---|
| 207 | 213 | |
|---|
| 208 | 214 | key.objectid = end - 1; |
|---|
| 209 | 215 | key.type = (u8)-1; |
|---|
| .. | .. |
|---|
| 221 | 227 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); |
|---|
| 222 | 228 | |
|---|
| 223 | 229 | if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { |
|---|
| 224 | | - ASSERT(found_key.objectid == block_group->key.objectid); |
|---|
| 225 | | - ASSERT(found_key.offset == block_group->key.offset); |
|---|
| 230 | + ASSERT(found_key.objectid == block_group->start); |
|---|
| 231 | + ASSERT(found_key.offset == block_group->length); |
|---|
| 226 | 232 | done = 1; |
|---|
| 227 | 233 | break; |
|---|
| 228 | 234 | } else if (found_key.type == BTRFS_FREE_SPACE_EXTENT_KEY) { |
|---|
| .. | .. |
|---|
| 252 | 258 | btrfs_release_path(path); |
|---|
| 253 | 259 | } |
|---|
| 254 | 260 | |
|---|
| 255 | | - info = search_free_space_info(trans, fs_info, block_group, path, 1); |
|---|
| 261 | + info = search_free_space_info(trans, block_group, path, 1); |
|---|
| 256 | 262 | if (IS_ERR(info)) { |
|---|
| 257 | 263 | ret = PTR_ERR(info); |
|---|
| 258 | 264 | goto out; |
|---|
| .. | .. |
|---|
| 268 | 274 | if (extent_count != expected_extent_count) { |
|---|
| 269 | 275 | btrfs_err(fs_info, |
|---|
| 270 | 276 | "incorrect extent count for %llu; counted %u, expected %u", |
|---|
| 271 | | - block_group->key.objectid, extent_count, |
|---|
| 277 | + block_group->start, extent_count, |
|---|
| 272 | 278 | expected_extent_count); |
|---|
| 273 | 279 | ASSERT(0); |
|---|
| 274 | 280 | ret = -EIO; |
|---|
| .. | .. |
|---|
| 315 | 321 | return ret; |
|---|
| 316 | 322 | } |
|---|
| 317 | 323 | |
|---|
| 324 | +EXPORT_FOR_TESTS |
|---|
| 318 | 325 | int convert_free_space_to_extents(struct btrfs_trans_handle *trans, |
|---|
| 319 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 326 | + struct btrfs_block_group *block_group, |
|---|
| 320 | 327 | struct btrfs_path *path) |
|---|
| 321 | 328 | { |
|---|
| 322 | 329 | struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| .. | .. |
|---|
| 332 | 339 | int done = 0, nr; |
|---|
| 333 | 340 | int ret; |
|---|
| 334 | 341 | |
|---|
| 335 | | - bitmap_size = free_space_bitmap_size(block_group->key.offset, |
|---|
| 342 | + bitmap_size = free_space_bitmap_size(block_group->length, |
|---|
| 336 | 343 | fs_info->sectorsize); |
|---|
| 337 | 344 | bitmap = alloc_bitmap(bitmap_size); |
|---|
| 338 | 345 | if (!bitmap) { |
|---|
| .. | .. |
|---|
| 340 | 347 | goto out; |
|---|
| 341 | 348 | } |
|---|
| 342 | 349 | |
|---|
| 343 | | - start = block_group->key.objectid; |
|---|
| 344 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 350 | + start = block_group->start; |
|---|
| 351 | + end = block_group->start + block_group->length; |
|---|
| 345 | 352 | |
|---|
| 346 | 353 | key.objectid = end - 1; |
|---|
| 347 | 354 | key.type = (u8)-1; |
|---|
| .. | .. |
|---|
| 359 | 366 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); |
|---|
| 360 | 367 | |
|---|
| 361 | 368 | if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { |
|---|
| 362 | | - ASSERT(found_key.objectid == block_group->key.objectid); |
|---|
| 363 | | - ASSERT(found_key.offset == block_group->key.offset); |
|---|
| 369 | + ASSERT(found_key.objectid == block_group->start); |
|---|
| 370 | + ASSERT(found_key.offset == block_group->length); |
|---|
| 364 | 371 | done = 1; |
|---|
| 365 | 372 | break; |
|---|
| 366 | 373 | } else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) { |
|---|
| .. | .. |
|---|
| 396 | 403 | btrfs_release_path(path); |
|---|
| 397 | 404 | } |
|---|
| 398 | 405 | |
|---|
| 399 | | - info = search_free_space_info(trans, fs_info, block_group, path, 1); |
|---|
| 406 | + info = search_free_space_info(trans, block_group, path, 1); |
|---|
| 400 | 407 | if (IS_ERR(info)) { |
|---|
| 401 | 408 | ret = PTR_ERR(info); |
|---|
| 402 | 409 | goto out; |
|---|
| .. | .. |
|---|
| 409 | 416 | btrfs_mark_buffer_dirty(leaf); |
|---|
| 410 | 417 | btrfs_release_path(path); |
|---|
| 411 | 418 | |
|---|
| 412 | | - nrbits = div_u64(block_group->key.offset, block_group->fs_info->sectorsize); |
|---|
| 419 | + nrbits = div_u64(block_group->length, block_group->fs_info->sectorsize); |
|---|
| 413 | 420 | start_bit = find_next_bit_le(bitmap, nrbits, 0); |
|---|
| 414 | 421 | |
|---|
| 415 | 422 | while (start_bit < nrbits) { |
|---|
| .. | .. |
|---|
| 433 | 440 | if (extent_count != expected_extent_count) { |
|---|
| 434 | 441 | btrfs_err(fs_info, |
|---|
| 435 | 442 | "incorrect extent count for %llu; counted %u, expected %u", |
|---|
| 436 | | - block_group->key.objectid, extent_count, |
|---|
| 443 | + block_group->start, extent_count, |
|---|
| 437 | 444 | expected_extent_count); |
|---|
| 438 | 445 | ASSERT(0); |
|---|
| 439 | 446 | ret = -EIO; |
|---|
| .. | .. |
|---|
| 449 | 456 | } |
|---|
| 450 | 457 | |
|---|
| 451 | 458 | static int update_free_space_extent_count(struct btrfs_trans_handle *trans, |
|---|
| 452 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 459 | + struct btrfs_block_group *block_group, |
|---|
| 453 | 460 | struct btrfs_path *path, |
|---|
| 454 | 461 | int new_extents) |
|---|
| 455 | 462 | { |
|---|
| .. | .. |
|---|
| 461 | 468 | if (new_extents == 0) |
|---|
| 462 | 469 | return 0; |
|---|
| 463 | 470 | |
|---|
| 464 | | - info = search_free_space_info(trans, trans->fs_info, block_group, path, |
|---|
| 465 | | - 1); |
|---|
| 471 | + info = search_free_space_info(trans, block_group, path, 1); |
|---|
| 466 | 472 | if (IS_ERR(info)) { |
|---|
| 467 | 473 | ret = PTR_ERR(info); |
|---|
| 468 | 474 | goto out; |
|---|
| .. | .. |
|---|
| 487 | 493 | return ret; |
|---|
| 488 | 494 | } |
|---|
| 489 | 495 | |
|---|
| 490 | | -int free_space_test_bit(struct btrfs_block_group_cache *block_group, |
|---|
| 496 | +EXPORT_FOR_TESTS |
|---|
| 497 | +int free_space_test_bit(struct btrfs_block_group *block_group, |
|---|
| 491 | 498 | struct btrfs_path *path, u64 offset) |
|---|
| 492 | 499 | { |
|---|
| 493 | 500 | struct extent_buffer *leaf; |
|---|
| .. | .. |
|---|
| 509 | 516 | return !!extent_buffer_test_bit(leaf, ptr, i); |
|---|
| 510 | 517 | } |
|---|
| 511 | 518 | |
|---|
| 512 | | -static void free_space_set_bits(struct btrfs_block_group_cache *block_group, |
|---|
| 519 | +static void free_space_set_bits(struct btrfs_block_group *block_group, |
|---|
| 513 | 520 | struct btrfs_path *path, u64 *start, u64 *size, |
|---|
| 514 | 521 | int bit) |
|---|
| 515 | 522 | { |
|---|
| .. | .. |
|---|
| 577 | 584 | * the bitmap. |
|---|
| 578 | 585 | */ |
|---|
| 579 | 586 | static int modify_free_space_bitmap(struct btrfs_trans_handle *trans, |
|---|
| 580 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 587 | + struct btrfs_block_group *block_group, |
|---|
| 581 | 588 | struct btrfs_path *path, |
|---|
| 582 | 589 | u64 start, u64 size, int remove) |
|---|
| 583 | 590 | { |
|---|
| .. | .. |
|---|
| 593 | 600 | * Read the bit for the block immediately before the extent of space if |
|---|
| 594 | 601 | * that block is within the block group. |
|---|
| 595 | 602 | */ |
|---|
| 596 | | - if (start > block_group->key.objectid) { |
|---|
| 603 | + if (start > block_group->start) { |
|---|
| 597 | 604 | u64 prev_block = start - block_group->fs_info->sectorsize; |
|---|
| 598 | 605 | |
|---|
| 599 | 606 | key.objectid = prev_block; |
|---|
| .. | .. |
|---|
| 645 | 652 | * Read the bit for the block immediately after the extent of space if |
|---|
| 646 | 653 | * that block is within the block group. |
|---|
| 647 | 654 | */ |
|---|
| 648 | | - if (end < block_group->key.objectid + block_group->key.offset) { |
|---|
| 655 | + if (end < block_group->start + block_group->length) { |
|---|
| 649 | 656 | /* The next block may be in the next bitmap. */ |
|---|
| 650 | 657 | btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); |
|---|
| 651 | 658 | if (end >= key.objectid + key.offset) { |
|---|
| .. | .. |
|---|
| 690 | 697 | } |
|---|
| 691 | 698 | |
|---|
| 692 | 699 | static int remove_free_space_extent(struct btrfs_trans_handle *trans, |
|---|
| 693 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 700 | + struct btrfs_block_group *block_group, |
|---|
| 694 | 701 | struct btrfs_path *path, |
|---|
| 695 | 702 | u64 start, u64 size) |
|---|
| 696 | 703 | { |
|---|
| .. | .. |
|---|
| 775 | 782 | return ret; |
|---|
| 776 | 783 | } |
|---|
| 777 | 784 | |
|---|
| 785 | +EXPORT_FOR_TESTS |
|---|
| 778 | 786 | int __remove_from_free_space_tree(struct btrfs_trans_handle *trans, |
|---|
| 779 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 787 | + struct btrfs_block_group *block_group, |
|---|
| 780 | 788 | struct btrfs_path *path, u64 start, u64 size) |
|---|
| 781 | 789 | { |
|---|
| 782 | 790 | struct btrfs_free_space_info *info; |
|---|
| .. | .. |
|---|
| 789 | 797 | return ret; |
|---|
| 790 | 798 | } |
|---|
| 791 | 799 | |
|---|
| 792 | | - info = search_free_space_info(NULL, trans->fs_info, block_group, path, |
|---|
| 793 | | - 0); |
|---|
| 800 | + info = search_free_space_info(NULL, block_group, path, 0); |
|---|
| 794 | 801 | if (IS_ERR(info)) |
|---|
| 795 | 802 | return PTR_ERR(info); |
|---|
| 796 | 803 | flags = btrfs_free_space_flags(path->nodes[0], info); |
|---|
| .. | .. |
|---|
| 808 | 815 | int remove_from_free_space_tree(struct btrfs_trans_handle *trans, |
|---|
| 809 | 816 | u64 start, u64 size) |
|---|
| 810 | 817 | { |
|---|
| 811 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 818 | + struct btrfs_block_group *block_group; |
|---|
| 812 | 819 | struct btrfs_path *path; |
|---|
| 813 | 820 | int ret; |
|---|
| 814 | 821 | |
|---|
| .. | .. |
|---|
| 842 | 849 | } |
|---|
| 843 | 850 | |
|---|
| 844 | 851 | static int add_free_space_extent(struct btrfs_trans_handle *trans, |
|---|
| 845 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 852 | + struct btrfs_block_group *block_group, |
|---|
| 846 | 853 | struct btrfs_path *path, |
|---|
| 847 | 854 | u64 start, u64 size) |
|---|
| 848 | 855 | { |
|---|
| .. | .. |
|---|
| 876 | 883 | new_key.offset = size; |
|---|
| 877 | 884 | |
|---|
| 878 | 885 | /* Search for a neighbor on the left. */ |
|---|
| 879 | | - if (start == block_group->key.objectid) |
|---|
| 886 | + if (start == block_group->start) |
|---|
| 880 | 887 | goto right; |
|---|
| 881 | 888 | key.objectid = start - 1; |
|---|
| 882 | 889 | key.type = (u8)-1; |
|---|
| .. | .. |
|---|
| 896 | 903 | |
|---|
| 897 | 904 | found_start = key.objectid; |
|---|
| 898 | 905 | found_end = key.objectid + key.offset; |
|---|
| 899 | | - ASSERT(found_start >= block_group->key.objectid && |
|---|
| 900 | | - found_end > block_group->key.objectid); |
|---|
| 906 | + ASSERT(found_start >= block_group->start && |
|---|
| 907 | + found_end > block_group->start); |
|---|
| 901 | 908 | ASSERT(found_start < start && found_end <= start); |
|---|
| 902 | 909 | |
|---|
| 903 | 910 | /* |
|---|
| .. | .. |
|---|
| 916 | 923 | |
|---|
| 917 | 924 | right: |
|---|
| 918 | 925 | /* Search for a neighbor on the right. */ |
|---|
| 919 | | - if (end == block_group->key.objectid + block_group->key.offset) |
|---|
| 926 | + if (end == block_group->start + block_group->length) |
|---|
| 920 | 927 | goto insert; |
|---|
| 921 | 928 | key.objectid = end; |
|---|
| 922 | 929 | key.type = (u8)-1; |
|---|
| .. | .. |
|---|
| 936 | 943 | |
|---|
| 937 | 944 | found_start = key.objectid; |
|---|
| 938 | 945 | found_end = key.objectid + key.offset; |
|---|
| 939 | | - ASSERT(found_start >= block_group->key.objectid && |
|---|
| 940 | | - found_end > block_group->key.objectid); |
|---|
| 946 | + ASSERT(found_start >= block_group->start && |
|---|
| 947 | + found_end > block_group->start); |
|---|
| 941 | 948 | ASSERT((found_start < start && found_end <= start) || |
|---|
| 942 | 949 | (found_start >= end && found_end > end)); |
|---|
| 943 | 950 | |
|---|
| .. | .. |
|---|
| 968 | 975 | return ret; |
|---|
| 969 | 976 | } |
|---|
| 970 | 977 | |
|---|
| 978 | +EXPORT_FOR_TESTS |
|---|
| 971 | 979 | int __add_to_free_space_tree(struct btrfs_trans_handle *trans, |
|---|
| 972 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 980 | + struct btrfs_block_group *block_group, |
|---|
| 973 | 981 | struct btrfs_path *path, u64 start, u64 size) |
|---|
| 974 | 982 | { |
|---|
| 975 | | - struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| 976 | 983 | struct btrfs_free_space_info *info; |
|---|
| 977 | 984 | u32 flags; |
|---|
| 978 | 985 | int ret; |
|---|
| .. | .. |
|---|
| 983 | 990 | return ret; |
|---|
| 984 | 991 | } |
|---|
| 985 | 992 | |
|---|
| 986 | | - info = search_free_space_info(NULL, fs_info, block_group, path, 0); |
|---|
| 993 | + info = search_free_space_info(NULL, block_group, path, 0); |
|---|
| 987 | 994 | if (IS_ERR(info)) |
|---|
| 988 | 995 | return PTR_ERR(info); |
|---|
| 989 | 996 | flags = btrfs_free_space_flags(path->nodes[0], info); |
|---|
| .. | .. |
|---|
| 1001 | 1008 | int add_to_free_space_tree(struct btrfs_trans_handle *trans, |
|---|
| 1002 | 1009 | u64 start, u64 size) |
|---|
| 1003 | 1010 | { |
|---|
| 1004 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 1011 | + struct btrfs_block_group *block_group; |
|---|
| 1005 | 1012 | struct btrfs_path *path; |
|---|
| 1006 | 1013 | int ret; |
|---|
| 1007 | 1014 | |
|---|
| .. | .. |
|---|
| 1039 | 1046 | * through the normal add/remove hooks. |
|---|
| 1040 | 1047 | */ |
|---|
| 1041 | 1048 | static int populate_free_space_tree(struct btrfs_trans_handle *trans, |
|---|
| 1042 | | - struct btrfs_block_group_cache *block_group) |
|---|
| 1049 | + struct btrfs_block_group *block_group) |
|---|
| 1043 | 1050 | { |
|---|
| 1044 | 1051 | struct btrfs_root *extent_root = trans->fs_info->extent_root; |
|---|
| 1045 | 1052 | struct btrfs_path *path, *path2; |
|---|
| .. | .. |
|---|
| 1071 | 1078 | * BLOCK_GROUP_ITEM, so an extent may precede the block group that it's |
|---|
| 1072 | 1079 | * contained in. |
|---|
| 1073 | 1080 | */ |
|---|
| 1074 | | - key.objectid = block_group->key.objectid; |
|---|
| 1081 | + key.objectid = block_group->start; |
|---|
| 1075 | 1082 | key.type = BTRFS_EXTENT_ITEM_KEY; |
|---|
| 1076 | 1083 | key.offset = 0; |
|---|
| 1077 | 1084 | |
|---|
| .. | .. |
|---|
| 1080 | 1087 | goto out_locked; |
|---|
| 1081 | 1088 | ASSERT(ret == 0); |
|---|
| 1082 | 1089 | |
|---|
| 1083 | | - start = block_group->key.objectid; |
|---|
| 1084 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 1090 | + start = block_group->start; |
|---|
| 1091 | + end = block_group->start + block_group->length; |
|---|
| 1085 | 1092 | while (1) { |
|---|
| 1086 | 1093 | btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); |
|---|
| 1087 | 1094 | |
|---|
| .. | .. |
|---|
| 1105 | 1112 | else |
|---|
| 1106 | 1113 | start += key.offset; |
|---|
| 1107 | 1114 | } else if (key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { |
|---|
| 1108 | | - if (key.objectid != block_group->key.objectid) |
|---|
| 1115 | + if (key.objectid != block_group->start) |
|---|
| 1109 | 1116 | break; |
|---|
| 1110 | 1117 | } |
|---|
| 1111 | 1118 | |
|---|
| .. | .. |
|---|
| 1136 | 1143 | struct btrfs_trans_handle *trans; |
|---|
| 1137 | 1144 | struct btrfs_root *tree_root = fs_info->tree_root; |
|---|
| 1138 | 1145 | struct btrfs_root *free_space_root; |
|---|
| 1139 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 1146 | + struct btrfs_block_group *block_group; |
|---|
| 1140 | 1147 | struct rb_node *node; |
|---|
| 1141 | 1148 | int ret; |
|---|
| 1142 | 1149 | |
|---|
| .. | .. |
|---|
| 1145 | 1152 | return PTR_ERR(trans); |
|---|
| 1146 | 1153 | |
|---|
| 1147 | 1154 | set_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags); |
|---|
| 1148 | | - free_space_root = btrfs_create_tree(trans, fs_info, |
|---|
| 1155 | + set_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags); |
|---|
| 1156 | + free_space_root = btrfs_create_tree(trans, |
|---|
| 1149 | 1157 | BTRFS_FREE_SPACE_TREE_OBJECTID); |
|---|
| 1150 | 1158 | if (IS_ERR(free_space_root)) { |
|---|
| 1151 | 1159 | ret = PTR_ERR(free_space_root); |
|---|
| .. | .. |
|---|
| 1155 | 1163 | |
|---|
| 1156 | 1164 | node = rb_first(&fs_info->block_group_cache_tree); |
|---|
| 1157 | 1165 | while (node) { |
|---|
| 1158 | | - block_group = rb_entry(node, struct btrfs_block_group_cache, |
|---|
| 1166 | + block_group = rb_entry(node, struct btrfs_block_group, |
|---|
| 1159 | 1167 | cache_node); |
|---|
| 1160 | 1168 | ret = populate_free_space_tree(trans, block_group); |
|---|
| 1161 | 1169 | if (ret) |
|---|
| .. | .. |
|---|
| 1166 | 1174 | btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE); |
|---|
| 1167 | 1175 | btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID); |
|---|
| 1168 | 1176 | clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags); |
|---|
| 1177 | + ret = btrfs_commit_transaction(trans); |
|---|
| 1169 | 1178 | |
|---|
| 1170 | | - return btrfs_commit_transaction(trans); |
|---|
| 1179 | + /* |
|---|
| 1180 | + * Now that we've committed the transaction any reading of our commit |
|---|
| 1181 | + * root will be safe, so we can cache from the free space tree now. |
|---|
| 1182 | + */ |
|---|
| 1183 | + clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags); |
|---|
| 1184 | + return ret; |
|---|
| 1171 | 1185 | |
|---|
| 1172 | 1186 | abort: |
|---|
| 1173 | 1187 | clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags); |
|---|
| 1188 | + clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags); |
|---|
| 1174 | 1189 | btrfs_abort_transaction(trans, ret); |
|---|
| 1175 | 1190 | btrfs_end_transaction(trans); |
|---|
| 1176 | 1191 | return ret; |
|---|
| .. | .. |
|---|
| 1243 | 1258 | list_del(&free_space_root->dirty_list); |
|---|
| 1244 | 1259 | |
|---|
| 1245 | 1260 | btrfs_tree_lock(free_space_root->node); |
|---|
| 1246 | | - clean_tree_block(fs_info, free_space_root->node); |
|---|
| 1261 | + btrfs_clean_tree_block(free_space_root->node); |
|---|
| 1247 | 1262 | btrfs_tree_unlock(free_space_root->node); |
|---|
| 1248 | 1263 | btrfs_free_tree_block(trans, free_space_root, free_space_root->node, |
|---|
| 1249 | 1264 | 0, 1); |
|---|
| 1250 | 1265 | |
|---|
| 1251 | | - free_extent_buffer(free_space_root->node); |
|---|
| 1252 | | - free_extent_buffer(free_space_root->commit_root); |
|---|
| 1253 | | - kfree(free_space_root); |
|---|
| 1266 | + btrfs_put_root(free_space_root); |
|---|
| 1254 | 1267 | |
|---|
| 1255 | 1268 | return btrfs_commit_transaction(trans); |
|---|
| 1256 | 1269 | |
|---|
| .. | .. |
|---|
| 1261 | 1274 | } |
|---|
| 1262 | 1275 | |
|---|
| 1263 | 1276 | static int __add_block_group_free_space(struct btrfs_trans_handle *trans, |
|---|
| 1264 | | - struct btrfs_block_group_cache *block_group, |
|---|
| 1277 | + struct btrfs_block_group *block_group, |
|---|
| 1265 | 1278 | struct btrfs_path *path) |
|---|
| 1266 | 1279 | { |
|---|
| 1267 | 1280 | int ret; |
|---|
| .. | .. |
|---|
| 1273 | 1286 | return ret; |
|---|
| 1274 | 1287 | |
|---|
| 1275 | 1288 | return __add_to_free_space_tree(trans, block_group, path, |
|---|
| 1276 | | - block_group->key.objectid, |
|---|
| 1277 | | - block_group->key.offset); |
|---|
| 1289 | + block_group->start, |
|---|
| 1290 | + block_group->length); |
|---|
| 1278 | 1291 | } |
|---|
| 1279 | 1292 | |
|---|
| 1280 | 1293 | int add_block_group_free_space(struct btrfs_trans_handle *trans, |
|---|
| 1281 | | - struct btrfs_block_group_cache *block_group) |
|---|
| 1294 | + struct btrfs_block_group *block_group) |
|---|
| 1282 | 1295 | { |
|---|
| 1283 | 1296 | struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| 1284 | 1297 | struct btrfs_path *path = NULL; |
|---|
| .. | .. |
|---|
| 1308 | 1321 | } |
|---|
| 1309 | 1322 | |
|---|
| 1310 | 1323 | int remove_block_group_free_space(struct btrfs_trans_handle *trans, |
|---|
| 1311 | | - struct btrfs_block_group_cache *block_group) |
|---|
| 1324 | + struct btrfs_block_group *block_group) |
|---|
| 1312 | 1325 | { |
|---|
| 1313 | 1326 | struct btrfs_root *root = trans->fs_info->free_space_root; |
|---|
| 1314 | 1327 | struct btrfs_path *path; |
|---|
| .. | .. |
|---|
| 1332 | 1345 | goto out; |
|---|
| 1333 | 1346 | } |
|---|
| 1334 | 1347 | |
|---|
| 1335 | | - start = block_group->key.objectid; |
|---|
| 1336 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 1348 | + start = block_group->start; |
|---|
| 1349 | + end = block_group->start + block_group->length; |
|---|
| 1337 | 1350 | |
|---|
| 1338 | 1351 | key.objectid = end - 1; |
|---|
| 1339 | 1352 | key.type = (u8)-1; |
|---|
| .. | .. |
|---|
| 1351 | 1364 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); |
|---|
| 1352 | 1365 | |
|---|
| 1353 | 1366 | if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { |
|---|
| 1354 | | - ASSERT(found_key.objectid == block_group->key.objectid); |
|---|
| 1355 | | - ASSERT(found_key.offset == block_group->key.offset); |
|---|
| 1367 | + ASSERT(found_key.objectid == block_group->start); |
|---|
| 1368 | + ASSERT(found_key.offset == block_group->length); |
|---|
| 1356 | 1369 | done = 1; |
|---|
| 1357 | 1370 | nr++; |
|---|
| 1358 | 1371 | path->slots[0]--; |
|---|
| .. | .. |
|---|
| 1387 | 1400 | struct btrfs_path *path, |
|---|
| 1388 | 1401 | u32 expected_extent_count) |
|---|
| 1389 | 1402 | { |
|---|
| 1390 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 1403 | + struct btrfs_block_group *block_group; |
|---|
| 1391 | 1404 | struct btrfs_fs_info *fs_info; |
|---|
| 1392 | 1405 | struct btrfs_root *root; |
|---|
| 1393 | 1406 | struct btrfs_key key; |
|---|
| .. | .. |
|---|
| 1403 | 1416 | fs_info = block_group->fs_info; |
|---|
| 1404 | 1417 | root = fs_info->free_space_root; |
|---|
| 1405 | 1418 | |
|---|
| 1406 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 1419 | + end = block_group->start + block_group->length; |
|---|
| 1407 | 1420 | |
|---|
| 1408 | 1421 | while (1) { |
|---|
| 1409 | 1422 | ret = btrfs_next_item(root, path); |
|---|
| .. | .. |
|---|
| 1450 | 1463 | if (extent_count != expected_extent_count) { |
|---|
| 1451 | 1464 | btrfs_err(fs_info, |
|---|
| 1452 | 1465 | "incorrect extent count for %llu; counted %u, expected %u", |
|---|
| 1453 | | - block_group->key.objectid, extent_count, |
|---|
| 1466 | + block_group->start, extent_count, |
|---|
| 1454 | 1467 | expected_extent_count); |
|---|
| 1455 | 1468 | ASSERT(0); |
|---|
| 1456 | 1469 | ret = -EIO; |
|---|
| .. | .. |
|---|
| 1468 | 1481 | struct btrfs_path *path, |
|---|
| 1469 | 1482 | u32 expected_extent_count) |
|---|
| 1470 | 1483 | { |
|---|
| 1471 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 1484 | + struct btrfs_block_group *block_group; |
|---|
| 1472 | 1485 | struct btrfs_fs_info *fs_info; |
|---|
| 1473 | 1486 | struct btrfs_root *root; |
|---|
| 1474 | 1487 | struct btrfs_key key; |
|---|
| .. | .. |
|---|
| 1481 | 1494 | fs_info = block_group->fs_info; |
|---|
| 1482 | 1495 | root = fs_info->free_space_root; |
|---|
| 1483 | 1496 | |
|---|
| 1484 | | - end = block_group->key.objectid + block_group->key.offset; |
|---|
| 1497 | + end = block_group->start + block_group->length; |
|---|
| 1485 | 1498 | |
|---|
| 1486 | 1499 | while (1) { |
|---|
| 1487 | 1500 | ret = btrfs_next_item(root, path); |
|---|
| .. | .. |
|---|
| 1512 | 1525 | if (extent_count != expected_extent_count) { |
|---|
| 1513 | 1526 | btrfs_err(fs_info, |
|---|
| 1514 | 1527 | "incorrect extent count for %llu; counted %u, expected %u", |
|---|
| 1515 | | - block_group->key.objectid, extent_count, |
|---|
| 1528 | + block_group->start, extent_count, |
|---|
| 1516 | 1529 | expected_extent_count); |
|---|
| 1517 | 1530 | ASSERT(0); |
|---|
| 1518 | 1531 | ret = -EIO; |
|---|
| .. | .. |
|---|
| 1528 | 1541 | |
|---|
| 1529 | 1542 | int load_free_space_tree(struct btrfs_caching_control *caching_ctl) |
|---|
| 1530 | 1543 | { |
|---|
| 1531 | | - struct btrfs_block_group_cache *block_group; |
|---|
| 1532 | | - struct btrfs_fs_info *fs_info; |
|---|
| 1544 | + struct btrfs_block_group *block_group; |
|---|
| 1533 | 1545 | struct btrfs_free_space_info *info; |
|---|
| 1534 | 1546 | struct btrfs_path *path; |
|---|
| 1535 | 1547 | u32 extent_count, flags; |
|---|
| 1536 | 1548 | int ret; |
|---|
| 1537 | 1549 | |
|---|
| 1538 | 1550 | block_group = caching_ctl->block_group; |
|---|
| 1539 | | - fs_info = block_group->fs_info; |
|---|
| 1540 | 1551 | |
|---|
| 1541 | 1552 | path = btrfs_alloc_path(); |
|---|
| 1542 | 1553 | if (!path) |
|---|
| .. | .. |
|---|
| 1550 | 1561 | path->search_commit_root = 1; |
|---|
| 1551 | 1562 | path->reada = READA_FORWARD; |
|---|
| 1552 | 1563 | |
|---|
| 1553 | | - info = search_free_space_info(NULL, fs_info, block_group, path, 0); |
|---|
| 1564 | + info = search_free_space_info(NULL, block_group, path, 0); |
|---|
| 1554 | 1565 | if (IS_ERR(info)) { |
|---|
| 1555 | 1566 | ret = PTR_ERR(info); |
|---|
| 1556 | 1567 | goto out; |
|---|