aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-10-08 13:34:05 -0400
committerChris Mason <chris.mason@oracle.com>2009-10-08 15:21:10 -0400
commit32c00aff718bb54a214b39146bdd9ac01511cd25 (patch)
treec094ee494723a9ebc9d83cb95607f06351665639 /fs/btrfs/extent-tree.c
parenta3429ab70b04363c6190964e82f04f44f3e34cf0 (diff)
Btrfs: release delalloc reservations on extent item insertion
This patch fixes an issue with the delalloc metadata space reservation code. The problem is we used to free the reservation as soon as we allocated the delalloc region. The problem with this is if we are not inserting an inline extent, we don't actually insert the extent item until after the ordered extent is written out. This patch does 3 things, 1) It moves the reservation clearing stuff into the ordered code, so when we remove the ordered extent we remove the reservation. 2) It adds a EXTENT_DO_ACCOUNTING flag that gets passed when we clear delalloc bits in the cases where we want to clear the metadata reservation when we clear the delalloc extent, in the case that we do an inline extent or we invalidate the page. 3) It adds another waitqueue to the space info so that when we start a fs wide delalloc flush, anybody else who also hits that area will simply wait for the flush to finish and then try to make their allocation. This has been tested thoroughly to make sure we did not regress on performance. Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2f82fabd7011..3d1be0b77f8f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2823,14 +2823,17 @@ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
2823 num_items); 2823 num_items);
2824 2824
2825 spin_lock(&meta_sinfo->lock); 2825 spin_lock(&meta_sinfo->lock);
2826 if (BTRFS_I(inode)->delalloc_reserved_extents <= 2826 spin_lock(&BTRFS_I(inode)->accounting_lock);
2827 BTRFS_I(inode)->delalloc_extents) { 2827 if (BTRFS_I(inode)->reserved_extents <=
2828 BTRFS_I(inode)->outstanding_extents) {
2829 spin_unlock(&BTRFS_I(inode)->accounting_lock);
2828 spin_unlock(&meta_sinfo->lock); 2830 spin_unlock(&meta_sinfo->lock);
2829 return 0; 2831 return 0;
2830 } 2832 }
2833 spin_unlock(&BTRFS_I(inode)->accounting_lock);
2831 2834
2832 BTRFS_I(inode)->delalloc_reserved_extents--; 2835 BTRFS_I(inode)->reserved_extents--;
2833 BUG_ON(BTRFS_I(inode)->delalloc_reserved_extents < 0); 2836 BUG_ON(BTRFS_I(inode)->reserved_extents < 0);
2834 2837
2835 if (meta_sinfo->bytes_delalloc < num_bytes) { 2838 if (meta_sinfo->bytes_delalloc < num_bytes) {
2836 bug = true; 2839 bug = true;
@@ -2863,6 +2866,37 @@ static void check_force_delalloc(struct btrfs_space_info *meta_sinfo)
2863 meta_sinfo->force_delalloc = 0; 2866 meta_sinfo->force_delalloc = 0;
2864} 2867}
2865 2868
2869static void flush_delalloc(struct btrfs_root *root,
2870 struct btrfs_space_info *info)
2871{
2872 bool wait = false;
2873
2874 spin_lock(&info->lock);
2875
2876 if (!info->flushing) {
2877 info->flushing = 1;
2878 init_waitqueue_head(&info->flush_wait);
2879 } else {
2880 wait = true;
2881 }
2882
2883 spin_unlock(&info->lock);
2884
2885 if (wait) {
2886 wait_event(info->flush_wait,
2887 !info->flushing);
2888 return;
2889 }
2890
2891 btrfs_start_delalloc_inodes(root);
2892 btrfs_wait_ordered_extents(root, 0);
2893
2894 spin_lock(&info->lock);
2895 info->flushing = 0;
2896 spin_unlock(&info->lock);
2897 wake_up(&info->flush_wait);
2898}
2899
2866static int maybe_allocate_chunk(struct btrfs_root *root, 2900static int maybe_allocate_chunk(struct btrfs_root *root,
2867 struct btrfs_space_info *info) 2901 struct btrfs_space_info *info)
2868{ 2902{
@@ -2980,21 +3014,20 @@ again:
2980 filemap_flush(inode->i_mapping); 3014 filemap_flush(inode->i_mapping);
2981 goto again; 3015 goto again;
2982 } else if (flushed == 3) { 3016 } else if (flushed == 3) {
2983 btrfs_start_delalloc_inodes(root); 3017 flush_delalloc(root, meta_sinfo);
2984 btrfs_wait_ordered_extents(root, 0);
2985 goto again; 3018 goto again;
2986 } 3019 }
2987 spin_lock(&meta_sinfo->lock); 3020 spin_lock(&meta_sinfo->lock);
2988 meta_sinfo->bytes_delalloc -= num_bytes; 3021 meta_sinfo->bytes_delalloc -= num_bytes;
2989 spin_unlock(&meta_sinfo->lock); 3022 spin_unlock(&meta_sinfo->lock);
2990 printk(KERN_ERR "enospc, has %d, reserved %d\n", 3023 printk(KERN_ERR "enospc, has %d, reserved %d\n",
2991 BTRFS_I(inode)->delalloc_extents, 3024 BTRFS_I(inode)->outstanding_extents,
2992 BTRFS_I(inode)->delalloc_reserved_extents); 3025 BTRFS_I(inode)->reserved_extents);
2993 dump_space_info(meta_sinfo, 0, 0); 3026 dump_space_info(meta_sinfo, 0, 0);
2994 return -ENOSPC; 3027 return -ENOSPC;
2995 } 3028 }
2996 3029
2997 BTRFS_I(inode)->delalloc_reserved_extents++; 3030 BTRFS_I(inode)->reserved_extents++;
2998 check_force_delalloc(meta_sinfo); 3031 check_force_delalloc(meta_sinfo);
2999 spin_unlock(&meta_sinfo->lock); 3032 spin_unlock(&meta_sinfo->lock);
3000 3033
@@ -3093,8 +3126,7 @@ again:
3093 } 3126 }
3094 3127
3095 if (retries == 2) { 3128 if (retries == 2) {
3096 btrfs_start_delalloc_inodes(root); 3129 flush_delalloc(root, meta_sinfo);
3097 btrfs_wait_ordered_extents(root, 0);
3098 goto again; 3130 goto again;
3099 } 3131 }
3100 spin_lock(&meta_sinfo->lock); 3132 spin_lock(&meta_sinfo->lock);