[S390] dasd: add device attribute to disable blocking on lost paths
authorHolger Smolinski <Holger.Smolinski@de.ibm.com>
Fri, 9 Jan 2009 11:14:51 +0000 (12:14 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 9 Jan 2009 11:15:05 +0000 (12:15 +0100)
When the connection between host and storage server is lost, the
dasd device driver usually blocks all I/O on affected devices and
waits for them to reappear. In some setups however it would be
better if the I/O is returned as error so that device can be
recovered by some other means, eg. in a raid or multipath setup.

Signed-off-by: Holger Smolinski <Holger.Smolinski@de.ibm.com>
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/dasd.h
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c

index 55b2b80cdf6e0926da9663a52292fafb0ca27762..fb50a7864dd5f64344c2b519cd76cf607e3cae50 100644 (file)
@@ -78,6 +78,7 @@ typedef struct dasd_information2_t {
 #define DASD_FEATURE_USEDIAG        0x02
 #define DASD_FEATURE_INITIAL_ONLINE  0x04
 #define DASD_FEATURE_ERPLOG         0x08
+#define DASD_FEATURE_FAILFAST       0x10
 
 #define DASD_PARTN_BITS 2
 
index 2ef25731d197ed0f6a9ce2fdfdc1fc4358b9e460..300e28a531f80c938f880b68c246f921686c63bb 100644 (file)
@@ -206,6 +206,8 @@ dasd_feature_list(char *str, char **endp)
                        features |= DASD_FEATURE_USEDIAG;
                else if (len == 6 && !strncmp(str, "erplog", 6))
                        features |= DASD_FEATURE_ERPLOG;
+               else if (len == 8 && !strncmp(str, "failfast", 8))
+                       features |= DASD_FEATURE_FAILFAST;
                else {
                        MESSAGE(KERN_WARNING,
                                "unsupported feature: %*s, "
@@ -666,6 +668,51 @@ dasd_device_from_cdev(struct ccw_device *cdev)
  * SECTION: files in sysfs
  */
 
+/*
+ * failfast controls the behaviour, if no path is available
+ */
+static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct dasd_devmap *devmap;
+       int ff_flag;
+
+       devmap = dasd_find_busid(dev->bus_id);
+       if (!IS_ERR(devmap))
+               ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
+       else
+               ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
+       return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
+}
+
+static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
+             const char *buf, size_t count)
+{
+       struct dasd_devmap *devmap;
+       int val;
+       char *endp;
+
+       devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+       if (IS_ERR(devmap))
+               return PTR_ERR(devmap);
+
+       val = simple_strtoul(buf, &endp, 0);
+       if (((endp + 1) < (buf + count)) || (val > 1))
+               return -EINVAL;
+
+       spin_lock(&dasd_devmap_lock);
+       if (val)
+               devmap->features |= DASD_FEATURE_FAILFAST;
+       else
+               devmap->features &= ~DASD_FEATURE_FAILFAST;
+       if (devmap->device)
+               devmap->device->features = devmap->features;
+       spin_unlock(&dasd_devmap_lock);
+       return count;
+}
+
+static DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store);
+
 /*
  * readonly controls the readonly status of a dasd
  */
@@ -1020,6 +1067,7 @@ static struct attribute * dasd_attrs[] = {
        &dev_attr_use_diag.attr,
        &dev_attr_eer_enabled.attr,
        &dev_attr_erplog.attr,
+       &dev_attr_failfast.attr,
        NULL,
 };
 
index 7844461a995b7caf0b0b27ee32dfaf53f2d6cf69..ef2a5695205442a05c4ff817444066076df5d6e7 100644 (file)
@@ -544,7 +544,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
        }
        cqr->retries = DIAG_MAX_RETRIES;
        cqr->buildclk = get_clock();
-       if (blk_noretry_request(req))
+       if (blk_noretry_request(req) ||
+           block->base->features & DASD_FEATURE_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = memdev;
        cqr->memdev = memdev;
index bd2c52e20762e3593cb531be9b77552db0a2089a..bdb87998f364f276067470e672a0db49bfc21e26 100644 (file)
@@ -1700,7 +1700,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
                        recid++;
                }
        }
-       if (blk_noretry_request(req))
+       if (blk_noretry_request(req) ||
+           block->base->features & DASD_FEATURE_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = startdev;
        cqr->memdev = startdev;
index 7d442aeff3d1163c6f6b728cdd0b9d2a1f2017e5..f1d176021694886fc1b6c2ba1f30ee6318c322c8 100644 (file)
@@ -355,7 +355,8 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
                        recid++;
                }
        }
-       if (blk_noretry_request(req))
+       if (blk_noretry_request(req) ||
+           block->base->features & DASD_FEATURE_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->startdev = memdev;
        cqr->memdev = memdev;