+
+ mutex_lock(&uuid_mutex);
+ mutex_lock(&fs_devices->device_list_mutex);
+ device = find_device(fs_devices, devid, disk_super->dev_item.uuid);
+ if (!device) {
+ ret = -ENOENT;
+ goto error;
+ }
+
+ delete_device_from_list(device);
+
+error:
+ mutex_unlock(&fs_devices->device_list_mutex);
+ mutex_unlock(&uuid_mutex);
+
+ return ret;
+}
+
+int btrfs_ignore_one_device(const char *path, fmode_t flags, void *holder,
+ struct btrfs_fs_devices **fs_devices_ret)
+{
+ struct btrfs_super_block *disk_super;
+ struct block_device *bdev;
+ struct page *page;
+ int ret = -EINVAL;
+ u64 devid;
+ u64 bytenr;
+
+ bytenr = btrfs_sb_offset(0);
+ flags |= FMODE_EXCL;
+
+ bdev = blkdev_get_by_path(path, flags, holder);
+ if (IS_ERR(bdev)) {
+ ret = PTR_ERR(bdev);
+ goto error;
+ }
+
+ if (btrfs_read_disk_super(bdev, bytenr, &page, &disk_super))
+ goto error_bdev_put;
+
+ devid = btrfs_stack_device_id(&disk_super->dev_item);
+
+ ret = device_list_remove(disk_super, devid);
+ if (ret)
+ pr_err("BTRFS: %pU: device %s uuid %pU devid %llu failed to unscan: %d",
+ disk_super->fsid, path, disk_super->dev_item.uuid, devid, ret);
+ else
+ pr_info("BTRFS: %pU: device %s uuid %pU devid %llu ran undo scan",
+ disk_super->fsid, path, disk_super->dev_item.uuid, devid);
+
+ btrfs_release_disk_super(page);
+
+error_bdev_put:
+ blkdev_put(bdev, flags);
+error:
+ return ret;
+}
+
/*
* Look for a btrfs signature on a device. This may be called out of the
mount path
* and we are not allowed to call set_blocksize during the scan. The
superblock
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 6108fdfec67f..340e40acdab5 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -421,6 +421,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
fmode_t flags, void *holder);
int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
struct btrfs_fs_devices **fs_devices_ret);
+int btrfs_ignore_one_device(const char *path, fmode_t flags, void *holder,
+ struct btrfs_fs_devices **fs_devices_ret);
int btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices, int step);
void btrfs_assign_next_active_device(struct btrfs_fs_info *fs_info,
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index 378230c163d5..928485c31aa4 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -739,6 +739,8 @@ enum btrfs_err_code {
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
struct btrfs_ioctl_vol_args)
+#define BTRFS_IOC_IGNORE_DEV _IOW(BTRFS_IOCTL_MAGIC, 5, \
+ struct btrfs_ioctl_vol_args)
/* trans start and trans end are dangerous, and only for
* use by applications that know how to avoid the
* resulting deadlocks