lkml.org 
[lkml]   [2020]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.9 233/391] btrfs: skip devices without magic signature when mounting
    Date
    From: Anand Jain <anand.jain@oracle.com>

    commit 96c2e067ed3e3e004580a643c76f58729206b829 upstream.

    Many things can happen after the device is scanned and before the device
    is mounted. One such thing is losing the BTRFS_MAGIC on the device.
    If it happens we still won't free that device from the memory and cause
    the userland confusion.

    For example: As the BTRFS_IOC_DEV_INFO still carries the device path
    which does not have the BTRFS_MAGIC, 'btrfs fi show' still lists
    device which does not belong to the filesystem anymore:

    $ mkfs.btrfs -fq -draid1 -mraid1 /dev/sda /dev/sdb
    $ wipefs -a /dev/sdb
    # /dev/sdb does not contain magic signature
    $ mount -o degraded /dev/sda /btrfs
    $ btrfs fi show -m
    Label: none uuid: 470ec6fb-646b-4464-b3cb-df1b26c527bd
    Total devices 2 FS bytes used 128.00KiB
    devid 1 size 3.00GiB used 571.19MiB path /dev/sda
    devid 2 size 3.00GiB used 571.19MiB path /dev/sdb

    We need to distinguish the missing signature and invalid superblock, so
    add a specific error code ENODATA for that. This also fixes failure of
    fstest btrfs/198.

    CC: stable@vger.kernel.org # 4.19+
    Reviewed-by: Josef Bacik <josef@toxicpanda.com>
    Signed-off-by: Anand Jain <anand.jain@oracle.com>
    Reviewed-by: David Sterba <dsterba@suse.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/btrfs/disk-io.c | 8 ++++++--
    fs/btrfs/volumes.c | 18 ++++++++++++------
    2 files changed, 18 insertions(+), 8 deletions(-)

    --- a/fs/btrfs/disk-io.c
    +++ b/fs/btrfs/disk-io.c
    @@ -3482,8 +3482,12 @@ struct btrfs_super_block *btrfs_read_dev
    return ERR_CAST(page);

    super = page_address(page);
    - if (btrfs_super_bytenr(super) != bytenr ||
    - btrfs_super_magic(super) != BTRFS_MAGIC) {
    + if (btrfs_super_magic(super) != BTRFS_MAGIC) {
    + btrfs_release_disk_super(super);
    + return ERR_PTR(-ENODATA);
    + }
    +
    + if (btrfs_super_bytenr(super) != bytenr) {
    btrfs_release_disk_super(super);
    return ERR_PTR(-EINVAL);
    }
    --- a/fs/btrfs/volumes.c
    +++ b/fs/btrfs/volumes.c
    @@ -1200,17 +1200,23 @@ static int open_fs_devices(struct btrfs_
    {
    struct btrfs_device *device;
    struct btrfs_device *latest_dev = NULL;
    + struct btrfs_device *tmp_device;

    flags |= FMODE_EXCL;

    - list_for_each_entry(device, &fs_devices->devices, dev_list) {
    - /* Just open everything we can; ignore failures here */
    - if (btrfs_open_one_device(fs_devices, device, flags, holder))
    - continue;
    + list_for_each_entry_safe(device, tmp_device, &fs_devices->devices,
    + dev_list) {
    + int ret;

    - if (!latest_dev ||
    - device->generation > latest_dev->generation)
    + ret = btrfs_open_one_device(fs_devices, device, flags, holder);
    + if (ret == 0 &&
    + (!latest_dev || device->generation > latest_dev->generation)) {
    latest_dev = device;
    + } else if (ret == -ENODATA) {
    + fs_devices->num_devices--;
    + list_del(&device->dev_list);
    + btrfs_free_device(device);
    + }
    }
    if (fs_devices->open_devices == 0)
    return -EINVAL;

    \
     
     \ /
      Last update: 2020-11-03 21:47    [W:4.066 / U:0.784 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site