Btrfs: Bring back mount -o ssd optimizations

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 14eb8fc..e9ef644 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1473,13 +1473,31 @@
 	struct btrfs_root * root = orig_root->fs_info->extent_root;
 	struct btrfs_fs_info *info = root->fs_info;
 	u64 total_needed = num_bytes;
+	u64 *last_ptr = NULL;
 	struct btrfs_block_group_cache *block_group;
 	int full_scan = 0;
 	int wrapped = 0;
+	int empty_cluster = 2 * 1024 * 1024;
 
 	WARN_ON(num_bytes < root->sectorsize);
 	btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
 
+	if (data & BTRFS_BLOCK_GROUP_METADATA) {
+		last_ptr = &root->fs_info->last_alloc;
+	}
+
+	if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
+		last_ptr = &root->fs_info->last_data_alloc;
+	}
+
+	if (last_ptr) {
+		if (*last_ptr)
+			hint_byte = *last_ptr;
+		else {
+			empty_size += empty_cluster;
+		}
+	}
+
 	if (search_end == (u64)-1)
 		search_end = btrfs_super_total_bytes(&info->super_copy);
 
@@ -1489,11 +1507,14 @@
 			hint_byte = search_start;
 		block_group = btrfs_find_block_group(root, block_group,
 						     hint_byte, data, 1);
+		if (last_ptr && *last_ptr == 0 && block_group)
+			hint_byte = block_group->key.objectid;
 	} else {
 		block_group = btrfs_find_block_group(root,
 						     trans->block_group,
 						     search_start, data, 1);
 	}
+	search_start = max(search_start, hint_byte);
 
 	total_needed += empty_size;
 
@@ -1506,9 +1527,36 @@
 	}
 	ret = find_search_start(root, &block_group, &search_start,
 				total_needed, data);
+	if (ret == -ENOSPC && last_ptr && *last_ptr) {
+		*last_ptr = 0;
+		block_group = btrfs_lookup_block_group(info,
+						       orig_search_start);
+		search_start = orig_search_start;
+		ret = find_search_start(root, &block_group, &search_start,
+					total_needed, data);
+	}
+	if (ret == -ENOSPC)
+		goto enospc;
 	if (ret)
 		goto error;
 
+	if (last_ptr && *last_ptr && search_start != *last_ptr) {
+		*last_ptr = 0;
+		if (!empty_size) {
+			empty_size += empty_cluster;
+			total_needed += empty_size;
+		}
+		block_group = btrfs_lookup_block_group(info,
+						       orig_search_start);
+		search_start = orig_search_start;
+		ret = find_search_start(root, &block_group,
+					&search_start, total_needed, data);
+		if (ret == -ENOSPC)
+			goto enospc;
+		if (ret)
+			goto error;
+	}
+
 	search_start = stripe_align(root, search_start);
 	ins->objectid = search_start;
 	ins->offset = num_bytes;
@@ -1547,6 +1595,13 @@
 			trans->block_group = block_group;
 	}
 	ins->offset = num_bytes;
+	if (last_ptr) {
+		*last_ptr = ins->objectid + ins->offset;
+		if (*last_ptr ==
+		    btrfs_super_total_bytes(&root->fs_info->super_copy)) {
+			*last_ptr = 0;
+		}
+	}
 	return 0;
 
 new_group:
@@ -1612,12 +1667,12 @@
 	if (root->ref_cows) {
 		if (data != BTRFS_BLOCK_GROUP_METADATA) {
 			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-					     num_bytes,
+					     2 * 1024 * 1024,
 					     BTRFS_BLOCK_GROUP_METADATA);
 			BUG_ON(ret);
 		}
 		ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-				     num_bytes, data);
+				     num_bytes + 2 * 1024 * 1024, data);
 		BUG_ON(ret);
 	}