Btrfs: Allow find_free_extent callers to pass in an exclusion range

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7e55034..01dc305 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -25,7 +25,8 @@
 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
 			    *orig_root, u64 num_blocks, u64 search_start,
 			    u64 search_end, u64 hint_block,
-			    struct btrfs_key *ins, int data);
+			    struct btrfs_key *ins, u64 exclude_start,
+			    u64 exclude_nr, int data);
 static int finish_current_insert(struct btrfs_trans_handle *trans, struct
 				 btrfs_root *extent_root);
 static int del_pending_extents(struct btrfs_trans_handle *trans, struct
@@ -407,7 +408,7 @@
 	if (!path)
 		return -ENOMEM;
 	ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0,
-			       (u64)-1, 0, &ins, 0);
+			       (u64)-1, 0, &ins, 0, 0, 0);
 	if (ret) {
 		btrfs_free_path(path);
 		return ret;
@@ -559,7 +560,8 @@
 	struct btrfs_block_group_item *bi;
 	struct btrfs_key ins;
 
-	ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
+	ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins,
+			       0, 0, 0);
 	/* FIXME, set bit to recalc cache groups on next mount */
 	if (ret)
 		return ret;
@@ -868,7 +870,7 @@
 	if (!path)
 		return -ENOMEM;
 
-	ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
+	ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0, 0, 0);
 	if (ret) {
 		btrfs_free_path(path);
 		return ret;
@@ -987,7 +989,8 @@
 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
 			    *orig_root, u64 num_blocks, u64 search_start, u64
 			    search_end, u64 hint_block,
-			    struct btrfs_key *ins, int data)
+			    struct btrfs_key *ins, u64 exclude_start,
+			    u64 exclude_nr, int data)
 {
 	struct btrfs_path *path;
 	struct btrfs_key key;
@@ -1191,6 +1194,11 @@
 			goto new_group;
 		}
 	}
+	if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start &&
+	    ins->objectid < exclude_start + exclude_nr)) {
+		search_start = exclude_start + exclude_nr;
+		goto new_group;
+	}
 	if (fill_prealloc) {
 		int nr;
 		test_block = ins->objectid;
@@ -1267,6 +1275,8 @@
 	int pending_ret;
 	u64 super_blocks_used;
 	u64 search_start = 0;
+	u64 exclude_start = 0;
+	u64 exclude_nr = 0;
 	struct btrfs_fs_info *info = root->fs_info;
 	struct btrfs_root *extent_root = info->extent_root;
 	struct btrfs_extent_item extent_item;
@@ -1298,34 +1308,20 @@
 	 */
 	if (data) {
 		ret = find_free_extent(trans, root, 0, 0,
-				       search_end, 0, &prealloc_key, 0);
-		if (ret) {
-			return ret;
-		}
-		if (prealloc_key.objectid + prealloc_key.offset >= search_end) {
-			int nr = info->extent_tree_prealloc_nr;
-			search_end = info->extent_tree_prealloc[nr - 1] - 1;
-		} else {
-			search_start = info->extent_tree_prealloc[0] + 1;
-		}
-	}
-	if (hint_block < search_start)
-		hint_block = search_start;
-	/* do the real allocation */
-	ret = find_free_extent(trans, root, num_blocks, search_start,
-			       search_end, hint_block, ins, data);
-	if (ret) {
-		if (search_start == 0)
-			return ret;
-		search_end = search_start - 1;
-		search_start = 0;
-		hint_block = search_start;
-		ret = find_free_extent(trans, root, num_blocks, search_start,
-				       search_end, hint_block, ins, data);
+				       search_end, 0, &prealloc_key, 0, 0, 0);
 		if (ret)
 			return ret;
+		exclude_nr = info->extent_tree_prealloc_nr;
+		exclude_start = info->extent_tree_prealloc[exclude_nr - 1];
 	}
 
+	/* do the real allocation */
+	ret = find_free_extent(trans, root, num_blocks, search_start,
+			       search_end, hint_block, ins,
+			       exclude_start, exclude_nr, data);
+	if (ret)
+		return ret;
+
 	/*
 	 * if we're doing a metadata allocation, preallocate space in the
 	 * extent tree second.  This way, we don't create a tiny hole
@@ -1336,29 +1332,14 @@
 	 * The unused prealloc will get reused the next time around.
 	 */
 	if (!data) {
-		if (ins->objectid + ins->offset >= search_end)
-			search_end = ins->objectid - 1;
-		else
-			search_start = ins->objectid + ins->offset;
-
-		if (hint_block < search_start)
-			hint_block = search_start;
-
+		exclude_start = ins->objectid;
+		exclude_nr = ins->offset;
 		ret = find_free_extent(trans, root, 0, search_start,
 				       search_end, hint_block,
-				       &prealloc_key, 0);
-		if (ret) {
-			if (search_start == 0)
-				return ret;
-			search_end = search_start - 1;
-			search_start = 0;
-			hint_block = search_start;
-			ret = find_free_extent(trans, root, 0, search_start,
-					       search_end, hint_block,
-					       &prealloc_key, 0);
-			if (ret)
-				return ret;
-		}
+				       &prealloc_key, exclude_start,
+				       exclude_nr, 0);
+		if (ret)
+			return ret;
 	}
 
 	super_blocks_used = btrfs_super_blocks_used(&info->super_copy);