Commit a91ff09d authored by Stefan Haberland's avatar Stefan Haberland Committed by Jens Axboe

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: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarJan Hoeppner <hoeppner@linux.ibm.com>
Link: https://lore.kernel.org/r/20220920192616.808070-4-sth@linux.ibm.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 3f217cce
This diff is collapsed.
...@@ -2012,11 +2012,28 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device) ...@@ -2012,11 +2012,28 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device)
dasd_put_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) static int dasd_eckd_alloc_block(struct dasd_device *device)
{ {
struct dasd_block *block; struct dasd_block *block;
struct dasd_uid temp_uid; struct dasd_uid temp_uid;
if (!dasd_device_is_primary(device))
return 0;
dasd_eckd_get_uid(device, &temp_uid); dasd_eckd_get_uid(device, &temp_uid);
if (temp_uid.type == UA_BASE_DEVICE) { if (temp_uid.type == UA_BASE_DEVICE) {
block = dasd_alloc_block(); block = dasd_alloc_block();
...@@ -2031,6 +2048,13 @@ static int dasd_eckd_alloc_block(struct dasd_device *device) ...@@ -2031,6 +2048,13 @@ static int dasd_eckd_alloc_block(struct dasd_device *device)
return 0; 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. * Check device characteristics.
* If the device is accessible using ECKD discipline, the device is enabled. * If the device is accessible using ECKD discipline, the device is enabled.
...@@ -2096,6 +2120,24 @@ dasd_eckd_check_characteristics(struct dasd_device *device) ...@@ -2096,6 +2120,24 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
device->default_expires = value; 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 */ /* check if block device is needed and allocate in case */
rc = dasd_eckd_alloc_block(device); rc = dasd_eckd_alloc_block(device);
if (rc) if (rc)
...@@ -2125,15 +2167,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) ...@@ -2125,15 +2167,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Extent Pool Information */ /* Read Extent Pool Information */
dasd_eckd_read_ext_pool_info(device); 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) && if ((device->features & DASD_FEATURE_USERAW) &&
!(private->rdc_data.facilities.RT_in_LR)) { !(private->rdc_data.facilities.RT_in_LR)) {
dev_err(&device->cdev->dev, "The storage server does not " dev_err(&device->cdev->dev, "The storage server does not "
...@@ -6771,6 +6804,7 @@ static struct dasd_discipline dasd_eckd_discipline = { ...@@ -6771,6 +6804,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.ese_format = dasd_eckd_ese_format, .ese_format = dasd_eckd_ese_format,
.ese_read = dasd_eckd_ese_read, .ese_read = dasd_eckd_ese_read,
.pprc_status = dasd_eckd_query_pprc_status, .pprc_status = dasd_eckd_query_pprc_status,
.pprc_enabled = dasd_eckd_pprc_enabled,
}; };
static int __init static int __init
......
...@@ -267,7 +267,7 @@ struct dasd_eckd_characteristics { ...@@ -267,7 +267,7 @@ struct dasd_eckd_characteristics {
unsigned char reserved3:8; unsigned char reserved3:8;
unsigned char defect_wr:1; unsigned char defect_wr:1;
unsigned char XRC_supported:1; unsigned char XRC_supported:1;
unsigned char reserved4:1; unsigned char PPRC_enabled:1;
unsigned char striping:1; unsigned char striping:1;
unsigned char reserved5:4; unsigned char reserved5:4;
unsigned char cfw:1; unsigned char cfw:1;
......
...@@ -290,6 +290,24 @@ struct dasd_pprc_data_sc4 { ...@@ -290,6 +290,24 @@ struct dasd_pprc_data_sc4 {
struct dasd_pprc_dev_info dev_info[5]; struct dasd_pprc_dev_info dev_info[5];
} __packed; } __packed;
#define DASD_BUS_ID_SIZE 20
#define DASD_CP_ENTRIES 5
struct dasd_copy_entry {
char busid[DASD_BUS_ID_SIZE];
struct dasd_device *device;
bool primary;
bool configured;
};
struct dasd_copy_relation {
struct dasd_copy_entry entry[DASD_CP_ENTRIES];
struct dasd_copy_entry *active;
};
int dasd_devmap_set_device_copy_relation(struct ccw_device *,
bool pprc_enabled);
/* /*
* the struct dasd_discipline is * the struct dasd_discipline is
* sth like a table of virtual functions, if you think of dasd_eckd * sth like a table of virtual functions, if you think of dasd_eckd
...@@ -419,6 +437,7 @@ struct dasd_discipline { ...@@ -419,6 +437,7 @@ struct dasd_discipline {
struct dasd_ccw_req *, struct irb *); struct dasd_ccw_req *, struct irb *);
int (*ese_read)(struct dasd_ccw_req *, struct irb *); int (*ese_read)(struct dasd_ccw_req *, struct irb *);
int (*pprc_status)(struct dasd_device *, struct dasd_pprc_data_sc4 *); int (*pprc_status)(struct dasd_device *, struct dasd_pprc_data_sc4 *);
bool (*pprc_enabled)(struct dasd_device *);
}; };
extern struct dasd_discipline *dasd_diag_discipline_pointer; extern struct dasd_discipline *dasd_diag_discipline_pointer;
...@@ -615,6 +634,7 @@ struct dasd_device { ...@@ -615,6 +634,7 @@ struct dasd_device {
struct dasd_profile profile; struct dasd_profile profile;
struct dasd_format_entry format_entry; struct dasd_format_entry format_entry;
struct kset *paths_info; struct kset *paths_info;
struct dasd_copy_relation *copy;
}; };
struct dasd_block { struct dasd_block {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment