aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2013-04-22 06:53:47 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:55:15 -0400
commitace68bac61b338e52924d87ebdd0fa8c7439f896 (patch)
treeffebb5c3de0dcc6e10e90f2c69f276a063edb049 /fs
parent6463fe58ea60cbcc3e799937dd0877466fc7b8d5 (diff)
Btrfs: return free space in cow error path
Replace some BUG_ONs with proper handling and take allocated space back to free space cache for later use. We don't have to worry about extent maps since they'd be freed in releasepage path. Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 33a9e9da726d..0eab7b67e109 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -920,7 +920,8 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
920 } 920 }
921 921
922 em = alloc_extent_map(); 922 em = alloc_extent_map();
923 BUG_ON(!em); /* -ENOMEM */ 923 if (!em)
924 goto out_reserve;
924 em->start = start; 925 em->start = start;
925 em->orig_start = em->start; 926 em->orig_start = em->start;
926 ram_size = ins.offset; 927 ram_size = ins.offset;
@@ -947,11 +948,14 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
947 btrfs_drop_extent_cache(inode, start, 948 btrfs_drop_extent_cache(inode, start,
948 start + ram_size - 1, 0); 949 start + ram_size - 1, 0);
949 } 950 }
951 if (ret)
952 goto out_reserve;
950 953
951 cur_alloc_size = ins.offset; 954 cur_alloc_size = ins.offset;
952 ret = btrfs_add_ordered_extent(inode, start, ins.objectid, 955 ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
953 ram_size, cur_alloc_size, 0); 956 ram_size, cur_alloc_size, 0);
954 BUG_ON(ret); /* -ENOMEM */ 957 if (ret)
958 goto out_reserve;
955 959
956 if (root->root_key.objectid == 960 if (root->root_key.objectid ==
957 BTRFS_DATA_RELOC_TREE_OBJECTID) { 961 BTRFS_DATA_RELOC_TREE_OBJECTID) {
@@ -959,7 +963,7 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
959 cur_alloc_size); 963 cur_alloc_size);
960 if (ret) { 964 if (ret) {
961 btrfs_abort_transaction(trans, root, ret); 965 btrfs_abort_transaction(trans, root, ret);
962 goto out_unlock; 966 goto out_reserve;
963 } 967 }
964 } 968 }
965 969
@@ -988,6 +992,8 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
988out: 992out:
989 return ret; 993 return ret;
990 994
995out_reserve:
996 btrfs_free_reserved_extent(root, ins.objectid, ins.offset);
991out_unlock: 997out_unlock:
992 extent_clear_unlock_delalloc(inode, 998 extent_clear_unlock_delalloc(inode,
993 &BTRFS_I(inode)->io_tree, 999 &BTRFS_I(inode)->io_tree,