mirror of
https://github.com/kdave/btrfs-progs
synced 2025-05-07 02:17:56 +00:00
Write all super blocks during commit
This commit is contained in:
parent
fd2d0af0bf
commit
d1b04c2112
41
disk-io.c
41
disk-io.c
@ -195,6 +195,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|||||||
length = eb->len;
|
length = eb->len;
|
||||||
ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
|
ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
|
||||||
eb->start, &length, &multi, 0);
|
eb->start, &length, &multi, 0);
|
||||||
|
|
||||||
while(dev_nr < multi->num_stripes) {
|
while(dev_nr < multi->num_stripes) {
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
eb->fd = multi->stripes[dev_nr].dev->fd;
|
eb->fd = multi->stripes[dev_nr].dev->fd;
|
||||||
@ -528,10 +529,12 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr)
|
|||||||
ret = btrfs_open_devices(fs_devices, O_RDWR);
|
ret = btrfs_open_devices(fs_devices, O_RDWR);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
ret = btrfs_bootstrap_super_map(&fs_info->mapping_tree, fs_devices);
|
||||||
|
BUG_ON(ret);
|
||||||
fs_info->sb_buffer = btrfs_find_create_tree_block(tree_root, sb_bytenr,
|
fs_info->sb_buffer = btrfs_find_create_tree_block(tree_root, sb_bytenr,
|
||||||
4096);
|
4096);
|
||||||
BUG_ON(!fs_info->sb_buffer);
|
BUG_ON(!fs_info->sb_buffer);
|
||||||
fs_info->sb_buffer->fd = fs_devices->lowest_bdev;
|
fs_info->sb_buffer->fd = fs_devices->latest_bdev;
|
||||||
fs_info->sb_buffer->dev_bytenr = sb_bytenr;
|
fs_info->sb_buffer->dev_bytenr = sb_bytenr;
|
||||||
ret = read_extent_from_disk(fs_info->sb_buffer);
|
ret = read_extent_from_disk(fs_info->sb_buffer);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
@ -608,6 +611,40 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr)
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int write_all_supers(struct btrfs_root *root)
|
||||||
|
{
|
||||||
|
struct list_head *cur;
|
||||||
|
struct list_head *head = &root->fs_info->fs_devices->devices;
|
||||||
|
struct btrfs_device *dev;
|
||||||
|
struct extent_buffer *sb;
|
||||||
|
struct btrfs_dev_item *dev_item;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sb = root->fs_info->sb_buffer;
|
||||||
|
dev_item = (struct btrfs_dev_item *)offsetof(struct btrfs_super_block,
|
||||||
|
dev_item);
|
||||||
|
list_for_each(cur, head) {
|
||||||
|
dev = list_entry(cur, struct btrfs_device, dev_list);
|
||||||
|
btrfs_set_device_type(sb, dev_item, dev->type);
|
||||||
|
btrfs_set_device_id(sb, dev_item, dev->devid);
|
||||||
|
btrfs_set_device_total_bytes(sb, dev_item, dev->total_bytes);
|
||||||
|
btrfs_set_device_bytes_used(sb, dev_item, dev->bytes_used);
|
||||||
|
btrfs_set_device_io_align(sb, dev_item, dev->io_align);
|
||||||
|
btrfs_set_device_io_width(sb, dev_item, dev->io_width);
|
||||||
|
btrfs_set_device_sector_size(sb, dev_item, dev->sector_size);
|
||||||
|
write_extent_buffer(sb, dev->uuid,
|
||||||
|
(unsigned long)btrfs_device_uuid(dev_item),
|
||||||
|
BTRFS_DEV_UUID_SIZE);
|
||||||
|
sb->fd = dev->fd;
|
||||||
|
sb->dev_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
||||||
|
btrfs_set_header_flag(sb, BTRFS_HEADER_FLAG_WRITTEN);
|
||||||
|
csum_tree_block(root, sb, 0);
|
||||||
|
ret = write_extent_to_disk(sb);
|
||||||
|
BUG_ON(ret);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int write_ctree_super(struct btrfs_trans_handle *trans,
|
int write_ctree_super(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root)
|
struct btrfs_root *root)
|
||||||
{
|
{
|
||||||
@ -627,7 +664,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
|
|||||||
write_extent_buffer(root->fs_info->sb_buffer,
|
write_extent_buffer(root->fs_info->sb_buffer,
|
||||||
&root->fs_info->super_copy, 0,
|
&root->fs_info->super_copy, 0,
|
||||||
sizeof(root->fs_info->super_copy));
|
sizeof(root->fs_info->super_copy));
|
||||||
ret = write_tree_block(trans, root, root->fs_info->sb_buffer);
|
ret = write_all_supers(root);
|
||||||
if (ret)
|
if (ret)
|
||||||
fprintf(stderr, "failed to write new super block err %d\n", ret);
|
fprintf(stderr, "failed to write new super block err %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#define __DISKIO__
|
#define __DISKIO__
|
||||||
|
|
||||||
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
|
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
|
||||||
|
#define BTRFS_SUPER_INFO_SIZE 4096
|
||||||
|
|
||||||
struct btrfs_device;
|
struct btrfs_device;
|
||||||
|
|
||||||
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
||||||
|
3
utils.c
3
utils.c
@ -471,6 +471,9 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
|
|||||||
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
list_add(&device->dev_list, &root->fs_info->fs_devices->devices);
|
list_add(&device->dev_list, &root->fs_info->fs_devices->devices);
|
||||||
|
ret = btrfs_bootstrap_super_map(&root->fs_info->mapping_tree,
|
||||||
|
root->fs_info->fs_devices);
|
||||||
|
BUG_ON(ret);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
volumes.c
64
volumes.c
@ -862,6 +862,57 @@ struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid)
|
|||||||
return __find_device(head, devid);
|
return __find_device(head, devid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_bootstrap_super_map(struct btrfs_mapping_tree *map_tree,
|
||||||
|
struct btrfs_fs_devices *fs_devices)
|
||||||
|
{
|
||||||
|
struct map_lookup *map;
|
||||||
|
u64 logical = BTRFS_SUPER_INFO_OFFSET;
|
||||||
|
u64 length = BTRFS_SUPER_INFO_SIZE;
|
||||||
|
int num_stripes = 0;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
struct list_head *cur;
|
||||||
|
|
||||||
|
list_for_each(cur, &fs_devices->devices) {
|
||||||
|
num_stripes++;
|
||||||
|
}
|
||||||
|
map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
|
||||||
|
if (!map)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
map->ce.start = logical;
|
||||||
|
map->ce.size = length;
|
||||||
|
map->num_stripes = num_stripes;
|
||||||
|
map->io_width = length;
|
||||||
|
map->io_align = length;
|
||||||
|
map->sector_size = length;
|
||||||
|
map->stripe_len = length;
|
||||||
|
map->type = BTRFS_BLOCK_GROUP_RAID1;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
list_for_each(cur, &fs_devices->devices) {
|
||||||
|
struct btrfs_device *device = list_entry(cur,
|
||||||
|
struct btrfs_device,
|
||||||
|
dev_list);
|
||||||
|
map->stripes[i].physical = logical;
|
||||||
|
map->stripes[i].dev = device;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ret = insert_existing_cache_extent(&map_tree->cache_tree, &map->ce);
|
||||||
|
if (ret == -EEXIST) {
|
||||||
|
struct cache_extent *old;
|
||||||
|
struct map_lookup *old_map;
|
||||||
|
old = find_cache_extent(&map_tree->cache_tree, logical, length);
|
||||||
|
old_map = container_of(old, struct map_lookup, ce);
|
||||||
|
remove_cache_extent(&map_tree->cache_tree, old);
|
||||||
|
kfree(old_map);
|
||||||
|
ret = insert_existing_cache_extent(&map_tree->cache_tree,
|
||||||
|
&map->ce);
|
||||||
|
}
|
||||||
|
BUG_ON(ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
||||||
struct extent_buffer *leaf,
|
struct extent_buffer *leaf,
|
||||||
struct btrfs_chunk *chunk)
|
struct btrfs_chunk *chunk)
|
||||||
@ -872,12 +923,20 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
u64 logical;
|
u64 logical;
|
||||||
u64 length;
|
u64 length;
|
||||||
u64 devid;
|
u64 devid;
|
||||||
|
u64 super_offset_diff = 0;
|
||||||
int num_stripes;
|
int num_stripes;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
logical = key->objectid;
|
logical = key->objectid;
|
||||||
length = key->offset;
|
length = key->offset;
|
||||||
|
|
||||||
|
if (logical < BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE) {
|
||||||
|
super_offset_diff = BTRFS_SUPER_INFO_OFFSET +
|
||||||
|
BTRFS_SUPER_INFO_SIZE - logical;
|
||||||
|
logical = BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
ce = find_first_cache_extent(&map_tree->cache_tree, logical);
|
ce = find_first_cache_extent(&map_tree->cache_tree, logical);
|
||||||
|
|
||||||
/* already mapped? */
|
/* already mapped? */
|
||||||
@ -891,7 +950,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
map->ce.start = logical;
|
map->ce.start = logical;
|
||||||
map->ce.size = length;
|
map->ce.size = length - super_offset_diff;
|
||||||
map->num_stripes = num_stripes;
|
map->num_stripes = num_stripes;
|
||||||
map->io_width = btrfs_chunk_io_width(leaf, chunk);
|
map->io_width = btrfs_chunk_io_width(leaf, chunk);
|
||||||
map->io_align = btrfs_chunk_io_align(leaf, chunk);
|
map->io_align = btrfs_chunk_io_align(leaf, chunk);
|
||||||
@ -901,7 +960,8 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
|
|
||||||
for (i = 0; i < num_stripes; i++) {
|
for (i = 0; i < num_stripes; i++) {
|
||||||
map->stripes[i].physical =
|
map->stripes[i].physical =
|
||||||
btrfs_stripe_offset_nr(leaf, chunk, i);
|
btrfs_stripe_offset_nr(leaf, chunk, i) +
|
||||||
|
super_offset_diff;
|
||||||
devid = btrfs_stripe_devid_nr(leaf, chunk, i);
|
devid = btrfs_stripe_devid_nr(leaf, chunk, i);
|
||||||
map->stripes[i].dev = btrfs_find_device(root, devid);
|
map->stripes[i].dev = btrfs_find_device(root, devid);
|
||||||
if (!map->stripes[i].dev) {
|
if (!map->stripes[i].dev) {
|
||||||
|
@ -105,4 +105,6 @@ int btrfs_scan_one_device(int fd, const char *path,
|
|||||||
struct btrfs_fs_devices **fs_devices_ret,
|
struct btrfs_fs_devices **fs_devices_ret,
|
||||||
u64 *total_devs, u64 super_offset);
|
u64 *total_devs, u64 super_offset);
|
||||||
int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len);
|
int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len);
|
||||||
|
int btrfs_bootstrap_super_map(struct btrfs_mapping_tree *map_tree,
|
||||||
|
struct btrfs_fs_devices *fs_devices);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user