Skip to content

Commit

Permalink
btrfs: skip devices without magic signature when mounting
Browse files Browse the repository at this point in the history
commit 96c2e06 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>
  • Loading branch information
asj authored and gregkh committed Nov 5, 2020
1 parent fbf3b12 commit 0cb097f
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
8 changes: 6 additions & 2 deletions fs/btrfs/disk-io.c
Expand Up @@ -3482,8 +3482,12 @@ struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
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);
}
Expand Down
18 changes: 12 additions & 6 deletions fs/btrfs/volumes.c
Expand Up @@ -1200,17 +1200,23 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
{
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;
Expand Down

0 comments on commit 0cb097f

Please sign in to comment.