diff options
author | Stefan Haberland <sth@linux.ibm.com> | 2022-09-20 22:26:12 +0300 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2022-09-21 17:32:51 +0300 |
commit | a91ff09d39f9b6545254839ac91f1ff7bd21d39e (patch) | |
tree | b0f577b0a730150c2870c0e21f09e70d55cc9d99 /drivers/s390/block/dasd_eckd.c | |
parent | 3f217cceb6846e7533511fc69bc774cdba37ff7d (diff) | |
download | linux-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.c | 52 |
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 |