diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 82 |
1 files changed, 78 insertions, 4 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 13575de85543..f561c953205b 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "free-space-cache.h" | 24 | #include "free-space-cache.h" |
25 | #include "transaction.h" | 25 | #include "transaction.h" |
26 | #include "disk-io.h" | 26 | #include "disk-io.h" |
27 | #include "extent_io.h" | ||
27 | 28 | ||
28 | #define BITS_PER_BITMAP (PAGE_CACHE_SIZE * 8) | 29 | #define BITS_PER_BITMAP (PAGE_CACHE_SIZE * 8) |
29 | #define MAX_CACHE_BYTES_PER_GIG (32 * 1024) | 30 | #define MAX_CACHE_BYTES_PER_GIG (32 * 1024) |
@@ -224,6 +225,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, | |||
224 | u64 num_entries; | 225 | u64 num_entries; |
225 | u64 num_bitmaps; | 226 | u64 num_bitmaps; |
226 | u64 generation; | 227 | u64 generation; |
228 | u64 used = btrfs_block_group_used(&block_group->item); | ||
227 | u32 cur_crc = ~(u32)0; | 229 | u32 cur_crc = ~(u32)0; |
228 | pgoff_t index = 0; | 230 | pgoff_t index = 0; |
229 | unsigned long first_page_offset; | 231 | unsigned long first_page_offset; |
@@ -469,6 +471,17 @@ next: | |||
469 | index++; | 471 | index++; |
470 | } | 472 | } |
471 | 473 | ||
474 | spin_lock(&block_group->tree_lock); | ||
475 | if (block_group->free_space != (block_group->key.offset - used - | ||
476 | block_group->bytes_super)) { | ||
477 | spin_unlock(&block_group->tree_lock); | ||
478 | printk(KERN_ERR "block group %llu has an wrong amount of free " | ||
479 | "space\n", block_group->key.objectid); | ||
480 | ret = 0; | ||
481 | goto free_cache; | ||
482 | } | ||
483 | spin_unlock(&block_group->tree_lock); | ||
484 | |||
472 | ret = 1; | 485 | ret = 1; |
473 | out: | 486 | out: |
474 | kfree(checksums); | 487 | kfree(checksums); |
@@ -497,8 +510,11 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
497 | struct list_head *pos, *n; | 510 | struct list_head *pos, *n; |
498 | struct page *page; | 511 | struct page *page; |
499 | struct extent_state *cached_state = NULL; | 512 | struct extent_state *cached_state = NULL; |
513 | struct btrfs_free_cluster *cluster = NULL; | ||
514 | struct extent_io_tree *unpin = NULL; | ||
500 | struct list_head bitmap_list; | 515 | struct list_head bitmap_list; |
501 | struct btrfs_key key; | 516 | struct btrfs_key key; |
517 | u64 start, end, len; | ||
502 | u64 bytes = 0; | 518 | u64 bytes = 0; |
503 | u32 *crc, *checksums; | 519 | u32 *crc, *checksums; |
504 | pgoff_t index = 0, last_index = 0; | 520 | pgoff_t index = 0, last_index = 0; |
@@ -507,6 +523,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
507 | int entries = 0; | 523 | int entries = 0; |
508 | int bitmaps = 0; | 524 | int bitmaps = 0; |
509 | int ret = 0; | 525 | int ret = 0; |
526 | bool next_page = false; | ||
510 | 527 | ||
511 | root = root->fs_info->tree_root; | 528 | root = root->fs_info->tree_root; |
512 | 529 | ||
@@ -553,6 +570,18 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
553 | */ | 570 | */ |
554 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); | 571 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); |
555 | 572 | ||
573 | /* Get the cluster for this block_group if it exists */ | ||
574 | if (!list_empty(&block_group->cluster_list)) | ||
575 | cluster = list_entry(block_group->cluster_list.next, | ||
576 | struct btrfs_free_cluster, | ||
577 | block_group_list); | ||
578 | |||
579 | /* | ||
580 | * We shouldn't have switched the pinned extents yet so this is the | ||
581 | * right one | ||
582 | */ | ||
583 | unpin = root->fs_info->pinned_extents; | ||
584 | |||
556 | /* | 585 | /* |
557 | * Lock all pages first so we can lock the extent safely. | 586 | * Lock all pages first so we can lock the extent safely. |
558 | * | 587 | * |
@@ -582,6 +611,12 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
582 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, | 611 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, |
583 | 0, &cached_state, GFP_NOFS); | 612 | 0, &cached_state, GFP_NOFS); |
584 | 613 | ||
614 | /* | ||
615 | * When searching for pinned extents, we need to start at our start | ||
616 | * offset. | ||
617 | */ | ||
618 | start = block_group->key.objectid; | ||
619 | |||
585 | /* Write out the extent entries */ | 620 | /* Write out the extent entries */ |
586 | do { | 621 | do { |
587 | struct btrfs_free_space_entry *entry; | 622 | struct btrfs_free_space_entry *entry; |
@@ -589,6 +624,8 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
589 | unsigned long offset = 0; | 624 | unsigned long offset = 0; |
590 | unsigned long start_offset = 0; | 625 | unsigned long start_offset = 0; |
591 | 626 | ||
627 | next_page = false; | ||
628 | |||
592 | if (index == 0) { | 629 | if (index == 0) { |
593 | start_offset = first_page_offset; | 630 | start_offset = first_page_offset; |
594 | offset = start_offset; | 631 | offset = start_offset; |
@@ -600,7 +637,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
600 | entry = addr + start_offset; | 637 | entry = addr + start_offset; |
601 | 638 | ||
602 | memset(addr, 0, PAGE_CACHE_SIZE); | 639 | memset(addr, 0, PAGE_CACHE_SIZE); |
603 | while (1) { | 640 | while (node && !next_page) { |
604 | struct btrfs_free_space *e; | 641 | struct btrfs_free_space *e; |
605 | 642 | ||
606 | e = rb_entry(node, struct btrfs_free_space, offset_index); | 643 | e = rb_entry(node, struct btrfs_free_space, offset_index); |
@@ -616,12 +653,49 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
616 | entry->type = BTRFS_FREE_SPACE_EXTENT; | 653 | entry->type = BTRFS_FREE_SPACE_EXTENT; |
617 | } | 654 | } |
618 | node = rb_next(node); | 655 | node = rb_next(node); |
619 | if (!node) | 656 | if (!node && cluster) { |
620 | break; | 657 | node = rb_first(&cluster->root); |
658 | cluster = NULL; | ||
659 | } | ||
621 | offset += sizeof(struct btrfs_free_space_entry); | 660 | offset += sizeof(struct btrfs_free_space_entry); |
622 | if (offset + sizeof(struct btrfs_free_space_entry) >= | 661 | if (offset + sizeof(struct btrfs_free_space_entry) >= |
623 | PAGE_CACHE_SIZE) | 662 | PAGE_CACHE_SIZE) |
663 | next_page = true; | ||
664 | entry++; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * We want to add any pinned extents to our free space cache | ||
669 | * so we don't leak the space | ||
670 | */ | ||
671 | while (!next_page && (start < block_group->key.objectid + | ||
672 | block_group->key.offset)) { | ||
673 | ret = find_first_extent_bit(unpin, start, &start, &end, | ||
674 | EXTENT_DIRTY); | ||
675 | if (ret) { | ||
676 | ret = 0; | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | /* This pinned extent is out of our range */ | ||
681 | if (start >= block_group->key.objectid + | ||
682 | block_group->key.offset) | ||
624 | break; | 683 | break; |
684 | |||
685 | len = block_group->key.objectid + | ||
686 | block_group->key.offset - start; | ||
687 | len = min(len, end + 1 - start); | ||
688 | |||
689 | entries++; | ||
690 | entry->offset = cpu_to_le64(start); | ||
691 | entry->bytes = cpu_to_le64(len); | ||
692 | entry->type = BTRFS_FREE_SPACE_EXTENT; | ||
693 | |||
694 | start = end + 1; | ||
695 | offset += sizeof(struct btrfs_free_space_entry); | ||
696 | if (offset + sizeof(struct btrfs_free_space_entry) >= | ||
697 | PAGE_CACHE_SIZE) | ||
698 | next_page = true; | ||
625 | entry++; | 699 | entry++; |
626 | } | 700 | } |
627 | *crc = ~(u32)0; | 701 | *crc = ~(u32)0; |
@@ -652,7 +726,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
652 | page_cache_release(page); | 726 | page_cache_release(page); |
653 | 727 | ||
654 | index++; | 728 | index++; |
655 | } while (node); | 729 | } while (node || next_page); |
656 | 730 | ||
657 | /* Write out the bitmaps */ | 731 | /* Write out the bitmaps */ |
658 | list_for_each_safe(pos, n, &bitmap_list) { | 732 | list_for_each_safe(pos, n, &bitmap_list) { |