s390/dasd: fix invalid PAV assignment after suspend/resume
authorStefan Haberland <stefan.haberland@de.ibm.com>
Thu, 15 Oct 2015 11:54:39 +0000 (13:54 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 3 Nov 2015 13:40:46 +0000 (14:40 +0100)
For a valid PAV assignment the DASD driver needs to notice possibly
changed configuration data. Thus the failing of read configuration
data should also fail the device restore to prevent invalid PAV
assignment. The failed device may get restored after additional paths
get available later on.
If the restore fails after the device was added to the lcu alias
handling it needs to be removed from the alias handling before exiting
the restore function.

Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/dasd_eckd.c

index e53b895a4d0f86ace95c4c20185e65fe0ff42aed..3d929abb52c759cb8a3fa7d4001119bf7d513eb4 100644 (file)
@@ -4435,7 +4435,12 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        private = (struct dasd_eckd_private *) device->private;
 
        /* Read Configuration Data */
-       dasd_eckd_read_conf(device);
+       rc = dasd_eckd_read_conf(device);
+       if (rc) {
+               DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+                               "Read configuration data failed, rc=%d", rc);
+               goto out_err;
+       }
 
        dasd_eckd_get_uid(device, &temp_uid);
        /* Generate device unique id */
@@ -4451,13 +4456,18 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        /* register lcu with alias handling, enable PAV if this is a new lcu */
        rc = dasd_alias_make_device_known_to_lcu(device);
        if (rc)
-               return rc;
+               goto out_err;
 
        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr_flags);
        dasd_eckd_validate_server(device, cqr_flags);
 
        /* RE-Read Configuration Data */
-       dasd_eckd_read_conf(device);
+       rc = dasd_eckd_read_conf(device);
+       if (rc) {
+               DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+                       "Read configuration data failed, rc=%d", rc);
+               goto out_err2;
+       }
 
        /* Read Feature Codes */
        dasd_eckd_read_features(device);
@@ -4468,7 +4478,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        if (rc) {
                DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
                                "Read device characteristic failed, rc=%d", rc);
-               goto out_err;
+               goto out_err2;
        }
        spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data));
@@ -4479,6 +4489,8 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
 
        return 0;
 
+out_err2:
+       dasd_alias_disconnect_device_from_lcu(device);
 out_err:
        return -1;
 }