diff options
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 73 |
1 files changed, 64 insertions, 9 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index af99b78b288e..5edcee3a617f 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -414,11 +414,29 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro | |||
| 414 | u64 *offset, u64 *bytes) | 414 | u64 *offset, u64 *bytes) |
| 415 | { | 415 | { |
| 416 | u64 end; | 416 | u64 end; |
| 417 | u64 search_start, search_bytes; | ||
| 418 | int ret; | ||
| 417 | 419 | ||
| 418 | again: | 420 | again: |
| 419 | end = bitmap_info->offset + | 421 | end = bitmap_info->offset + |
| 420 | (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; | 422 | (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; |
| 421 | 423 | ||
| 424 | /* | ||
| 425 | * XXX - this can go away after a few releases. | ||
| 426 | * | ||
| 427 | * since the only user of btrfs_remove_free_space is the tree logging | ||
| 428 | * stuff, and the only way to test that is under crash conditions, we | ||
| 429 | * want to have this debug stuff here just in case somethings not | ||
| 430 | * working. Search the bitmap for the space we are trying to use to | ||
| 431 | * make sure its actually there. If its not there then we need to stop | ||
| 432 | * because something has gone wrong. | ||
| 433 | */ | ||
| 434 | search_start = *offset; | ||
| 435 | search_bytes = *bytes; | ||
| 436 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 437 | &search_bytes); | ||
| 438 | BUG_ON(ret < 0 || search_start != *offset); | ||
| 439 | |||
| 422 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { | 440 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { |
| 423 | bitmap_clear_bits(block_group, bitmap_info, *offset, | 441 | bitmap_clear_bits(block_group, bitmap_info, *offset, |
| 424 | end - *offset + 1); | 442 | end - *offset + 1); |
| @@ -430,6 +448,7 @@ again: | |||
| 430 | } | 448 | } |
| 431 | 449 | ||
| 432 | if (*bytes) { | 450 | if (*bytes) { |
| 451 | struct rb_node *next = rb_next(&bitmap_info->offset_index); | ||
| 433 | if (!bitmap_info->bytes) { | 452 | if (!bitmap_info->bytes) { |
| 434 | unlink_free_space(block_group, bitmap_info); | 453 | unlink_free_space(block_group, bitmap_info); |
| 435 | kfree(bitmap_info->bitmap); | 454 | kfree(bitmap_info->bitmap); |
| @@ -438,16 +457,36 @@ again: | |||
| 438 | recalculate_thresholds(block_group); | 457 | recalculate_thresholds(block_group); |
| 439 | } | 458 | } |
| 440 | 459 | ||
| 441 | bitmap_info = tree_search_offset(block_group, | 460 | /* |
| 442 | offset_to_bitmap(block_group, | 461 | * no entry after this bitmap, but we still have bytes to |
| 443 | *offset), | 462 | * remove, so something has gone wrong. |
| 444 | 1, 0); | 463 | */ |
| 445 | if (!bitmap_info) | 464 | if (!next) |
| 446 | return -EINVAL; | 465 | return -EINVAL; |
| 447 | 466 | ||
| 467 | bitmap_info = rb_entry(next, struct btrfs_free_space, | ||
| 468 | offset_index); | ||
| 469 | |||
| 470 | /* | ||
| 471 | * if the next entry isn't a bitmap we need to return to let the | ||
| 472 | * extent stuff do its work. | ||
| 473 | */ | ||
| 448 | if (!bitmap_info->bitmap) | 474 | if (!bitmap_info->bitmap) |
| 449 | return -EAGAIN; | 475 | return -EAGAIN; |
| 450 | 476 | ||
| 477 | /* | ||
| 478 | * Ok the next item is a bitmap, but it may not actually hold | ||
| 479 | * the information for the rest of this free space stuff, so | ||
| 480 | * look for it, and if we don't find it return so we can try | ||
| 481 | * everything over again. | ||
| 482 | */ | ||
| 483 | search_start = *offset; | ||
| 484 | search_bytes = *bytes; | ||
| 485 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 486 | &search_bytes); | ||
| 487 | if (ret < 0 || search_start != *offset) | ||
| 488 | return -EAGAIN; | ||
| 489 | |||
| 451 | goto again; | 490 | goto again; |
| 452 | } else if (!bitmap_info->bytes) { | 491 | } else if (!bitmap_info->bytes) { |
| 453 | unlink_free_space(block_group, bitmap_info); | 492 | unlink_free_space(block_group, bitmap_info); |
| @@ -644,8 +683,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
| 644 | again: | 683 | again: |
| 645 | info = tree_search_offset(block_group, offset, 0, 0); | 684 | info = tree_search_offset(block_group, offset, 0, 0); |
| 646 | if (!info) { | 685 | if (!info) { |
| 647 | WARN_ON(1); | 686 | /* |
| 648 | goto out_lock; | 687 | * oops didn't find an extent that matched the space we wanted |
| 688 | * to remove, look for a bitmap instead | ||
| 689 | */ | ||
| 690 | info = tree_search_offset(block_group, | ||
| 691 | offset_to_bitmap(block_group, offset), | ||
| 692 | 1, 0); | ||
| 693 | if (!info) { | ||
| 694 | WARN_ON(1); | ||
| 695 | goto out_lock; | ||
| 696 | } | ||
| 649 | } | 697 | } |
| 650 | 698 | ||
| 651 | if (info->bytes < bytes && rb_next(&info->offset_index)) { | 699 | if (info->bytes < bytes && rb_next(&info->offset_index)) { |
| @@ -957,8 +1005,15 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, | |||
| 957 | if (cluster->block_group != block_group) | 1005 | if (cluster->block_group != block_group) |
| 958 | goto out; | 1006 | goto out; |
| 959 | 1007 | ||
| 960 | entry = tree_search_offset(block_group, search_start, 0, 0); | 1008 | /* |
| 961 | 1009 | * search_start is the beginning of the bitmap, but at some point it may | |
| 1010 | * be a good idea to point to the actual start of the free area in the | ||
| 1011 | * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only | ||
| 1012 | * to 1 to make sure we get the bitmap entry | ||
| 1013 | */ | ||
| 1014 | entry = tree_search_offset(block_group, | ||
| 1015 | offset_to_bitmap(block_group, search_start), | ||
| 1016 | 1, 0); | ||
| 962 | if (!entry || !entry->bitmap) | 1017 | if (!entry || !entry->bitmap) |
| 963 | goto out; | 1018 | goto out; |
| 964 | 1019 | ||
