mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-11 03:31:17 +00:00
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.
This commit is contained in:
parent
a57a255e44
commit
a37e1e7204
5
ctree.c
5
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;
|
||||
}
|
||||
|
14
ctree.h
14
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,
|
||||
|
11
disk-io.c
11
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
45
mkfs.c
45
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)
|
||||
{
|
||||
@ -170,10 +206,18 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
|
||||
allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
2
utils.c
2
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;
|
||||
|
18
volumes.c
18
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);
|
||||
|
Loading…
Reference in New Issue
Block a user