aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-08-30 10:19:10 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:42 -0400
commitc09544e07f8cdc455ed8615d4c067d694c33bd18 (patch)
treec9943e56457ac64e2223396841e043e4514462e0 /fs/btrfs
parent300e4f8a56f263797568c95b71c949f9f02e4534 (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')
-rw-r--r--fs/btrfs/extent-tree.c18
-rw-r--r--fs/btrfs/free-space-cache.c44
-rw-r--r--fs/btrfs/inode-map.c6
-rw-r--r--fs/btrfs/inode.c2
4 files changed, 47 insertions, 23 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 1f1d3e8dcec9..ccdc4d12e8d4 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2755,16 +2755,20 @@ again:
2755 num_pages *= 16; 2755 num_pages *= 16;
2756 num_pages *= PAGE_CACHE_SIZE; 2756 num_pages *= PAGE_CACHE_SIZE;
2757 2757
2758 ret = btrfs_check_data_free_space(inode, num_pages); 2758 ret = btrfs_delalloc_reserve_space(inode, num_pages);
2759 if (ret) 2759 if (ret)
2760 goto out_put; 2760 goto out_put;
2761 2761
2762 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, 2762 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
2763 num_pages, num_pages, 2763 num_pages, num_pages,
2764 &alloc_hint); 2764 &alloc_hint);
2765 if (!ret) 2765 if (!ret) {
2766 dcs = BTRFS_DC_SETUP; 2766 dcs = BTRFS_DC_SETUP;
2767 btrfs_free_reserved_data_space(inode, num_pages); 2767 btrfs_free_reserved_data_space(inode, num_pages);
2768 } else {
2769 btrfs_delalloc_release_space(inode, num_pages);
2770 }
2771
2768out_put: 2772out_put:
2769 iput(inode); 2773 iput(inode);
2770out_free: 2774out_free:
@@ -4002,9 +4006,13 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
4002 struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; 4006 struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
4003 u64 to_reserve = 0; 4007 u64 to_reserve = 0;
4004 unsigned nr_extents = 0; 4008 unsigned nr_extents = 0;
4009 int flush = 1;
4005 int ret; 4010 int ret;
4006 4011
4007 if (btrfs_transaction_in_commit(root->fs_info)) 4012 if (btrfs_is_free_space_inode(root, inode))
4013 flush = 0;
4014
4015 if (flush && btrfs_transaction_in_commit(root->fs_info))
4008 schedule_timeout(1); 4016 schedule_timeout(1);
4009 4017
4010 num_bytes = ALIGN(num_bytes, root->sectorsize); 4018 num_bytes = ALIGN(num_bytes, root->sectorsize);
@@ -4023,7 +4031,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
4023 to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); 4031 to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
4024 spin_unlock(&BTRFS_I(inode)->lock); 4032 spin_unlock(&BTRFS_I(inode)->lock);
4025 4033
4026 ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); 4034 ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, flush);
4027 if (ret) { 4035 if (ret) {
4028 u64 to_free = 0; 4036 u64 to_free = 0;
4029 unsigned dropped; 4037 unsigned dropped;
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 */
535int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, 548int __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
840out: 848out:
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
850int btrfs_write_out_cache(struct btrfs_root *root, 858int 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;
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index b4087e0fa871..53dcbdf446cd 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -465,14 +465,16 @@ again:
465 /* Just to make sure we have enough space */ 465 /* Just to make sure we have enough space */
466 prealloc += 8 * PAGE_CACHE_SIZE; 466 prealloc += 8 * PAGE_CACHE_SIZE;
467 467
468 ret = btrfs_check_data_free_space(inode, prealloc); 468 ret = btrfs_delalloc_reserve_space(inode, prealloc);
469 if (ret) 469 if (ret)
470 goto out_put; 470 goto out_put;
471 471
472 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc, 472 ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc,
473 prealloc, prealloc, &alloc_hint); 473 prealloc, prealloc, &alloc_hint);
474 if (ret) 474 if (ret) {
475 btrfs_delalloc_release_space(inode, prealloc);
475 goto out_put; 476 goto out_put;
477 }
476 btrfs_free_reserved_data_space(inode, prealloc); 478 btrfs_free_reserved_data_space(inode, prealloc);
477 479
478out_put: 480out_put:
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 06ae5b173fd7..78b5ae59ac4f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1792,11 +1792,11 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1792 } 1792 }
1793 ret = 0; 1793 ret = 0;
1794out: 1794out:
1795 btrfs_delalloc_release_metadata(inode, ordered_extent->len);
1795 if (nolock) { 1796 if (nolock) {
1796 if (trans) 1797 if (trans)
1797 btrfs_end_transaction_nolock(trans, root); 1798 btrfs_end_transaction_nolock(trans, root);
1798 } else { 1799 } else {
1799 btrfs_delalloc_release_metadata(inode, ordered_extent->len);
1800 if (trans) 1800 if (trans)
1801 btrfs_end_transaction(trans, root); 1801 btrfs_end_transaction(trans, root);
1802 } 1802 }