s390/dasd: configurable IFCC handling
Make the behavior in case of constant IFCC/CCC errors configurable. Add a sysfs attribute to switch between path disabled after threshold exceeded (default) and message only. Reviewed-by: Jan Hoeppner <hoeppner@linux.vnet.ibm.com> Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
66aec64721
Коммит
ddc1c94535
|
@ -68,25 +68,27 @@ typedef struct dasd_information2_t {
|
|||
#define DASD_FORMAT_CDL 2
|
||||
/*
|
||||
* values to be used for dasd_information_t.features
|
||||
* 0x00: default features
|
||||
* 0x01: readonly (ro)
|
||||
* 0x02: use diag discipline (diag)
|
||||
* 0x04: set the device initially online (internal use only)
|
||||
* 0x08: enable ERP related logging
|
||||
* 0x10: allow I/O to fail on lost paths
|
||||
* 0x20: allow I/O to fail when a lock was stolen
|
||||
* 0x40: give access to raw eckd data
|
||||
* 0x80: enable discard support
|
||||
* 0x100: default features
|
||||
* 0x001: readonly (ro)
|
||||
* 0x002: use diag discipline (diag)
|
||||
* 0x004: set the device initially online (internal use only)
|
||||
* 0x008: enable ERP related logging
|
||||
* 0x010: allow I/O to fail on lost paths
|
||||
* 0x020: allow I/O to fail when a lock was stolen
|
||||
* 0x040: give access to raw eckd data
|
||||
* 0x080: enable discard support
|
||||
* 0x100: enable autodisable for IFCC errors (default)
|
||||
*/
|
||||
#define DASD_FEATURE_DEFAULT 0x00
|
||||
#define DASD_FEATURE_READONLY 0x01
|
||||
#define DASD_FEATURE_USEDIAG 0x02
|
||||
#define DASD_FEATURE_INITIAL_ONLINE 0x04
|
||||
#define DASD_FEATURE_ERPLOG 0x08
|
||||
#define DASD_FEATURE_FAILFAST 0x10
|
||||
#define DASD_FEATURE_FAILONSLCK 0x20
|
||||
#define DASD_FEATURE_USERAW 0x40
|
||||
#define DASD_FEATURE_DISCARD 0x80
|
||||
#define DASD_FEATURE_READONLY 0x001
|
||||
#define DASD_FEATURE_USEDIAG 0x002
|
||||
#define DASD_FEATURE_INITIAL_ONLINE 0x004
|
||||
#define DASD_FEATURE_ERPLOG 0x008
|
||||
#define DASD_FEATURE_FAILFAST 0x010
|
||||
#define DASD_FEATURE_FAILONSLCK 0x020
|
||||
#define DASD_FEATURE_USERAW 0x040
|
||||
#define DASD_FEATURE_DISCARD 0x080
|
||||
#define DASD_FEATURE_PATH_AUTODISABLE 0x100
|
||||
#define DASD_FEATURE_DEFAULT DASD_FEATURE_PATH_AUTODISABLE
|
||||
|
||||
#define DASD_PARTN_BITS 2
|
||||
|
||||
|
|
|
@ -2214,15 +2214,28 @@ static void dasd_3990_erp_disable_path(struct dasd_device *device, __u8 lpum)
|
|||
{
|
||||
int pos = pathmask_to_pos(lpum);
|
||||
|
||||
if (!(device->features & DASD_FEATURE_PATH_AUTODISABLE)) {
|
||||
dev_err(&device->cdev->dev,
|
||||
"Path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n",
|
||||
device->path[pos].cssid, device->path[pos].chpid, lpum);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* no remaining path, cannot disable */
|
||||
if (!(dasd_path_get_opm(device) & ~lpum))
|
||||
return;
|
||||
if (!(dasd_path_get_opm(device) & ~lpum)) {
|
||||
dev_err(&device->cdev->dev,
|
||||
"Last path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n",
|
||||
device->path[pos].cssid, device->path[pos].chpid, lpum);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_err(&device->cdev->dev,
|
||||
"Path %x.%02x (pathmask %02x) is disabled - IFCC threshold exceeded\n",
|
||||
device->path[pos].cssid, device->path[pos].chpid, lpum);
|
||||
dasd_path_remove_opm(device, lpum);
|
||||
dasd_path_add_ifccpm(device, lpum);
|
||||
|
||||
out:
|
||||
device->path[pos].errorclk = 0;
|
||||
atomic_set(&device->path[pos].error_count, 0);
|
||||
}
|
||||
|
|
|
@ -1550,9 +1550,49 @@ dasd_path_threshold_store(struct device *dev, struct device_attribute *attr,
|
|||
dasd_put_device(device);
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(path_threshold, 0644, dasd_path_threshold_show,
|
||||
dasd_path_threshold_store);
|
||||
|
||||
/*
|
||||
* configure if path is disabled after IFCC/CCC error threshold is
|
||||
* exceeded
|
||||
*/
|
||||
static ssize_t
|
||||
dasd_path_autodisable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dasd_devmap *devmap;
|
||||
int flag;
|
||||
|
||||
devmap = dasd_find_busid(dev_name(dev));
|
||||
if (!IS_ERR(devmap))
|
||||
flag = (devmap->features & DASD_FEATURE_PATH_AUTODISABLE) != 0;
|
||||
else
|
||||
flag = (DASD_FEATURE_DEFAULT &
|
||||
DASD_FEATURE_PATH_AUTODISABLE) != 0;
|
||||
return snprintf(buf, PAGE_SIZE, flag ? "1\n" : "0\n");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dasd_path_autodisable_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned int val;
|
||||
int rc;
|
||||
|
||||
if (kstrtouint(buf, 0, &val) || val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
rc = dasd_set_feature(to_ccwdev(dev),
|
||||
DASD_FEATURE_PATH_AUTODISABLE, val);
|
||||
|
||||
return rc ? : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(path_autodisable, 0644,
|
||||
dasd_path_autodisable_show,
|
||||
dasd_path_autodisable_store);
|
||||
/*
|
||||
* interval for IFCC/CCC checks
|
||||
* meaning time with no IFCC/CCC error before the error counter
|
||||
|
@ -1623,6 +1663,7 @@ static struct attribute * dasd_attrs[] = {
|
|||
&dev_attr_host_access_count.attr,
|
||||
&dev_attr_path_masks.attr,
|
||||
&dev_attr_path_threshold.attr,
|
||||
&dev_attr_path_autodisable.attr,
|
||||
&dev_attr_path_interval.attr,
|
||||
&dev_attr_path_reset.attr,
|
||||
&dev_attr_hpf.attr,
|
||||
|
|
Загрузка…
Ссылка в новой задаче