From a37e1e720451664477b030242616b3e48d31013e Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 4 Apr 2008 15:42:17 -0400 Subject: [PATCH] Recow all roots at the end of mkfs The mkfs code bootstraps the filesystem on a single device. Once the raid block groups are setup, it needs to recow all of the blocks so that each tree is properly allocated. --- ctree.c | 5 +---- ctree.h | 14 +++++++++++++ disk-io.c | 11 ++++++---- extent-tree.c | 64 ++++++++++++++++++++++++++++++++++++++--------------------- mkfs.c | 45 ++++++++++++++++++++++++++++++++++++++++- utils.c | 2 +- volumes.c | 18 +++++++++++++---- 7 files changed, 122 insertions(+), 37 deletions(-) diff --git a/ctree.c b/ctree.c index 5e42375..051cab5 100644 --- a/ctree.c +++ b/ctree.c @@ -244,11 +244,8 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, (unsigned long long)root->fs_info->generation); WARN_ON(1); } - if (btrfs_header_generation(buf) == trans->transid) { -#if 0 - && + if (btrfs_header_generation(buf) == trans->transid && !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { -#endif *cow_ret = buf; return 0; } diff --git a/ctree.h b/ctree.h index ccd9319..9c7f8a5 100644 --- a/ctree.h +++ b/ctree.h @@ -464,6 +464,14 @@ struct btrfs_fs_info { u64 generation; u64 last_trans_committed; + + u64 avail_data_alloc_bits; + u64 avail_metadata_alloc_bits; + u64 avail_system_alloc_bits; + u64 data_alloc_profile; + u64 metadata_alloc_profile; + u64 system_alloc_profile; + struct btrfs_trans_handle *running_transaction; struct btrfs_super_block super_copy; struct extent_buffer *sb_buffer; @@ -1269,6 +1277,12 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer *parent, int parent_slot, struct extent_buffer **cow_ret); +int __btrfs_cow_block(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf, + struct extent_buffer *parent, int parent_slot, + struct extent_buffer **cow_ret, + u64 search_start, u64 empty_size); int btrfs_copy_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, diff --git a/disk-io.c b/disk-io.c index 204abe0..ccc2f35 100644 --- a/disk-io.c +++ b/disk-io.c @@ -33,6 +33,7 @@ #include "transaction.h" #include "crc32c.h" #include "utils.h" +#include "print-tree.h" static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) { @@ -481,16 +482,13 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr) BUG_ON(ret); } + memset(fs_info, 0, sizeof(*fs_info)); fs_info->fp = fs_devices->lowest_bdev; - fs_info->running_transaction = NULL; fs_info->fs_root = root; fs_info->tree_root = tree_root; fs_info->extent_root = extent_root; - fs_info->extent_ops = NULL; - fs_info->priv_data = NULL; fs_info->chunk_root = chunk_root; fs_info->dev_root = dev_root; - fs_info->force_system_allocs = 0; extent_io_tree_init(&fs_info->extent_cache); extent_io_tree_init(&fs_info->free_space_cache); @@ -584,6 +582,11 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr) root->ref_cows = 1; fs_info->generation = btrfs_super_generation(disk_super) + 1; btrfs_read_block_groups(root); + + fs_info->data_alloc_profile = (u64)-1; + fs_info->metadata_alloc_profile = (u64)-1; + fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; + return root; } diff --git a/extent-tree.c b/extent-tree.c index ba44600..8c39537 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -172,7 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) { - return (cache->flags & bits); + return (cache->flags & bits) == bits; } static int noinline find_search_start(struct btrfs_root *root, @@ -348,14 +348,17 @@ again: last = cache->key.objectid + cache->key.offset; used = btrfs_block_group_used(&cache->item); - if (full_search) - free_check = cache->key.offset; - else - free_check = div_factor(cache->key.offset, factor); + if (block_group_bits(cache, data)) { + if (full_search) + free_check = cache->key.offset; + else + free_check = div_factor(cache->key.offset, + factor); - if (used + cache->pinned < free_check) { - found_group = cache; - goto found; + if (used + cache->pinned < free_check) { + found_group = cache; + goto found; + } } cond_resched(); } @@ -1020,6 +1023,21 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, } +static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) +{ + u64 extra_flags = flags & (BTRFS_BLOCK_GROUP_RAID0 | + BTRFS_BLOCK_GROUP_RAID1 | + BTRFS_BLOCK_GROUP_DUP); + if (extra_flags) { + if (flags & BTRFS_BLOCK_GROUP_DATA) + fs_info->avail_data_alloc_bits |= extra_flags; + if (flags & BTRFS_BLOCK_GROUP_METADATA) + fs_info->avail_metadata_alloc_bits |= extra_flags; + if (flags & BTRFS_BLOCK_GROUP_SYSTEM) + fs_info->avail_system_alloc_bits |= extra_flags; + } +} + static int do_chunk_alloc(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root, u64 alloc_bytes, u64 flags) @@ -1610,6 +1628,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int pending_ret; u64 super_used, root_used; u64 search_start = 0; + u64 alloc_profile; struct btrfs_fs_info *info = root->fs_info; struct btrfs_extent_ops *ops = info->extent_ops; u32 sizes[2]; @@ -1620,12 +1639,17 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_key keys[2]; if (data) { - data = BTRFS_BLOCK_GROUP_DATA; - } else if (root == root->fs_info->chunk_root || - info->force_system_allocs) { - data = BTRFS_BLOCK_GROUP_SYSTEM; + alloc_profile = info->avail_data_alloc_bits & + info->data_alloc_profile; + data = BTRFS_BLOCK_GROUP_DATA | alloc_profile; + } else if (root == info->chunk_root || info->force_system_allocs) { + alloc_profile = info->avail_system_alloc_bits & + info->system_alloc_profile; + data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile; } else { - data = BTRFS_BLOCK_GROUP_METADATA; + alloc_profile = info->avail_metadata_alloc_bits & + info->metadata_alloc_profile; + data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; } if (root->ref_cows) { @@ -2240,6 +2264,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { bit = BLOCK_GROUP_METADATA; } + set_avail_alloc_bits(info, cache->flags); ret = update_space_info(info, cache->flags, found_key.offset, btrfs_block_group_used(&cache->item), @@ -2278,13 +2303,11 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, extent_root = root->fs_info->extent_root; block_group_cache = &root->fs_info->block_group_cache; - cache = kmalloc(sizeof(*cache), GFP_NOFS); + cache = kzalloc(sizeof(*cache), GFP_NOFS); BUG_ON(!cache); cache->key.objectid = chunk_objectid; cache->key.offset = size; - cache->cached = 0; btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY); - memset(&cache->item, 0, sizeof(cache->item)); btrfs_set_block_group_used(&cache->item, bytes_used); btrfs_set_block_group_chunk_tree(&cache->item, chunk_tree); btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); @@ -2295,13 +2318,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, &cache->space_info); BUG_ON(ret); - if (type & BTRFS_BLOCK_GROUP_DATA) { - bit = BLOCK_GROUP_DATA; - } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { - bit = BLOCK_GROUP_SYSTEM; - } else if (type & BTRFS_BLOCK_GROUP_METADATA) { - bit = BLOCK_GROUP_METADATA; - } + bit = block_group_state_bits(type); set_extent_bits(block_group_cache, chunk_objectid, chunk_objectid + size - 1, bit | EXTENT_LOCKED, GFP_NOFS); @@ -2315,6 +2332,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, finish_current_insert(trans, extent_root); ret = del_pending_extents(trans, extent_root); BUG_ON(ret); + set_avail_alloc_bits(extent_root->fs_info, type); return 0; } diff --git a/mkfs.c b/mkfs.c index 4d28bdf..506b6e0 100644 --- a/mkfs.c +++ b/mkfs.c @@ -139,6 +139,42 @@ err: return ret; } +static int recow_roots(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + int ret; + struct extent_buffer *tmp; + struct btrfs_fs_info *info = root->fs_info; + + ret = __btrfs_cow_block(trans, info->fs_root, info->fs_root->node, + NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + + ret = __btrfs_cow_block(trans, info->tree_root, info->tree_root->node, + NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + + ret = __btrfs_cow_block(trans, info->extent_root, + info->extent_root->node, NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + + ret = __btrfs_cow_block(trans, info->chunk_root, info->chunk_root->node, + NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + + + ret = __btrfs_cow_block(trans, info->dev_root, info->dev_root->node, + NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + + return 0; +} + static int create_one_raid_group(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 type) { @@ -171,9 +207,17 @@ static int create_raid_groups(struct btrfs_trans_handle *trans, if (allowed & metadata_profile) { ret = create_one_raid_group(trans, root, + BTRFS_BLOCK_GROUP_SYSTEM | + (allowed & metadata_profile)); + BUG_ON(ret); + + ret = create_one_raid_group(trans, root, BTRFS_BLOCK_GROUP_METADATA | (allowed & metadata_profile)); BUG_ON(ret); + + ret = recow_roots(trans, root); + BUG_ON(ret); } if (num_devices > 1 && (allowed & data_profile)) { ret = create_one_raid_group(trans, root, @@ -362,7 +406,6 @@ int main(int ac, char **av) ret = btrfs_add_to_fsid(trans, root, fd, dev_block_count, sectorsize, sectorsize, sectorsize); BUG_ON(ret); - close(fd); btrfs_register_one_device(file); } diff --git a/utils.c b/utils.c index 3361030..55d3f5f 100644 --- a/utils.c +++ b/utils.c @@ -431,7 +431,7 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, device->io_width = io_width; device->io_align = io_align; device->sector_size = sectorsize; - device->fd = 0; + device->fd = fd; device->total_bytes = block_count; device->bytes_used = 0; device->total_ios = 0; diff --git a/volumes.c b/volumes.c index b5f6b8b..c86202d 100644 --- a/volumes.c +++ b/volumes.c @@ -586,7 +586,10 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, if (type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) { - calc_size = 1024 * 1024 * 1024; + if (type & BTRFS_BLOCK_GROUP_SYSTEM) + calc_size = 128 * 1024 * 1024; + else + calc_size = 1024 * 1024 * 1024; } if (type & BTRFS_BLOCK_GROUP_RAID1) { num_stripes = min_t(u64, 2, @@ -667,9 +670,10 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes key.objectid, calc_size, &dev_offset); BUG_ON(ret); -printk("\talloc chunk size %llu from dev %llu\n", +printk("\talloc chunk size %llu from dev %llu phys %llu\n", (unsigned long long)calc_size, - (unsigned long long)device->devid); + (unsigned long long)device->devid, + (unsigned long long)dev_offset); device->bytes_used += calc_size; ret = btrfs_update_device(trans, device); BUG_ON(ret); @@ -713,6 +717,12 @@ printk("\talloc chunk size %llu from dev %llu\n", &map->ce); BUG_ON(ret); + if (type & BTRFS_BLOCK_GROUP_SYSTEM) { + ret = btrfs_add_system_chunk(trans, chunk_root, &key, + chunk, btrfs_chunk_item_size(num_stripes)); + BUG_ON(ret); + } + kfree(chunk); return ret; } @@ -830,13 +840,13 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, map->ce.start = logical; map->ce.size = length; - map->num_stripes = num_stripes; map->io_width = btrfs_chunk_io_width(leaf, chunk); map->io_align = btrfs_chunk_io_align(leaf, chunk); map->sector_size = btrfs_chunk_sector_size(leaf, chunk); map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); map->type = btrfs_chunk_type(leaf, chunk); + for (i = 0; i < num_stripes; i++) { map->stripes[i].physical = btrfs_stripe_offset_nr(leaf, chunk, i); -- 2.7.4