Zheng Yan
2008-Sep-08  18:56 UTC
[PATCH 4/4] update allocator the handle ''hole'' in address space
Hello,
Space balancing creates some ''holes'' in the address space,
this confuses
the allocator. This patch removes all checks against the super_total_bytes.
Regards
Yan Zheng
---
diff -r 16615727163e ctree.h
--- a/ctree.h	Tue Sep 09 02:16:25 2008 +0800
+++ b/ctree.h	Tue Sep 09 02:16:35 2008 +0800
@@ -500,7 +500,6 @@
 	u64 bytes_used;
 	u64 bytes_pinned;
 	u64 bytes_reserved;
-	int full;
 	int force_alloc;
 	struct list_head list;
 };
diff -r 16615727163e extent-tree.c
--- a/extent-tree.c	Tue Sep 09 02:16:25 2008 +0800
+++ b/extent-tree.c	Tue Sep 09 02:16:35 2008 +0800
@@ -51,6 +51,8 @@
 				 btrfs_root *extent_root);
 static int del_pending_extents(struct btrfs_trans_handle *trans, struct
 			       btrfs_root *extent_root);
+static int __alloc_chunk_for_extent_op(struct btrfs_trans_handle *trans,
+				       struct btrfs_root *root);
 static struct btrfs_block_group_cache *
 __btrfs_find_block_group(struct btrfs_root *root,
 			 struct btrfs_block_group_cache *hint,
@@ -254,13 +256,10 @@
 	struct extent_state *state;
 	u64 last;
 	u64 start = 0;
-	u64 cache_miss = 0;
-	u64 total_fs_bytes;
 	u64 search_start = *start_ret;
 	int wrapped = 0;
 
 	WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex));
-	total_fs_bytes =
btrfs_super_total_bytes(&root->fs_info->super_copy);
 	free_space_cache = &root->fs_info->free_space_cache;
 
 	if (!cache)
@@ -280,8 +279,6 @@
 	state = find_first_extent_bit_state(free_space_cache, last, EXTENT_DIRTY);
 	while(1) {
 		if (!state) {
-			if (!cache_miss)
-				cache_miss = last;
 			spin_unlock_irq(&free_space_cache->lock);
 			goto new_group;
 		}
@@ -318,7 +315,7 @@
 	last = cache->key.objectid + cache->key.offset;
 wrapped:
 	cache = btrfs_lookup_first_block_group(root->fs_info, last);
-	if (!cache || cache->key.objectid >= total_fs_bytes) {
+	if (!cache) {
 no_cache:
 		if (!wrapped) {
 			wrapped = 1;
@@ -327,12 +324,6 @@
 		}
 		goto out;
 	}
-	if (cache_miss && !cache->cached) {
-		cache_block_group(root, cache);
-		last = cache_miss;
-		cache = btrfs_lookup_first_block_group(root->fs_info, last);
-	}
-	cache_miss = 0;
 	cache = btrfs_find_block_group(root, cache, last, data, 0);
 	if (!cache)
 		goto no_cache;
@@ -719,6 +710,7 @@
 	if (!path)
 		return -ENOMEM;
 
+	__alloc_chunk_for_extent_op(trans, root);
 	ret = lookup_extent_backref(trans, extent_root, path,
 				    bytenr, orig_parent,
 				    root_objectid, ref_generation, 1);
@@ -779,6 +771,7 @@
 	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
 	key.offset = num_bytes;
 
+	__alloc_chunk_for_extent_op(trans, root);
 	ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key,
path,
 				0, 1);
 	if (ret < 0)
@@ -1277,6 +1270,7 @@
 	unsigned long bi;
 	struct extent_buffer *leaf;
 
+	__alloc_chunk_for_extent_op(trans, extent_root);
 	ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
 	if (ret < 0)
 		goto fail;
@@ -1374,7 +1368,6 @@
 	if (found) {
 		found->total_bytes += total_bytes;
 		found->bytes_used += bytes_used;
-		found->full = 0;
 		*space_info = found;
 		return 0;
 	}
@@ -1388,7 +1381,6 @@
 	found->bytes_used = bytes_used;
 	found->bytes_pinned = 0;
 	found->bytes_reserved = 0;
-	found->full = 0;
 	found->force_alloc = 0;
 	*space_info = found;
 	return 0;
@@ -1462,8 +1454,6 @@
 		force = 1;
 		space_info->force_alloc = 0;
 	}
-	if (space_info->full)
-		goto out;
 
 	thresh = div_factor(space_info->total_bytes, 6);
 	if (!force &&
@@ -1473,12 +1463,8 @@
 
 	mutex_lock(&extent_root->fs_info->chunk_mutex);
 	ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes,
flags);
-	if (ret == -ENOSPC) {
-printk("space info full %Lu\n", flags);
-		space_info->full = 1;
+	if (ret == -ENOSPC)
 		goto out_unlock;
-	}
-	BUG_ON(ret);
 
 	ret = btrfs_make_block_group(trans, extent_root, 0, flags,
 		     BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes);
@@ -1487,6 +1473,24 @@
 	mutex_unlock(&extent_root->fs_info->chunk_mutex);
 out:
 	return 0;
+}
+
+static int __alloc_chunk_for_extent_op(struct btrfs_trans_handle *trans,
+				       struct btrfs_root *root)
+{
+	struct btrfs_fs_info *info = root->fs_info;
+	int ret;
+
+	if (root == root->fs_info->chunk_root ||
+	    root == root->fs_info->dev_root)
+		return 0;
+
+	ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+			     2 * 1024 * 1024,
+			     BTRFS_BLOCK_GROUP_METADATA |
+			     (info->metadata_alloc_profile &
+			      info->avail_metadata_alloc_bits), 0);
+	return ret;
 }
 
 static int update_block_group(struct btrfs_trans_handle *trans,
@@ -2232,6 +2236,7 @@
 	if (ref_generation != trans->transid)
 		pin = 1;
 
+	__alloc_chunk_for_extent_op(trans, root);
 	ret = __free_extent(trans, root, bytenr, num_bytes, parent,
 			    root_objectid, ref_generation,
 			    owner_objectid, owner_offset, pin, pin == 0);
@@ -2324,9 +2329,6 @@
 
 	search_start = max(search_start, first_logical_byte(root, 0));
 	orig_search_start = search_start;
-
-	if (search_end == (u64)-1)
-		search_end = btrfs_super_total_bytes(&info->super_copy);
 
 	if (hint_byte) {
 		block_group = btrfs_lookup_first_block_group(info, hint_byte);
@@ -2399,9 +2401,6 @@
 	ins->objectid = search_start;
 	ins->offset = num_bytes;
 
-	if (ins->objectid + num_bytes >= search_end)
-		goto enospc;
-
 	if (ins->objectid + num_bytes >
 	    block_group->key.objectid + block_group->key.offset) {
 		search_start = block_group->key.objectid +
@@ -2443,7 +2442,8 @@
 	return 0;
 
 new_group:
-	if (search_start + num_bytes >= search_end) {
+	block_group = btrfs_lookup_first_block_group(info, search_start);
+	if (!block_group) {
 enospc:
 		search_start = orig_search_start;
 		if (full_scan) {
@@ -2457,7 +2457,6 @@
 		} else
 			wrapped = 1;
 	}
-	block_group = btrfs_lookup_first_block_group(info, search_start);
 	cond_resched();
 	block_group = btrfs_find_block_group(root, block_group,
 					     search_start, data, 0);
@@ -2613,6 +2612,7 @@
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 
+	__alloc_chunk_for_extent_op(trans, root);
 	ret = btrfs_insert_empty_items(trans, extent_root, path, keys,
 				       sizes, 2);
 
@@ -3795,6 +3795,8 @@
 		needs_lock = 1;
 		mutex_lock(&root->fs_info->alloc_mutex);
 	}
+	if (root == root->fs_info->extent_root)
+		__alloc_chunk_for_extent_op(trans, root);
 
 	path->lowest_level = level;
 	ret = btrfs_search_slot(trans, root, first_key, path, 0, 1);
@@ -4406,9 +4408,6 @@
 		set_extent_bits(block_group_cache, found_key.objectid,
 				found_key.objectid + found_key.offset - 1,
 				bit | EXTENT_LOCKED, GFP_NOFS);
-		if (key.objectid >-		   
btrfs_super_total_bytes(&info->super_copy))
-			break;
 	}
 	ret = 0;
 error:
diff -r 16615727163e volumes.c
--- a/volumes.c	Tue Sep 09 02:16:25 2008 +0800
+++ b/volumes.c	Tue Sep 09 02:16:35 2008 +0800
@@ -1094,6 +1094,7 @@
 		 &root->fs_info->fs_devices->alloc_list);
 	root->fs_info->fs_devices->num_devices++;
 	root->fs_info->fs_devices->open_devices++;
+	root->fs_info->fs_devices->full = 0;
 out:
 	unlock_chunks(root);
 	btrfs_end_transaction(trans, root);
@@ -1376,6 +1377,8 @@
 		BUG_ON(ret);
 
 		btrfs_end_transaction(trans, dev_root);
+
+		dev_root->fs_info->fs_devices->full = 0;
 	}
 
 	/* step two, relocate all the chunks */
@@ -1422,6 +1425,8 @@
 					   found_key.objectid,
 					   found_key.offset);
 		BUG_ON(ret);
+
+		dev_root->fs_info->fs_devices->full = 0;
 	}
 	ret = 0;
 error:
@@ -1601,6 +1606,10 @@
 		WARN_ON(1);
 		type &= ~BTRFS_BLOCK_GROUP_DUP;
 	}
+
+	if (extent_root->fs_info->fs_devices->full)
+		return -ENOSPC;
+
 	dev_list = &extent_root->fs_info->fs_devices->alloc_list;
 	if (list_empty(dev_list))
 		return -ENOSPC;
@@ -1717,7 +1726,12 @@
 			calc_size = max_avail;
 			goto again;
 		}
+		if (calc_size > min_stripe_size) {
+			calc_size >>= 1;
+			goto again;
+		}
 		btrfs_free_path(path);
+		extent_root->fs_info->fs_devices->full = 1;
 		return -ENOSPC;
 	}
 	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
diff -r 16615727163e volumes.h
--- a/volumes.h	Tue Sep 09 02:16:25 2008 +0800
+++ b/volumes.h	Tue Sep 09 02:16:35 2008 +0800
@@ -85,6 +85,7 @@
 	struct list_head alloc_list;
 	struct list_head list;
 	int mounted;
+	int full;
 };
 
 struct btrfs_bio_stripe {
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html