diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 1ea10731797a..3bde17ff14c0 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -532,6 +532,19 @@ out: | |||
532 | return ret; | 532 | return ret; |
533 | } | 533 | } |
534 | 534 | ||
535 | /** | ||
536 | * __btrfs_write_out_cache - write out cached info to an inode | ||
537 | * @root - the root the inode belongs to | ||
538 | * @ctl - the free space cache we are going to write out | ||
539 | * @block_group - the block_group for this cache if it belongs to a block_group | ||
540 | * @trans - the trans handle | ||
541 | * @path - the path to use | ||
542 | * @offset - the offset for the key we'll insert | ||
543 | * | ||
544 | * This function writes out a free space cache struct to disk for quick recovery | ||
545 | * on mount. This will return 0 if it was successfull in writing the cache out, | ||
546 | * and -1 if it was not. | ||
547 | */ | ||
535 | int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | 548 | int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, |
536 | struct btrfs_free_space_ctl *ctl, | 549 | struct btrfs_free_space_ctl *ctl, |
537 | struct btrfs_block_group_cache *block_group, | 550 | struct btrfs_block_group_cache *block_group, |
@@ -555,7 +568,8 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
555 | int index = 0, num_pages = 0; | 568 | int index = 0, num_pages = 0; |
556 | int entries = 0; | 569 | int entries = 0; |
557 | int bitmaps = 0; | 570 | int bitmaps = 0; |
558 | int ret = -1; | 571 | int ret; |
572 | int err = -1; | ||
559 | bool next_page = false; | 573 | bool next_page = false; |
560 | bool out_of_space = false; | 574 | bool out_of_space = false; |
561 | 575 | ||
@@ -563,7 +577,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
563 | 577 | ||
564 | node = rb_first(&ctl->free_space_offset); | 578 | node = rb_first(&ctl->free_space_offset); |
565 | if (!node) | 579 | if (!node) |
566 | return 0; | 580 | return -1; |
567 | 581 | ||
568 | if (!i_size_read(inode)) | 582 | if (!i_size_read(inode)) |
569 | return -1; | 583 | return -1; |
@@ -767,7 +781,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
767 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | 781 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
768 | i_size_read(inode) - 1, &cached_state, | 782 | i_size_read(inode) - 1, &cached_state, |
769 | GFP_NOFS); | 783 | GFP_NOFS); |
770 | ret = 0; | ||
771 | goto out; | 784 | goto out; |
772 | } | 785 | } |
773 | 786 | ||
@@ -789,10 +802,8 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
789 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | 802 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
790 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); | 803 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); |
791 | 804 | ||
792 | if (ret) { | 805 | if (ret) |
793 | ret = 0; | ||
794 | goto out; | 806 | goto out; |
795 | } | ||
796 | 807 | ||
797 | BTRFS_I(inode)->generation = trans->transid; | 808 | BTRFS_I(inode)->generation = trans->transid; |
798 | 809 | ||
@@ -804,7 +815,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
804 | 815 | ||
805 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 816 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
806 | if (ret < 0) { | 817 | if (ret < 0) { |
807 | ret = -1; | ||
808 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1, | 818 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1, |
809 | EXTENT_DIRTY | EXTENT_DELALLOC | | 819 | EXTENT_DIRTY | EXTENT_DELALLOC | |
810 | EXTENT_DO_ACCOUNTING, 0, 0, NULL, GFP_NOFS); | 820 | EXTENT_DO_ACCOUNTING, 0, 0, NULL, GFP_NOFS); |
@@ -818,7 +828,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
818 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 828 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
819 | if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID || | 829 | if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID || |
820 | found_key.offset != offset) { | 830 | found_key.offset != offset) { |
821 | ret = -1; | ||
822 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1, | 831 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1, |
823 | EXTENT_DIRTY | EXTENT_DELALLOC | | 832 | EXTENT_DIRTY | EXTENT_DELALLOC | |
824 | EXTENT_DO_ACCOUNTING, 0, 0, NULL, | 833 | EXTENT_DO_ACCOUNTING, 0, 0, NULL, |
@@ -835,16 +844,15 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
835 | btrfs_mark_buffer_dirty(leaf); | 844 | btrfs_mark_buffer_dirty(leaf); |
836 | btrfs_release_path(path); | 845 | btrfs_release_path(path); |
837 | 846 | ||
838 | ret = 1; | 847 | err = 0; |
839 | |||
840 | out: | 848 | out: |
841 | kfree(pages); | 849 | kfree(pages); |
842 | if (ret != 1) { | 850 | if (err) { |
843 | invalidate_inode_pages2_range(inode->i_mapping, 0, index); | 851 | invalidate_inode_pages2_range(inode->i_mapping, 0, index); |
844 | BTRFS_I(inode)->generation = 0; | 852 | BTRFS_I(inode)->generation = 0; |
845 | } | 853 | } |
846 | btrfs_update_inode(trans, root, inode); | 854 | btrfs_update_inode(trans, root, inode); |
847 | return ret; | 855 | return err; |
848 | } | 856 | } |
849 | 857 | ||
850 | int btrfs_write_out_cache(struct btrfs_root *root, | 858 | int btrfs_write_out_cache(struct btrfs_root *root, |
@@ -871,14 +879,16 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
871 | 879 | ||
872 | ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans, | 880 | ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans, |
873 | path, block_group->key.objectid); | 881 | path, block_group->key.objectid); |
874 | if (ret < 0) { | 882 | if (ret) { |
883 | btrfs_delalloc_release_metadata(inode, inode->i_size); | ||
875 | spin_lock(&block_group->lock); | 884 | spin_lock(&block_group->lock); |
876 | block_group->disk_cache_state = BTRFS_DC_ERROR; | 885 | block_group->disk_cache_state = BTRFS_DC_ERROR; |
877 | spin_unlock(&block_group->lock); | 886 | spin_unlock(&block_group->lock); |
878 | ret = 0; | 887 | ret = 0; |
879 | 888 | #ifdef DEBUG | |
880 | printk(KERN_ERR "btrfs: failed to write free space cace " | 889 | printk(KERN_ERR "btrfs: failed to write free space cace " |
881 | "for block group %llu\n", block_group->key.objectid); | 890 | "for block group %llu\n", block_group->key.objectid); |
891 | #endif | ||
882 | } | 892 | } |
883 | 893 | ||
884 | iput(inode); | 894 | iput(inode); |
@@ -2662,9 +2672,13 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root, | |||
2662 | return 0; | 2672 | return 0; |
2663 | 2673 | ||
2664 | ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0); | 2674 | ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0); |
2665 | if (ret < 0) | 2675 | if (ret) { |
2676 | btrfs_delalloc_release_metadata(inode, inode->i_size); | ||
2677 | #ifdef DEBUG | ||
2666 | printk(KERN_ERR "btrfs: failed to write free ino cache " | 2678 | printk(KERN_ERR "btrfs: failed to write free ino cache " |
2667 | "for root %llu\n", root->root_key.objectid); | 2679 | "for root %llu\n", root->root_key.objectid); |
2680 | #endif | ||
2681 | } | ||
2668 | 2682 | ||
2669 | iput(inode); | 2683 | iput(inode); |
2670 | return ret; | 2684 | return ret; |