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