summaryrefslogtreecommitdiff
path: root/drivers/s390/block
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.ibm.com>2022-09-20 22:26:14 +0300
committerJens Axboe <axboe@kernel.dk>2022-09-21 17:32:51 +0300
commit112ff512fc654d7066936dcc06f77cc60471fdb4 (patch)
tree90c5b2025828765325a0d0562366242e6ead5ed6 /drivers/s390/block
parent413862caad6fe7fddec639219bccfdab60333551 (diff)
downloadlinux-112ff512fc654d7066936dcc06f77cc60471fdb4.tar.xz
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.c53
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;