]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/s390/block/dasd_devmap.c
[S390] dasd: add device attribute to disable blocking on lost paths
[linux-2.6-omap-h63xx.git] / drivers / s390 / block / dasd_devmap.c
index 921443b01d163165bcf20b50e81d9baceb785f34..300e28a531f80c938f880b68c246f921686c63bb 100644 (file)
@@ -23,6 +23,7 @@
 
 /* This is ugly... */
 #define PRINTK_HEADER "dasd_devmap:"
+#define DASD_BUS_ID_SIZE 20
 
 #include "dasd_int.h"
 
@@ -41,7 +42,7 @@ EXPORT_SYMBOL_GPL(dasd_page_cache);
  */
 struct dasd_devmap {
        struct list_head list;
-       char bus_id[BUS_ID_SIZE];
+       char bus_id[DASD_BUS_ID_SIZE];
         unsigned int devindex;
         unsigned short features;
        struct dasd_device *device;
@@ -94,7 +95,7 @@ dasd_hash_busid(const char *bus_id)
        int hash, i;
 
        hash = 0;
-       for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++)
+       for (i = 0; (i < DASD_BUS_ID_SIZE) && *bus_id; i++, bus_id++)
                hash += *bus_id;
        return hash & 0xff;
 }
@@ -205,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, "
@@ -301,7 +304,7 @@ dasd_parse_range( char *parsestring ) {
        int from, from_id0, from_id1;
        int to, to_id0, to_id1;
        int features, rc;
-       char bus_id[BUS_ID_SIZE+1], *str;
+       char bus_id[DASD_BUS_ID_SIZE+1], *str;
 
        str = parsestring;
        rc = dasd_busid(&str, &from_id0, &from_id1, &from);
@@ -407,14 +410,14 @@ dasd_add_busid(const char *bus_id, int features)
        devmap = NULL;
        hash = dasd_hash_busid(bus_id);
        list_for_each_entry(tmp, &dasd_hashlists[hash], list)
-               if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
+               if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
                        devmap = tmp;
                        break;
                }
        if (!devmap) {
                /* This bus_id is new. */
                new->devindex = dasd_max_devindex++;
-               strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
+               strncpy(new->bus_id, bus_id, DASD_BUS_ID_SIZE);
                new->features = features;
                new->device = NULL;
                list_add(&new->list, &dasd_hashlists[hash]);
@@ -439,7 +442,7 @@ dasd_find_busid(const char *bus_id)
        devmap = ERR_PTR(-ENODEV);
        hash = dasd_hash_busid(bus_id);
        list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
-               if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
+               if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
                        devmap = tmp;
                        break;
                }
@@ -561,7 +564,7 @@ dasd_create_device(struct ccw_device *cdev)
        }
 
        spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
-       cdev->dev.driver_data = device;
+       dev_set_drvdata(&cdev->dev, device);
        spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
 
        return device;
@@ -597,7 +600,7 @@ dasd_delete_device(struct dasd_device *device)
 
        /* Disconnect dasd_device structure from ccw_device structure. */
        spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
-       device->cdev->dev.driver_data = NULL;
+       dev_set_drvdata(&device->cdev->dev, NULL);
        spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 
        /*
@@ -638,7 +641,7 @@ dasd_put_device_wake(struct dasd_device *device)
 struct dasd_device *
 dasd_device_from_cdev_locked(struct ccw_device *cdev)
 {
-       struct dasd_device *device = cdev->dev.driver_data;
+       struct dasd_device *device = dev_get_drvdata(&cdev->dev);
 
        if (!device)
                return ERR_PTR(-ENODEV);
@@ -665,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
  */
@@ -1019,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,
 };