summaryrefslogtreecommitdiff
path: root/volumes.c
diff options
context:
space:
mode:
Diffstat (limited to 'volumes.c')
-rw-r--r--volumes.c85
1 files changed, 59 insertions, 26 deletions
diff --git a/volumes.c b/volumes.c
index 30090ce..2c6aaf4 100644
--- a/volumes.c
+++ b/volumes.c
@@ -142,13 +142,19 @@ static struct btrfs_device *find_device(struct btrfs_fs_devices *fs_devices,
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;
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;
+ } else if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0){
+ return fs_devices;
+ }
}
return NULL;
}
@@ -160,8 +166,15 @@ static int device_list_add(const char *path,
struct btrfs_device *device;
struct btrfs_fs_devices *fs_devices;
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) {
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
if (!fs_devices)
@@ -169,6 +182,13 @@ static int device_list_add(const char *path,
INIT_LIST_HEAD(&fs_devices->devices);
list_add(&fs_devices->list, &fs_uuids);
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_trans = found_transid;
fs_devices->lowest_devid = (u64)-1;
@@ -530,10 +550,12 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
return find_free_dev_extent_start(device, num_bytes, 0, start, len);
}
-static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
- struct btrfs_device *device,
- u64 chunk_offset, u64 num_bytes, u64 *start,
- int convert)
+/*
+ * Insert one device extent into the fs.
+ */
+int btrfs_insert_dev_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_device *device,
+ u64 chunk_offset, u64 num_bytes, u64 start)
{
int ret;
struct btrfs_path *path;
@@ -546,18 +568,8 @@ static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
if (!path)
return -ENOMEM;
- /*
- * For convert case, just skip search free dev_extent, as caller
- * is responsible to make sure it's free.
- */
- if (!convert) {
- ret = find_free_dev_extent(device, num_bytes, start, NULL);
- if (ret)
- goto err;
- }
-
key.objectid = device->devid;
- key.offset = *start;
+ key.offset = start;
key.type = BTRFS_DEV_EXTENT_KEY;
ret = btrfs_insert_empty_item(trans, root, path, &key,
sizeof(*extent));
@@ -583,6 +595,22 @@ err:
return ret;
}
+/*
+ * Allocate one free dev extent and insert it into the fs.
+ */
+static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_device *device,
+ u64 chunk_offset, u64 num_bytes, u64 *start)
+{
+ int ret;
+
+ ret = find_free_dev_extent(device, num_bytes, start, NULL);
+ if (ret)
+ return ret;
+ return btrfs_insert_dev_extent(trans, device, chunk_offset, num_bytes,
+ *start);
+}
+
static int find_next_chunk(struct btrfs_fs_info *fs_info, u64 *offset)
{
struct btrfs_root *root = fs_info->chunk_root;
@@ -713,7 +741,8 @@ int btrfs_add_device(struct btrfs_trans_handle *trans,
ptr = (unsigned long)btrfs_device_uuid(dev_item);
write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
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->fs_devices->metadata_uuid, ptr,
+ BTRFS_UUID_SIZE);
btrfs_mark_buffer_dirty(leaf);
ret = 0;
@@ -1107,7 +1136,7 @@ again:
list_move_tail(&device->dev_list, dev_list);
ret = btrfs_alloc_dev_extent(trans, device, key.offset,
- calc_size, &dev_offset, 0);
+ calc_size, &dev_offset);
if (ret < 0)
goto out_chunk_map;
@@ -1241,8 +1270,12 @@ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans,
while (index < num_stripes) {
struct btrfs_stripe *stripe;
- ret = btrfs_alloc_dev_extent(trans, device, key.offset,
- calc_size, &dev_offset, convert);
+ if (convert)
+ ret = btrfs_insert_dev_extent(trans, device, key.offset,
+ calc_size, dev_offset);
+ else
+ ret = btrfs_alloc_dev_extent(trans, device, key.offset,
+ calc_size, &dev_offset);
BUG_ON(ret);
device->bytes_used += calc_size;
@@ -1686,7 +1719,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
cur_devices = fs_info->fs_devices;
while (cur_devices) {
if (!fsid ||
- (!memcmp(cur_devices->fsid, fsid, BTRFS_UUID_SIZE) ||
+ (!memcmp(cur_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE) ||
fs_info->ignore_fsid_mismatch)) {
device = find_device(cur_devices, devid, uuid);
if (device)
@@ -1968,7 +2001,7 @@ static int open_seed_devices(struct btrfs_fs_info *fs_info, u8 *fsid)
fs_devices = fs_devices->seed;
}
- fs_devices = find_fsid(fsid);
+ fs_devices = find_fsid(fsid, NULL);
if (!fs_devices) {
/* missing all seed devices */
fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
@@ -2007,9 +2040,9 @@ static int read_one_dev(struct btrfs_fs_info *fs_info,
BTRFS_UUID_SIZE);
read_extent_buffer(leaf, fs_uuid,
(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->fs_devices->fsid, BTRFS_UUID_SIZE)) {
ret = open_seed_devices(fs_info, fs_uuid);
if (ret)
return ret;