diff options
author | Josef Bacik <josef@redhat.com> | 2011-08-30 10:19:10 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-10-19 15:12:42 -0400 |
commit | c09544e07f8cdc455ed8615d4c067d694c33bd18 (patch) | |
tree | c9943e56457ac64e2223396841e043e4514462e0 /fs/btrfs/free-space-cache.c | |
parent | 300e4f8a56f263797568c95b71c949f9f02e4534 (diff) |
Btrfs: handle enospc accounting for free space inodes
Since free space inodes now use normal checksumming we need to make sure to
account for their metadata use. So reserve metadata space, and then if we fail
to write out the metadata we can just release it, otherwise it will be freed up
when the io completes. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
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; |