summaryrefslogtreecommitdiff
path: root/drivers/s390/block/dasd_eckd.c
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.ibm.com>2022-09-20 22:26:12 +0300
committerJens Axboe <axboe@kernel.dk>2022-09-21 17:32:51 +0300
commita91ff09d39f9b6545254839ac91f1ff7bd21d39e (patch)
treeb0f577b0a730150c2870c0e21f09e70d55cc9d99 /drivers/s390/block/dasd_eckd.c
parent3f217cceb6846e7533511fc69bc774cdba37ff7d (diff)
downloadlinux-a91ff09d39f9b6545254839ac91f1ff7bd21d39e.tar.xz
s390/dasd: add copy pair setup
A copy relation that is configured on the storage server side needs to be enabled separately in the device driver. A sysfs interface is created that allows userspace tooling to control such setup. The following sysfs entries are added to store and read copy relation information: copy_pair - Add/Delete a copy pair relation to the DASD device driver - Query all previously added copy pair relations copy_role - Query the copy pair role of the device To add a copy pair to the DASD device driver it has to be specified through the sysfs attribute copy_pair. Only one secondary device can be specified at a time together with the primary device. Both, secondary and primary can be used equally to define the copy pair. The secondary devices have to be offline when adding the copy relation. The primary device needs to be specified first followed by the comma separated secondary device. Read from the copy_pair attribute to get the current setup and write "clear" to the attribute to delete any existing setup. Example: $ echo 0.0.9700,0.0.9740 > /sys/bus/ccw/devices/0.0.9700/copy_pair $ cat /sys/bus/ccw/devices/0.0.9700/copy_pair 0.0.9700,0.0.9740 During device online processing the required data will be read from the storage server and the information will be compared to the setup requested through the copy_pair attribute. The registration of the primary and secondary device will be handled accordingly. A blockdevice is only allocated for copy relation primary devices. To query the copy role of a device read from the copy_role sysfs attribute. Possible values are primary, secondary, and none. Example: $ cat /sys/bus/ccw/devices/0.0.9700/copy_role primary 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-4-sth@linux.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r--drivers/s390/block/dasd_eckd.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 600606d8d038..c8a226f070fa 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2012,11 +2012,28 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device)
dasd_put_device(device);
}
+/*
+ * return if the device is the copy relation primary if a copy relation is active
+ */
+static int dasd_device_is_primary(struct dasd_device *device)
+{
+ if (!device->copy)
+ return 1;
+
+ if (device->copy->active->device == device)
+ return 1;
+
+ return 0;
+}
+
static int dasd_eckd_alloc_block(struct dasd_device *device)
{
struct dasd_block *block;
struct dasd_uid temp_uid;
+ if (!dasd_device_is_primary(device))
+ return 0;
+
dasd_eckd_get_uid(device, &temp_uid);
if (temp_uid.type == UA_BASE_DEVICE) {
block = dasd_alloc_block();
@@ -2031,6 +2048,13 @@ static int dasd_eckd_alloc_block(struct dasd_device *device)
return 0;
}
+static bool dasd_eckd_pprc_enabled(struct dasd_device *device)
+{
+ struct dasd_eckd_private *private = device->private;
+
+ return private->rdc_data.facilities.PPRC_enabled;
+}
+
/*
* Check device characteristics.
* If the device is accessible using ECKD discipline, the device is enabled.
@@ -2096,6 +2120,24 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
device->default_expires = value;
}
+ /* Read Device Characteristics */
+ rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
+ &private->rdc_data, 64);
+ if (rc) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+ "Read device characteristic failed, rc=%d", rc);
+ goto out_err1;
+ }
+
+ /* setup PPRC for device from devmap */
+ rc = dasd_devmap_set_device_copy_relation(device->cdev,
+ dasd_eckd_pprc_enabled(device));
+ if (rc) {
+ DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+ "copy relation setup failed, rc=%d", rc);
+ goto out_err1;
+ }
+
/* check if block device is needed and allocate in case */
rc = dasd_eckd_alloc_block(device);
if (rc)
@@ -2125,15 +2167,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Extent Pool Information */
dasd_eckd_read_ext_pool_info(device);
- /* Read Device Characteristics */
- rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
- &private->rdc_data, 64);
- if (rc) {
- DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
- "Read device characteristic failed, rc=%d", rc);
- goto out_err3;
- }
-
if ((device->features & DASD_FEATURE_USERAW) &&
!(private->rdc_data.facilities.RT_in_LR)) {
dev_err(&device->cdev->dev, "The storage server does not "
@@ -6771,6 +6804,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.ese_format = dasd_eckd_ese_format,
.ese_read = dasd_eckd_ese_read,
.pprc_status = dasd_eckd_query_pprc_status,
+ .pprc_enabled = dasd_eckd_pprc_enabled,
};
static int __init