Message ID | e85f357bfbcef98bba37e2f39e884a371fc25b56.1695826320.git.anand.jain@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: support cloned-device mount capability | expand |
On Thu, Sep 28, 2023 at 09:09:47AM +0800, Anand Jain wrote: > Guilherme's previous work [1] aimed at the mounting of cloned devices > using a superblock flag SINGLE_DEV during mkfs. > [1] https://lore.kernel.org/linux-btrfs/20230831001544.3379273-1-gpiccoli@igalia.com/ > > Building upon this work, here is in memory only approach. As it mounts > we determine if the same fsid is already mounted if then we generate a > random temp fsid which shall be used the mount, in memory only not > written to the disk. We distinguish devices by devt. > > Example: > $ fallocate -l 300m ./disk1.img :0 > $ mkfs.btrfs -f ./disk1.img :0 > $ cp ./disk1.img ./disk2.img :0 > $ cp ./disk1.img ./disk3.img :0 > $ mount -o loop ./disk1.img /btrfs :0 > $ mount -o ./disk2.img /btrfs1 :0 > $ mount -o ./disk3.img /btrfs2 :0 I'm confused what the ":0" are supposed to mean, is it some artifact of your editor? > > $ btrfs fi show -m :0 > Label: none uuid: 4a212b48-1bec-46a5-938a-783c8c1f0b02 > Total devices 1 FS bytes used 144.00KiB > devid 1 size 300.00MiB used 88.00MiB path /dev/loop0 > > Label: none uuid: adabf2fe-5515-4ad0-95b4-7b1609218c16 > Total devices 1 FS bytes used 144.00KiB > devid 1 size 300.00MiB used 88.00MiB path /dev/loop1 > > Label: none uuid: 1d77d0df-7d92-439e-adbd-20b9b86fdedb > Total devices 1 FS bytes used 144.00KiB > devid 1 size 300.00MiB used 88.00MiB path /dev/loop2 > > Co-developed-by: Guilherme G. Piccoli <gpiccoli@igalia.com> > Signed-off-by: Anand Jain <anand.jain@oracle.com>
On 02/10/2023 20:57, David Sterba wrote: > On Thu, Sep 28, 2023 at 09:09:47AM +0800, Anand Jain wrote: >> Guilherme's previous work [1] aimed at the mounting of cloned devices >> using a superblock flag SINGLE_DEV during mkfs. >> [1] https://lore.kernel.org/linux-btrfs/20230831001544.3379273-1-gpiccoli@igalia.com/ The link should go at SOB with prefix Link:. >> >> Building upon this work, here is in memory only approach. As it mounts >> we determine if the same fsid is already mounted if then we generate a >> random temp fsid which shall be used the mount, in memory only not >> written to the disk. We distinguish devices by devt. >> >> Example: >> $ fallocate -l 300m ./disk1.img :0 >> $ mkfs.btrfs -f ./disk1.img :0 >> $ cp ./disk1.img ./disk2.img :0 >> $ cp ./disk1.img ./disk3.img :0 >> $ mount -o loop ./disk1.img /btrfs :0 >> $ mount -o ./disk2.img /btrfs1 :0 >> $ mount -o ./disk3.img /btrfs2 :0 > > I'm confused what the ":0" are supposed to mean, is it some artifact of > your editor? Oh, sorry for the confusion. It is the return status of the command. I have some local scripts to collect the output. Could you pls remove ":0", or I'll if there is a reroll. Thanks, Anand > >> >> $ btrfs fi show -m :0 >> Label: none uuid: 4a212b48-1bec-46a5-938a-783c8c1f0b02 >> Total devices 1 FS bytes used 144.00KiB >> devid 1 size 300.00MiB used 88.00MiB path /dev/loop0 >> >> Label: none uuid: adabf2fe-5515-4ad0-95b4-7b1609218c16 >> Total devices 1 FS bytes used 144.00KiB >> devid 1 size 300.00MiB used 88.00MiB path /dev/loop1 >> >> Label: none uuid: 1d77d0df-7d92-439e-adbd-20b9b86fdedb >> Total devices 1 FS bytes used 144.00KiB >> devid 1 size 300.00MiB used 88.00MiB path /dev/loop2 >> >> Co-developed-by: Guilherme G. Piccoli <gpiccoli@igalia.com> >> Signed-off-by: Anand Jain <anand.jain@oracle.com>
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a970da7263b3..04f57d8368c8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2399,7 +2399,8 @@ int btrfs_validate_super(struct btrfs_fs_info *fs_info, ret = -EINVAL; } - if (memcmp(fs_info->fs_devices->fsid, sb->fsid, BTRFS_FSID_SIZE) != 0) { + if (!fs_info->fs_devices->temp_fsid && + memcmp(fs_info->fs_devices->fsid, sb->fsid, BTRFS_FSID_SIZE) != 0) { btrfs_err(fs_info, "superblock fsid doesn't match fsid of fs_devices: %pU != %pU", sb->fsid, fs_info->fs_devices->fsid); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 39b5bc2521fb..ea4a110d7753 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -554,17 +554,64 @@ static int btrfs_free_stale_devices(dev_t devt, struct btrfs_device *skip_device } static struct btrfs_fs_devices *find_fsid_by_disk( - struct btrfs_super_block *disk_super) + struct btrfs_super_block *disk_super, + dev_t devt, bool *same_fsid_diff_dev) { struct btrfs_fs_devices *fsid_fs_devices; + struct btrfs_fs_devices *devt_fs_devices; bool has_metadata_uuid = (btrfs_super_incompat_flags(disk_super) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID); + bool found_by_devt = false; /* Find the fs_device by the usual method if found use it */ fsid_fs_devices = find_fsid(disk_super->fsid, has_metadata_uuid ? disk_super->metadata_uuid : NULL); - return fsid_fs_devices; + /* The temp_fsid feature is supported only with single device btrfs */ + if (btrfs_super_num_devices(disk_super) != 1) + return fsid_fs_devices; + + /* Try to find a fs_devices by matching devt */ + list_for_each_entry(devt_fs_devices, &fs_uuids, fs_list) { + struct btrfs_device *device; + + list_for_each_entry(device, &devt_fs_devices->devices, + dev_list) { + if (device->devt == devt) { + found_by_devt = true; + break; + } + } + if (found_by_devt) + break; + } + + if (found_by_devt) { + /* existing device */ + if (fsid_fs_devices == NULL) { + if (devt_fs_devices->opened == 0) { + /* stale device */ + return NULL; + } else { + /* temp_fsid is mounting a subvol */ + return devt_fs_devices; + } + } else { + /* regular or temp_fsid device mounting a subvol */ + return devt_fs_devices; + } + } else { + /* new device */ + if (fsid_fs_devices == NULL) { + return NULL; + } else { + /* sb::fsid is already used create a new temp_fsid */ + *same_fsid_diff_dev = true; + return NULL; + } + } + + /* Not reached */ } /* @@ -670,6 +717,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, u64 devid = btrfs_stack_device_id(&disk_super->dev_item); dev_t path_devt; int error; + bool same_fsid_diff_dev = false; bool has_metadata_uuid = (btrfs_super_incompat_flags(disk_super) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID); @@ -687,7 +735,8 @@ static noinline struct btrfs_device *device_list_add(const char *path, return ERR_PTR(error); } - fs_devices = find_fsid_by_disk(disk_super); + fs_devices = find_fsid_by_disk(disk_super, path_devt, + &same_fsid_diff_dev); if (!fs_devices) { fs_devices = alloc_fs_devices(disk_super->fsid); @@ -698,6 +747,13 @@ static noinline struct btrfs_device *device_list_add(const char *path, if (IS_ERR(fs_devices)) return ERR_CAST(fs_devices); + if (same_fsid_diff_dev) { + generate_random_uuid(fs_devices->fsid); + fs_devices->temp_fsid = true; + pr_info("BTRFS: device %s using temp fsid %pU\n", + path, fs_devices->fsid); + } + mutex_lock(&fs_devices->device_list_mutex); list_add(&fs_devices->fs_list, &fs_uuids); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index e485e6a3e52c..5921fdd3dd90 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -364,6 +364,8 @@ struct btrfs_fs_devices { bool discardable; /* The filesystem is a seed filesystem. */ bool seeding; + /* The mount need to use a randomly generated fsid. */ + bool temp_fsid; struct btrfs_fs_info *fs_info; /* sysfs kobjects */
Guilherme's previous work [1] aimed at the mounting of cloned devices using a superblock flag SINGLE_DEV during mkfs. [1] https://lore.kernel.org/linux-btrfs/20230831001544.3379273-1-gpiccoli@igalia.com/ Building upon this work, here is in memory only approach. As it mounts we determine if the same fsid is already mounted if then we generate a random temp fsid which shall be used the mount, in memory only not written to the disk. We distinguish devices by devt. Example: $ fallocate -l 300m ./disk1.img :0 $ mkfs.btrfs -f ./disk1.img :0 $ cp ./disk1.img ./disk2.img :0 $ cp ./disk1.img ./disk3.img :0 $ mount -o loop ./disk1.img /btrfs :0 $ mount -o ./disk2.img /btrfs1 :0 $ mount -o ./disk3.img /btrfs2 :0 $ btrfs fi show -m :0 Label: none uuid: 4a212b48-1bec-46a5-938a-783c8c1f0b02 Total devices 1 FS bytes used 144.00KiB devid 1 size 300.00MiB used 88.00MiB path /dev/loop0 Label: none uuid: adabf2fe-5515-4ad0-95b4-7b1609218c16 Total devices 1 FS bytes used 144.00KiB devid 1 size 300.00MiB used 88.00MiB path /dev/loop1 Label: none uuid: 1d77d0df-7d92-439e-adbd-20b9b86fdedb Total devices 1 FS bytes used 144.00KiB devid 1 size 300.00MiB used 88.00MiB path /dev/loop2 Co-developed-by: Guilherme G. Piccoli <gpiccoli@igalia.com> Signed-off-by: Anand Jain <anand.jain@oracle.com> --- fs/btrfs/disk-io.c | 3 ++- fs/btrfs/volumes.c | 62 +++++++++++++++++++++++++++++++++++++++++++--- fs/btrfs/volumes.h | 2 ++ 3 files changed, 63 insertions(+), 4 deletions(-)