btrfs: introduce new ioctl to unregister a btrfs device

Support for a new command that can be used eg. as a command

  $ btrfs device scan --forget [dev]'
(the final name may change though)

to undo the effects of 'btrfs device scan [dev]'. For this purpose
this patch proposes to use ioctl #5 as it was empty and is next to the
SCAN ioctl.

The new ioctl BTRFS_IOC_FORGET_DEV works only on the control device
(/dev/btrfs-control) to unregister one or all devices, devices that are
not mounted.

The argument is struct btrfs_ioctl_vol_args, ::name specifies the device
path. To unregister all device, the path is an empty string.

Again, the devices are removed only if they aren't part of a mounte
filesystem.

This new ioctl provides:

- release of unwanted btrfs_fs_devices and btrfs_devices structures
  from memory if the device is not going to be mounted

- ability to mount filesystem in degraded mode, when one devices is
  corrupted like in split brain raid1

- running test cases which would require reloading the kernel module
  but this is not possible eg. due to mounted filesystem or built-in

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Anand Jain 2019-01-04 13:31:54 +08:00 коммит произвёл David Sterba
Родитель 034f784d7c
Коммит 228a73abde
4 изменённых файлов: 17 добавлений и 0 удалений

Просмотреть файл

@ -2190,6 +2190,9 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
ret = PTR_ERR_OR_ZERO(device); ret = PTR_ERR_OR_ZERO(device);
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
break; break;
case BTRFS_IOC_FORGET_DEV:
ret = btrfs_forget_devices(vol->name);
break;
case BTRFS_IOC_DEVICES_READY: case BTRFS_IOC_DEVICES_READY:
mutex_lock(&uuid_mutex); mutex_lock(&uuid_mutex);
device = btrfs_scan_one_device(vol->name, FMODE_READ, device = btrfs_scan_one_device(vol->name, FMODE_READ,

Просмотреть файл

@ -1446,6 +1446,17 @@ static int btrfs_read_disk_super(struct block_device *bdev, u64 bytenr,
return 0; return 0;
} }
int btrfs_forget_devices(const char *path)
{
int ret;
mutex_lock(&uuid_mutex);
ret = btrfs_free_stale_devices(strlen(path) ? path : NULL, NULL);
mutex_unlock(&uuid_mutex);
return ret;
}
/* /*
* Look for a btrfs signature on a device. This may be called out of the mount path * 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 * and we are not allowed to call set_blocksize during the scan. The superblock

Просмотреть файл

@ -416,6 +416,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
fmode_t flags, void *holder); fmode_t flags, void *holder);
struct btrfs_device *btrfs_scan_one_device(const char *path, struct btrfs_device *btrfs_scan_one_device(const char *path,
fmode_t flags, void *holder); fmode_t flags, void *holder);
int btrfs_forget_devices(const char *path);
int btrfs_close_devices(struct btrfs_fs_devices *fs_devices); int btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step); void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step);
void btrfs_assign_next_active_device(struct btrfs_device *device, void btrfs_assign_next_active_device(struct btrfs_device *device,

Просмотреть файл

@ -837,6 +837,8 @@ enum btrfs_err_code {
struct btrfs_ioctl_vol_args) struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
struct btrfs_ioctl_vol_args) struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_FORGET_DEV _IOW(BTRFS_IOCTL_MAGIC, 5, \
struct btrfs_ioctl_vol_args)
/* trans start and trans end are dangerous, and only for /* trans start and trans end are dangerous, and only for
* use by applications that know how to avoid the * use by applications that know how to avoid the
* resulting deadlocks * resulting deadlocks