mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-24 20:17:57 +00:00
btrfs-progs: Add support for metadata_uuid field
Add support for a new metadata_uuid field. This is just a preparatory commit which switches all users of the fsid field for metdata comparison purposes to utilize the new field. This more or less mirrors the kernel patch, additionally: * Update 'btrfs inspect-internal dump-super' to account for the new field. This involes introducing the 'metadata_uuid' line to the output and updating the logic for comparing the fs uuid to the dev_item uuid. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
9996feb94d
commit
c4aadd9af2
@ -248,6 +248,9 @@ static int change_fsid_prepare(struct btrfs_fs_info *fs_info)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Also need to change the metadatauuid of the fs info */
|
||||||
|
memcpy(fs_info->metadata_uuid, fs_info->new_fsid, BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
/* also restore new chunk_tree_id into tree_root for restore */
|
/* also restore new chunk_tree_id into tree_root for restore */
|
||||||
write_extent_buffer(tree_root->node, fs_info->new_chunk_tree_uuid,
|
write_extent_buffer(tree_root->node, fs_info->new_chunk_tree_uuid,
|
||||||
btrfs_header_chunk_tree_uuid(tree_root->node),
|
btrfs_header_chunk_tree_uuid(tree_root->node),
|
||||||
|
@ -8424,7 +8424,7 @@ static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
|
|||||||
btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV);
|
btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV);
|
||||||
btrfs_set_header_owner(c, root->root_key.objectid);
|
btrfs_set_header_owner(c, root->root_key.objectid);
|
||||||
|
|
||||||
write_extent_buffer(c, root->fs_info->fsid,
|
write_extent_buffer(c, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
|
write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
|
||||||
|
@ -759,7 +759,7 @@ static int scan_one_device(void *dev_scan_struct)
|
|||||||
rc->nodesize)
|
rc->nodesize)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (memcmp_extent_buffer(buf, rc->fs_devices->fsid,
|
if (memcmp_extent_buffer(buf, rc->fs_devices->metadata_uuid,
|
||||||
btrfs_header_fsid(),
|
btrfs_header_fsid(),
|
||||||
BTRFS_FSID_SIZE)) {
|
BTRFS_FSID_SIZE)) {
|
||||||
bytenr += rc->sectorsize;
|
bytenr += rc->sectorsize;
|
||||||
@ -1155,7 +1155,7 @@ static int __rebuild_chunk_root(struct btrfs_trans_handle *trans,
|
|||||||
btrfs_set_header_level(cow, 0);
|
btrfs_set_header_level(cow, 0);
|
||||||
btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV);
|
btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV);
|
||||||
btrfs_set_header_owner(cow, BTRFS_CHUNK_TREE_OBJECTID);
|
btrfs_set_header_owner(cow, BTRFS_CHUNK_TREE_OBJECTID);
|
||||||
write_extent_buffer(cow, root->fs_info->fsid,
|
write_extent_buffer(cow, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
write_extent_buffer(cow, root->fs_info->chunk_tree_uuid,
|
write_extent_buffer(cow, root->fs_info->chunk_tree_uuid,
|
||||||
@ -1192,7 +1192,8 @@ static int __rebuild_device_items(struct btrfs_trans_handle *trans,
|
|||||||
btrfs_set_stack_device_io_width(dev_item, dev->io_width);
|
btrfs_set_stack_device_io_width(dev_item, dev->io_width);
|
||||||
btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
|
btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
|
||||||
memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
|
memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
|
||||||
memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE);
|
memcpy(dev_item->fsid, dev->fs_devices->metadata_uuid,
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
ret = btrfs_insert_item(trans, root, &key,
|
ret = btrfs_insert_item(trans, root, &key,
|
||||||
dev_item, sizeof(*dev_item));
|
dev_item, sizeof(*dev_item));
|
||||||
@ -1432,6 +1433,7 @@ open_ctree_with_broken_chunk(struct recover_control *rc)
|
|||||||
struct btrfs_fs_info *fs_info;
|
struct btrfs_fs_info *fs_info;
|
||||||
struct btrfs_super_block *disk_super;
|
struct btrfs_super_block *disk_super;
|
||||||
struct extent_buffer *eb;
|
struct extent_buffer *eb;
|
||||||
|
u64 features;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fs_info = btrfs_new_fs_info(1, BTRFS_SUPER_INFO_OFFSET);
|
fs_info = btrfs_new_fs_info(1, BTRFS_SUPER_INFO_OFFSET);
|
||||||
@ -1464,6 +1466,14 @@ open_ctree_with_broken_chunk(struct recover_control *rc)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_devices;
|
goto out_devices;
|
||||||
|
|
||||||
|
features = btrfs_super_incompat_flags(disk_super);
|
||||||
|
|
||||||
|
if (features & BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
|
||||||
|
memcpy(fs_info->metadata_uuid, disk_super->metadata_uuid,
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
else
|
||||||
|
memcpy(fs_info->metadata_uuid, fs_info->fsid, BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
btrfs_setup_root(fs_info->chunk_root, fs_info,
|
btrfs_setup_root(fs_info->chunk_root, fs_info,
|
||||||
BTRFS_CHUNK_TREE_OBJECTID);
|
BTRFS_CHUNK_TREE_OBJECTID);
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@ static int match_search_item_kernel(u8 *fsid, char *mnt, char *label,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Search for user visible uuid 'search' in registered filesystems */
|
||||||
static int uuid_search(struct btrfs_fs_devices *fs_devices, const char *search)
|
static int uuid_search(struct btrfs_fs_devices *fs_devices, const char *search)
|
||||||
{
|
{
|
||||||
char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
|
char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
|
||||||
@ -498,6 +499,7 @@ static int copy_fs_devices(struct btrfs_fs_devices *dst,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
memcpy(dst->fsid, src->fsid, BTRFS_FSID_SIZE);
|
memcpy(dst->fsid, src->fsid, BTRFS_FSID_SIZE);
|
||||||
|
memcpy(dst->metadata_uuid, src->metadata_uuid, BTRFS_FSID_SIZE);
|
||||||
INIT_LIST_HEAD(&dst->devices);
|
INIT_LIST_HEAD(&dst->devices);
|
||||||
dst->seed = NULL;
|
dst->seed = NULL;
|
||||||
|
|
||||||
|
@ -228,7 +228,8 @@ static struct readable_flag_entry incompat_flags_array[] = {
|
|||||||
DEF_INCOMPAT_FLAG_ENTRY(EXTENDED_IREF),
|
DEF_INCOMPAT_FLAG_ENTRY(EXTENDED_IREF),
|
||||||
DEF_INCOMPAT_FLAG_ENTRY(RAID56),
|
DEF_INCOMPAT_FLAG_ENTRY(RAID56),
|
||||||
DEF_INCOMPAT_FLAG_ENTRY(SKINNY_METADATA),
|
DEF_INCOMPAT_FLAG_ENTRY(SKINNY_METADATA),
|
||||||
DEF_INCOMPAT_FLAG_ENTRY(NO_HOLES)
|
DEF_INCOMPAT_FLAG_ENTRY(NO_HOLES),
|
||||||
|
DEF_INCOMPAT_FLAG_ENTRY(METADATA_UUID)
|
||||||
};
|
};
|
||||||
static const int incompat_flags_num = sizeof(incompat_flags_array) /
|
static const int incompat_flags_num = sizeof(incompat_flags_array) /
|
||||||
sizeof(struct readable_flag_entry);
|
sizeof(struct readable_flag_entry);
|
||||||
@ -319,6 +320,10 @@ static void dump_superblock(struct btrfs_super_block *sb, int full)
|
|||||||
u8 *p;
|
u8 *p;
|
||||||
u32 csum_size;
|
u32 csum_size;
|
||||||
u16 csum_type;
|
u16 csum_type;
|
||||||
|
bool metadata_uuid_present = (btrfs_super_incompat_flags(sb) &
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
|
||||||
|
int cmp_res = 0;
|
||||||
|
|
||||||
|
|
||||||
csum_type = btrfs_super_csum_type(sb);
|
csum_type = btrfs_super_csum_type(sb);
|
||||||
csum_size = BTRFS_CSUM_SIZE;
|
csum_size = BTRFS_CSUM_SIZE;
|
||||||
@ -365,6 +370,12 @@ static void dump_superblock(struct btrfs_super_block *sb, int full)
|
|||||||
|
|
||||||
uuid_unparse(sb->fsid, buf);
|
uuid_unparse(sb->fsid, buf);
|
||||||
printf("fsid\t\t\t%s\n", buf);
|
printf("fsid\t\t\t%s\n", buf);
|
||||||
|
if (metadata_uuid_present) {
|
||||||
|
uuid_unparse(sb->metadata_uuid, buf);
|
||||||
|
printf("metadata_uuid\t\t%s\n", buf);
|
||||||
|
} else {
|
||||||
|
printf("metadata_uuid\t\t%s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
printf("label\t\t\t");
|
printf("label\t\t\t");
|
||||||
s = sb->label;
|
s = sb->label;
|
||||||
@ -424,9 +435,14 @@ static void dump_superblock(struct btrfs_super_block *sb, int full)
|
|||||||
printf("dev_item.uuid\t\t%s\n", buf);
|
printf("dev_item.uuid\t\t%s\n", buf);
|
||||||
|
|
||||||
uuid_unparse(sb->dev_item.fsid, buf);
|
uuid_unparse(sb->dev_item.fsid, buf);
|
||||||
|
if (metadata_uuid_present) {
|
||||||
|
cmp_res = !memcmp(sb->dev_item.fsid, sb->metadata_uuid,
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
} else {
|
||||||
|
cmp_res = !memcmp(sb->dev_item.fsid, sb->fsid, BTRFS_FSID_SIZE);
|
||||||
|
}
|
||||||
printf("dev_item.fsid\t\t%s %s\n", buf,
|
printf("dev_item.fsid\t\t%s %s\n", buf,
|
||||||
!memcmp(sb->dev_item.fsid, sb->fsid, BTRFS_FSID_SIZE) ?
|
cmp_res ? "[match]" : "[DON'T MATCH]");
|
||||||
"[match]" : "[DON'T MATCH]");
|
|
||||||
|
|
||||||
printf("dev_item.type\t\t%llu\n", (unsigned long long)
|
printf("dev_item.type\t\t%llu\n", (unsigned long long)
|
||||||
btrfs_stack_device_type(&sb->dev_item));
|
btrfs_stack_device_type(&sb->dev_item));
|
||||||
|
@ -107,9 +107,11 @@ static int setup_temp_super(int fd, struct btrfs_mkfs_config *cfg,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
uuid_copy(super->metadata_uuid, super->fsid);
|
||||||
} else {
|
} else {
|
||||||
uuid_generate(super->fsid);
|
uuid_generate(super->fsid);
|
||||||
uuid_unparse(super->fsid, cfg->fs_uuid);
|
uuid_unparse(super->fsid, cfg->fs_uuid);
|
||||||
|
uuid_copy(super->metadata_uuid, super->fsid);
|
||||||
}
|
}
|
||||||
uuid_generate(chunk_uuid);
|
uuid_generate(chunk_uuid);
|
||||||
uuid_unparse(chunk_uuid, cfg->chunk_uuid);
|
uuid_unparse(chunk_uuid, cfg->chunk_uuid);
|
||||||
|
10
ctree.c
10
ctree.c
@ -134,7 +134,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
|
|||||||
else
|
else
|
||||||
btrfs_set_header_owner(cow, new_root_objectid);
|
btrfs_set_header_owner(cow, new_root_objectid);
|
||||||
|
|
||||||
write_extent_buffer(cow, root->fs_info->fsid,
|
write_extent_buffer(cow, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
WARN_ON(btrfs_header_generation(buf) > trans->transid);
|
WARN_ON(btrfs_header_generation(buf) > trans->transid);
|
||||||
@ -308,7 +308,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|||||||
else
|
else
|
||||||
btrfs_set_header_owner(cow, root->root_key.objectid);
|
btrfs_set_header_owner(cow, root->root_key.objectid);
|
||||||
|
|
||||||
write_extent_buffer(cow, root->fs_info->fsid,
|
write_extent_buffer(cow, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
WARN_ON(!(buf->flags & EXTENT_BAD_TRANSID) &&
|
WARN_ON(!(buf->flags & EXTENT_BAD_TRANSID) &&
|
||||||
@ -1548,7 +1548,7 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans,
|
|||||||
|
|
||||||
root_add_used(root, root->fs_info->nodesize);
|
root_add_used(root, root->fs_info->nodesize);
|
||||||
|
|
||||||
write_extent_buffer(c, root->fs_info->fsid,
|
write_extent_buffer(c, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
|
write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
|
||||||
@ -1669,7 +1669,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
|
|||||||
btrfs_set_header_generation(split, trans->transid);
|
btrfs_set_header_generation(split, trans->transid);
|
||||||
btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV);
|
btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV);
|
||||||
btrfs_set_header_owner(split, root->root_key.objectid);
|
btrfs_set_header_owner(split, root->root_key.objectid);
|
||||||
write_extent_buffer(split, root->fs_info->fsid,
|
write_extent_buffer(split, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
write_extent_buffer(split, root->fs_info->chunk_tree_uuid,
|
write_extent_buffer(split, root->fs_info->chunk_tree_uuid,
|
||||||
btrfs_header_chunk_tree_uuid(split),
|
btrfs_header_chunk_tree_uuid(split),
|
||||||
@ -2251,7 +2251,7 @@ again:
|
|||||||
btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV);
|
btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV);
|
||||||
btrfs_set_header_owner(right, root->root_key.objectid);
|
btrfs_set_header_owner(right, root->root_key.objectid);
|
||||||
btrfs_set_header_level(right, 0);
|
btrfs_set_header_level(right, 0);
|
||||||
write_extent_buffer(right, root->fs_info->fsid,
|
write_extent_buffer(right, root->fs_info->metadata_uuid,
|
||||||
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
write_extent_buffer(right, root->fs_info->chunk_tree_uuid,
|
write_extent_buffer(right, root->fs_info->chunk_tree_uuid,
|
||||||
|
8
ctree.h
8
ctree.h
@ -454,8 +454,9 @@ struct btrfs_super_block {
|
|||||||
__le64 cache_generation;
|
__le64 cache_generation;
|
||||||
__le64 uuid_tree_generation;
|
__le64 uuid_tree_generation;
|
||||||
|
|
||||||
|
u8 metadata_uuid[BTRFS_FSID_SIZE];
|
||||||
/* future expansion */
|
/* future expansion */
|
||||||
__le64 reserved[30];
|
__le64 reserved[28];
|
||||||
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
|
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
|
||||||
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
|
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
@ -489,6 +490,7 @@ struct btrfs_super_block {
|
|||||||
#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7)
|
#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7)
|
||||||
#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
|
#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
|
||||||
#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9)
|
#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9)
|
||||||
|
#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
|
||||||
|
|
||||||
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL
|
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL
|
||||||
|
|
||||||
@ -511,7 +513,8 @@ struct btrfs_super_block {
|
|||||||
BTRFS_FEATURE_INCOMPAT_RAID56 | \
|
BTRFS_FEATURE_INCOMPAT_RAID56 | \
|
||||||
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
|
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
|
||||||
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \
|
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \
|
||||||
BTRFS_FEATURE_INCOMPAT_NO_HOLES)
|
BTRFS_FEATURE_INCOMPAT_NO_HOLES | \
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A leaf is full of items. offset and size tell us where to find
|
* A leaf is full of items. offset and size tell us where to find
|
||||||
@ -1090,6 +1093,7 @@ struct btrfs_device;
|
|||||||
struct btrfs_fs_devices;
|
struct btrfs_fs_devices;
|
||||||
struct btrfs_fs_info {
|
struct btrfs_fs_info {
|
||||||
u8 fsid[BTRFS_FSID_SIZE];
|
u8 fsid[BTRFS_FSID_SIZE];
|
||||||
|
u8 metadata_uuid[BTRFS_FSID_SIZE];
|
||||||
u8 *new_fsid;
|
u8 *new_fsid;
|
||||||
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
|
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
|
||||||
u8 *new_chunk_tree_uuid;
|
u8 *new_chunk_tree_uuid;
|
||||||
|
58
disk-io.c
58
disk-io.c
@ -55,8 +55,9 @@ static int check_tree_block(struct btrfs_fs_info *fs_info,
|
|||||||
struct extent_buffer *buf)
|
struct extent_buffer *buf)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct btrfs_fs_devices *fs_devices;
|
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
|
||||||
u32 nodesize = fs_info->nodesize;
|
u32 nodesize = fs_info->nodesize;
|
||||||
|
bool fsid_match = false;
|
||||||
int ret = BTRFS_BAD_FSID;
|
int ret = BTRFS_BAD_FSID;
|
||||||
|
|
||||||
if (buf->start != btrfs_header_bytenr(buf))
|
if (buf->start != btrfs_header_bytenr(buf))
|
||||||
@ -72,12 +73,26 @@ static int check_tree_block(struct btrfs_fs_info *fs_info,
|
|||||||
btrfs_header_level(buf) != 0)
|
btrfs_header_level(buf) != 0)
|
||||||
return BTRFS_BAD_NRITEMS;
|
return BTRFS_BAD_NRITEMS;
|
||||||
|
|
||||||
fs_devices = fs_info->fs_devices;
|
|
||||||
while (fs_devices) {
|
while (fs_devices) {
|
||||||
if (fs_info->ignore_fsid_mismatch ||
|
/*
|
||||||
!memcmp_extent_buffer(buf, fs_devices->fsid,
|
* Checking the incompat flag is only valid for the current
|
||||||
|
* fs. For seed devices it's forbidden to have their uuid
|
||||||
|
* changed so reading ->fsid in this case is fine
|
||||||
|
*/
|
||||||
|
if (fs_devices == fs_info->fs_devices &&
|
||||||
|
btrfs_fs_incompat(fs_info, METADATA_UUID))
|
||||||
|
fsid_match = !memcmp_extent_buffer(buf,
|
||||||
|
fs_devices->metadata_uuid,
|
||||||
btrfs_header_fsid(),
|
btrfs_header_fsid(),
|
||||||
BTRFS_FSID_SIZE)) {
|
BTRFS_FSID_SIZE);
|
||||||
|
else
|
||||||
|
fsid_match = !memcmp_extent_buffer(buf,
|
||||||
|
fs_devices->fsid,
|
||||||
|
btrfs_header_fsid(),
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
if (fs_info->ignore_fsid_mismatch || fsid_match) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -103,7 +118,7 @@ static void print_tree_block_error(struct btrfs_fs_info *fs_info,
|
|||||||
read_extent_buffer(eb, buf, btrfs_header_fsid(),
|
read_extent_buffer(eb, buf, btrfs_header_fsid(),
|
||||||
BTRFS_UUID_SIZE);
|
BTRFS_UUID_SIZE);
|
||||||
uuid_unparse(buf, found_uuid);
|
uuid_unparse(buf, found_uuid);
|
||||||
uuid_unparse(fs_info->fsid, fs_uuid);
|
uuid_unparse(fs_info->metadata_uuid, fs_uuid);
|
||||||
fprintf(stderr, "fsid mismatch, want=%s, have=%s\n",
|
fprintf(stderr, "fsid mismatch, want=%s, have=%s\n",
|
||||||
fs_uuid, found_uuid);
|
fs_uuid, found_uuid);
|
||||||
break;
|
break;
|
||||||
@ -1170,6 +1185,12 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
|
memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
|
||||||
|
if (btrfs_fs_incompat(fs_info, METADATA_UUID)) {
|
||||||
|
memcpy(fs_info->metadata_uuid, disk_super->metadata_uuid,
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
} else {
|
||||||
|
memcpy(fs_info->metadata_uuid, fs_info->fsid, BTRFS_FSID_SIZE);
|
||||||
|
}
|
||||||
fs_info->sectorsize = btrfs_super_sectorsize(disk_super);
|
fs_info->sectorsize = btrfs_super_sectorsize(disk_super);
|
||||||
fs_info->nodesize = btrfs_super_nodesize(disk_super);
|
fs_info->nodesize = btrfs_super_nodesize(disk_super);
|
||||||
fs_info->stripesize = btrfs_super_stripesize(disk_super);
|
fs_info->stripesize = btrfs_super_stripesize(disk_super);
|
||||||
@ -1290,6 +1311,7 @@ static int check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
|||||||
u32 crc;
|
u32 crc;
|
||||||
u16 csum_type;
|
u16 csum_type;
|
||||||
int csum_size;
|
int csum_size;
|
||||||
|
u8 *metadata_uuid;
|
||||||
|
|
||||||
if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
|
if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
|
||||||
if (btrfs_super_magic(sb) == BTRFS_MAGIC_TEMPORARY) {
|
if (btrfs_super_magic(sb) == BTRFS_MAGIC_TEMPORARY) {
|
||||||
@ -1378,11 +1400,16 @@ static int check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
|||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(sb->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) {
|
if (btrfs_super_incompat_flags(sb) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
|
||||||
|
metadata_uuid = sb->metadata_uuid;
|
||||||
|
else
|
||||||
|
metadata_uuid = sb->fsid;
|
||||||
|
|
||||||
|
if (memcmp(metadata_uuid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
|
||||||
char fsid[BTRFS_UUID_UNPARSED_SIZE];
|
char fsid[BTRFS_UUID_UNPARSED_SIZE];
|
||||||
char dev_fsid[BTRFS_UUID_UNPARSED_SIZE];
|
char dev_fsid[BTRFS_UUID_UNPARSED_SIZE];
|
||||||
|
|
||||||
uuid_unparse(sb->fsid, fsid);
|
uuid_unparse(sb->metadata_uuid, fsid);
|
||||||
uuid_unparse(sb->dev_item.fsid, dev_fsid);
|
uuid_unparse(sb->dev_item.fsid, dev_fsid);
|
||||||
if (sbflags & SBREAD_IGNORE_FSID_MISMATCH) {
|
if (sbflags & SBREAD_IGNORE_FSID_MISMATCH) {
|
||||||
warning("ignored: dev_item fsid mismatch: %s != %s",
|
warning("ignored: dev_item fsid mismatch: %s != %s",
|
||||||
@ -1454,6 +1481,7 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
|
|||||||
unsigned sbflags)
|
unsigned sbflags)
|
||||||
{
|
{
|
||||||
u8 fsid[BTRFS_FSID_SIZE];
|
u8 fsid[BTRFS_FSID_SIZE];
|
||||||
|
u8 metadata_uuid[BTRFS_FSID_SIZE];
|
||||||
int fsid_is_initialized = 0;
|
int fsid_is_initialized = 0;
|
||||||
char tmp[BTRFS_SUPER_INFO_SIZE];
|
char tmp[BTRFS_SUPER_INFO_SIZE];
|
||||||
struct btrfs_super_block *buf = (struct btrfs_super_block *)tmp;
|
struct btrfs_super_block *buf = (struct btrfs_super_block *)tmp;
|
||||||
@ -1461,6 +1489,7 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
|
|||||||
int ret;
|
int ret;
|
||||||
int max_super = sbflags & SBREAD_RECOVER ? BTRFS_SUPER_MIRROR_MAX : 1;
|
int max_super = sbflags & SBREAD_RECOVER ? BTRFS_SUPER_MIRROR_MAX : 1;
|
||||||
u64 transid = 0;
|
u64 transid = 0;
|
||||||
|
bool metadata_uuid_set = false;
|
||||||
u64 bytenr;
|
u64 bytenr;
|
||||||
|
|
||||||
if (sb_bytenr != BTRFS_SUPER_INFO_OFFSET) {
|
if (sb_bytenr != BTRFS_SUPER_INFO_OFFSET) {
|
||||||
@ -1505,9 +1534,18 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!fsid_is_initialized) {
|
if (!fsid_is_initialized) {
|
||||||
|
if (btrfs_super_incompat_flags(buf) &
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID) {
|
||||||
|
metadata_uuid_set = true;
|
||||||
|
memcpy(metadata_uuid, buf->metadata_uuid,
|
||||||
|
sizeof(metadata_uuid));
|
||||||
|
}
|
||||||
memcpy(fsid, buf->fsid, sizeof(fsid));
|
memcpy(fsid, buf->fsid, sizeof(fsid));
|
||||||
fsid_is_initialized = 1;
|
fsid_is_initialized = 1;
|
||||||
} else if (memcmp(fsid, buf->fsid, sizeof(fsid))) {
|
} else if (memcmp(fsid, buf->fsid, sizeof(fsid)) ||
|
||||||
|
(metadata_uuid_set && memcmp(metadata_uuid,
|
||||||
|
buf->metadata_uuid,
|
||||||
|
sizeof(metadata_uuid)))) {
|
||||||
/*
|
/*
|
||||||
* the superblocks (the original one and
|
* the superblocks (the original one and
|
||||||
* its backups) contain data of different
|
* its backups) contain data of different
|
||||||
@ -1608,7 +1646,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info)
|
|||||||
btrfs_set_stack_device_io_width(dev_item, dev->io_width);
|
btrfs_set_stack_device_io_width(dev_item, dev->io_width);
|
||||||
btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
|
btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
|
||||||
memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
|
memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
|
||||||
memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE);
|
memcpy(dev_item->fsid, fs_info->metadata_uuid, BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
flags = btrfs_super_flags(sb);
|
flags = btrfs_super_flags(sb);
|
||||||
btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
|
btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
|
||||||
|
@ -1453,7 +1453,8 @@ static struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
|
|||||||
btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
|
btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
|
||||||
btrfs_set_header_owner(leaf, objectid);
|
btrfs_set_header_owner(leaf, objectid);
|
||||||
root->node = leaf;
|
root->node = leaf;
|
||||||
write_extent_buffer(leaf, fs_info->fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
write_extent_buffer(leaf, fs_info->metadata_uuid, btrfs_header_fsid(),
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
write_extent_buffer(leaf, fs_info->chunk_tree_uuid,
|
write_extent_buffer(leaf, fs_info->chunk_tree_uuid,
|
||||||
btrfs_header_chunk_tree_uuid(leaf),
|
btrfs_header_chunk_tree_uuid(leaf),
|
||||||
BTRFS_UUID_SIZE);
|
BTRFS_UUID_SIZE);
|
||||||
|
17
image/main.c
17
image/main.c
@ -1596,9 +1596,12 @@ static int fill_mdres_info(struct mdrestore_struct *mdres,
|
|||||||
|
|
||||||
super = (struct btrfs_super_block *)outbuf;
|
super = (struct btrfs_super_block *)outbuf;
|
||||||
mdres->nodesize = btrfs_super_nodesize(super);
|
mdres->nodesize = btrfs_super_nodesize(super);
|
||||||
|
if (btrfs_super_incompat_flags(super) &
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
|
||||||
|
memcpy(mdres->fsid, super->metadata_uuid, BTRFS_FSID_SIZE);
|
||||||
|
else
|
||||||
memcpy(mdres->fsid, super->fsid, BTRFS_FSID_SIZE);
|
memcpy(mdres->fsid, super->fsid, BTRFS_FSID_SIZE);
|
||||||
memcpy(mdres->uuid, super->dev_item.uuid,
|
memcpy(mdres->uuid, super->dev_item.uuid, BTRFS_UUID_SIZE);
|
||||||
BTRFS_UUID_SIZE);
|
|
||||||
mdres->devid = le64_to_cpu(super->dev_item.devid);
|
mdres->devid = le64_to_cpu(super->dev_item.devid);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1725,7 +1728,7 @@ static int read_chunk_block(struct mdrestore_struct *mdres, u8 *buffer,
|
|||||||
|
|
||||||
if (memcmp(mdres->fsid, eb->data + offsetof(struct btrfs_header, fsid),
|
if (memcmp(mdres->fsid, eb->data + offsetof(struct btrfs_header, fsid),
|
||||||
BTRFS_FSID_SIZE)) {
|
BTRFS_FSID_SIZE)) {
|
||||||
error("filesystem UUID of eb %llu does not match",
|
error("filesystem metadata UUID of eb %llu does not match",
|
||||||
(unsigned long long)bytenr);
|
(unsigned long long)bytenr);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2039,9 +2042,13 @@ static int build_chunk_tree(struct mdrestore_struct *mdres,
|
|||||||
super = (struct btrfs_super_block *)buffer;
|
super = (struct btrfs_super_block *)buffer;
|
||||||
chunk_root_bytenr = btrfs_super_chunk_root(super);
|
chunk_root_bytenr = btrfs_super_chunk_root(super);
|
||||||
mdres->nodesize = btrfs_super_nodesize(super);
|
mdres->nodesize = btrfs_super_nodesize(super);
|
||||||
|
if (btrfs_super_incompat_flags(super) &
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
|
||||||
|
memcpy(mdres->fsid, super->metadata_uuid, BTRFS_FSID_SIZE);
|
||||||
|
else
|
||||||
memcpy(mdres->fsid, super->fsid, BTRFS_FSID_SIZE);
|
memcpy(mdres->fsid, super->fsid, BTRFS_FSID_SIZE);
|
||||||
memcpy(mdres->uuid, super->dev_item.uuid,
|
|
||||||
BTRFS_UUID_SIZE);
|
memcpy(mdres->uuid, super->dev_item.uuid, BTRFS_UUID_SIZE);
|
||||||
mdres->devid = le64_to_cpu(super->dev_item.devid);
|
mdres->devid = le64_to_cpu(super->dev_item.devid);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
pthread_mutex_unlock(&mdres->mutex);
|
pthread_mutex_unlock(&mdres->mutex);
|
||||||
|
34
volumes.c
34
volumes.c
@ -142,13 +142,19 @@ static struct btrfs_device *find_device(struct btrfs_fs_devices *fs_devices,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct btrfs_fs_devices *find_fsid(u8 *fsid)
|
static struct btrfs_fs_devices *find_fsid(u8 *fsid, u8 *metadata_uuid)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_devices *fs_devices;
|
struct btrfs_fs_devices *fs_devices;
|
||||||
|
|
||||||
list_for_each_entry(fs_devices, &fs_uuids, list) {
|
list_for_each_entry(fs_devices, &fs_uuids, list) {
|
||||||
if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0)
|
if (metadata_uuid && (memcmp(fsid, fs_devices->fsid,
|
||||||
|
BTRFS_FSID_SIZE) == 0) &&
|
||||||
|
(memcmp(metadata_uuid, fs_devices->metadata_uuid,
|
||||||
|
BTRFS_FSID_SIZE) == 0)) {
|
||||||
return fs_devices;
|
return fs_devices;
|
||||||
|
} else if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0){
|
||||||
|
return fs_devices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -160,8 +166,15 @@ static int device_list_add(const char *path,
|
|||||||
struct btrfs_device *device;
|
struct btrfs_device *device;
|
||||||
struct btrfs_fs_devices *fs_devices;
|
struct btrfs_fs_devices *fs_devices;
|
||||||
u64 found_transid = btrfs_super_generation(disk_super);
|
u64 found_transid = btrfs_super_generation(disk_super);
|
||||||
|
bool metadata_uuid = (btrfs_super_incompat_flags(disk_super) &
|
||||||
|
BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
|
||||||
|
|
||||||
|
if (metadata_uuid)
|
||||||
|
fs_devices = find_fsid(disk_super->fsid,
|
||||||
|
disk_super->metadata_uuid);
|
||||||
|
else
|
||||||
|
fs_devices = find_fsid(disk_super->fsid, NULL);
|
||||||
|
|
||||||
fs_devices = find_fsid(disk_super->fsid);
|
|
||||||
if (!fs_devices) {
|
if (!fs_devices) {
|
||||||
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
|
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
|
||||||
if (!fs_devices)
|
if (!fs_devices)
|
||||||
@ -169,6 +182,13 @@ static int device_list_add(const char *path,
|
|||||||
INIT_LIST_HEAD(&fs_devices->devices);
|
INIT_LIST_HEAD(&fs_devices->devices);
|
||||||
list_add(&fs_devices->list, &fs_uuids);
|
list_add(&fs_devices->list, &fs_uuids);
|
||||||
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
|
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
|
||||||
|
if (metadata_uuid)
|
||||||
|
memcpy(fs_devices->metadata_uuid,
|
||||||
|
disk_super->metadata_uuid, BTRFS_FSID_SIZE);
|
||||||
|
else
|
||||||
|
memcpy(fs_devices->metadata_uuid, fs_devices->fsid,
|
||||||
|
BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
fs_devices->latest_devid = devid;
|
fs_devices->latest_devid = devid;
|
||||||
fs_devices->latest_trans = found_transid;
|
fs_devices->latest_trans = found_transid;
|
||||||
fs_devices->lowest_devid = (u64)-1;
|
fs_devices->lowest_devid = (u64)-1;
|
||||||
@ -721,7 +741,7 @@ int btrfs_add_device(struct btrfs_trans_handle *trans,
|
|||||||
ptr = (unsigned long)btrfs_device_uuid(dev_item);
|
ptr = (unsigned long)btrfs_device_uuid(dev_item);
|
||||||
write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
|
write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
|
||||||
ptr = (unsigned long)btrfs_device_fsid(dev_item);
|
ptr = (unsigned long)btrfs_device_fsid(dev_item);
|
||||||
write_extent_buffer(leaf, fs_info->fsid, ptr, BTRFS_UUID_SIZE);
|
write_extent_buffer(leaf, fs_info->metadata_uuid, ptr, BTRFS_UUID_SIZE);
|
||||||
btrfs_mark_buffer_dirty(leaf);
|
btrfs_mark_buffer_dirty(leaf);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -1698,7 +1718,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
|
|||||||
cur_devices = fs_info->fs_devices;
|
cur_devices = fs_info->fs_devices;
|
||||||
while (cur_devices) {
|
while (cur_devices) {
|
||||||
if (!fsid ||
|
if (!fsid ||
|
||||||
(!memcmp(cur_devices->fsid, fsid, BTRFS_UUID_SIZE) ||
|
(!memcmp(cur_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE) ||
|
||||||
fs_info->ignore_fsid_mismatch)) {
|
fs_info->ignore_fsid_mismatch)) {
|
||||||
device = find_device(cur_devices, devid, uuid);
|
device = find_device(cur_devices, devid, uuid);
|
||||||
if (device)
|
if (device)
|
||||||
@ -1980,7 +2000,7 @@ static int open_seed_devices(struct btrfs_fs_info *fs_info, u8 *fsid)
|
|||||||
fs_devices = fs_devices->seed;
|
fs_devices = fs_devices->seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_devices = find_fsid(fsid);
|
fs_devices = find_fsid(fsid, NULL);
|
||||||
if (!fs_devices) {
|
if (!fs_devices) {
|
||||||
/* missing all seed devices */
|
/* missing all seed devices */
|
||||||
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
|
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
|
||||||
@ -2019,7 +2039,7 @@ static int read_one_dev(struct btrfs_fs_info *fs_info,
|
|||||||
BTRFS_UUID_SIZE);
|
BTRFS_UUID_SIZE);
|
||||||
read_extent_buffer(leaf, fs_uuid,
|
read_extent_buffer(leaf, fs_uuid,
|
||||||
(unsigned long)btrfs_device_fsid(dev_item),
|
(unsigned long)btrfs_device_fsid(dev_item),
|
||||||
BTRFS_UUID_SIZE);
|
BTRFS_FSID_SIZE);
|
||||||
|
|
||||||
if (memcmp(fs_uuid, fs_info->fsid, BTRFS_UUID_SIZE)) {
|
if (memcmp(fs_uuid, fs_info->fsid, BTRFS_UUID_SIZE)) {
|
||||||
ret = open_seed_devices(fs_info, fs_uuid);
|
ret = open_seed_devices(fs_info, fs_uuid);
|
||||||
|
@ -71,6 +71,7 @@ struct btrfs_device {
|
|||||||
|
|
||||||
struct btrfs_fs_devices {
|
struct btrfs_fs_devices {
|
||||||
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
|
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
|
||||||
|
u8 metadata_uuid[BTRFS_FSID_SIZE]; /* FS specific uuid */
|
||||||
|
|
||||||
/* the device with this id has the most recent copy of the super */
|
/* the device with this id has the most recent copy of the super */
|
||||||
u64 latest_devid;
|
u64 latest_devid;
|
||||||
|
Loading…
Reference in New Issue
Block a user