diff options
author | Stefan Haberland <sth@linux.ibm.com> | 2022-09-20 21:26:14 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2022-09-21 08:32:51 -0600 |
commit | 112ff512fc654d7066936dcc06f77cc60471fdb4 (patch) | |
tree | 90c5b2025828765325a0d0562366242e6ead5ed6 /drivers/s390/block | |
parent | 413862caad6fe7fddec639219bccfdab60333551 (diff) |
s390/dasd: add ioctl to perform a swap of the drivers copy pair
The newly defined ioctl BIODASDCOPYPAIRSWAP takes a structure that
specifies a copy pair that should be swapped. It will call the device
discipline function to perform the swap operation.
The structure looks as followed:
struct dasd_copypair_swap_data_t {
char primary[20];
char secondary[20];
__u8 reserved[64];
};
where primary is the old primary device that will be replaced by the
secondary device. The old primary will become a secondary device
afterwards.
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Link: https://lore.kernel.org/r/20220920192616.808070-6-sth@linux.ibm.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/s390/block')
-rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 95349f95758c..d0ddf2cc9786 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -379,6 +379,56 @@ out_err: return rc; } +/* + * Swap driver iternal copy relation. + */ +static int +dasd_ioctl_copy_pair_swap(struct block_device *bdev, void __user *argp) +{ + struct dasd_copypair_swap_data_t data; + struct dasd_device *device; + int rc; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + device = dasd_device_from_gendisk(bdev->bd_disk); + if (!device) + return -ENODEV; + + if (copy_from_user(&data, argp, sizeof(struct dasd_copypair_swap_data_t))) { + dasd_put_device(device); + return -EFAULT; + } + if (memchr_inv(data.reserved, 0, sizeof(data.reserved))) { + pr_warn("%s: Ivalid swap data specified.\n", + dev_name(&device->cdev->dev)); + dasd_put_device(device); + return DASD_COPYPAIRSWAP_INVALID; + } + if (bdev_is_partition(bdev)) { + pr_warn("%s: The specified DASD is a partition and cannot be swapped\n", + dev_name(&device->cdev->dev)); + dasd_put_device(device); + return DASD_COPYPAIRSWAP_INVALID; + } + if (!device->copy) { + pr_warn("%s: The specified DASD has no copy pair set up\n", + dev_name(&device->cdev->dev)); + dasd_put_device(device); + return -ENODEV; + } + if (!device->discipline->copy_pair_swap) { + dasd_put_device(device); + return -EOPNOTSUPP; + } + rc = device->discipline->copy_pair_swap(device, data.primary, + data.secondary); + dasd_put_device(device); + + return rc; +} + #ifdef CONFIG_DASD_PROFILE /* * Reset device profile information @@ -637,6 +687,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, case BIODASDRAS: rc = dasd_ioctl_release_space(bdev, argp); break; + case BIODASDCOPYPAIRSWAP: + rc = dasd_ioctl_copy_pair_swap(bdev, argp); + break; default: /* if the discipline has an ioctl method try it. */ rc = -ENOTTY; |