[S390] dasd: prevent path verification before resume
authorStefan Haberland <stefan.haberland@de.ibm.com>
Sun, 30 Oct 2011 14:17:09 +0000 (15:17 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Sun, 30 Oct 2011 14:16:45 +0000 (15:16 +0100)
Mark the device as suspended and delay execution of the path
verification worker to prevent mix-up.

Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h

index ce2a780..65894f0 100644 (file)
@@ -3289,6 +3289,9 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
        if (IS_ERR(device))
                return PTR_ERR(device);
 
+       /* mark device as suspended */
+       set_bit(DASD_FLAG_SUSPENDED, &device->flags);
+
        if (device->discipline->freeze)
                rc = device->discipline->freeze(device);
 
@@ -3363,6 +3366,7 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
        if (device->block)
                dasd_schedule_block_bh(device->block);
 
+       clear_bit(DASD_FLAG_SUSPENDED, &device->flags);
        dasd_put_device(device);
        return 0;
 }
index cb1bbc2..cca2509 100644 (file)
@@ -1101,6 +1101,12 @@ static void do_path_verification_work(struct work_struct *work)
        data = container_of(work, struct path_verification_work_data, worker);
        device = data->device;
 
+       /* delay path verification until device was resumed */
+       if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
+               schedule_work(work);
+               return;
+       }
+
        opm = 0;
        npm = 0;
        ppm = 0;
@@ -2047,9 +2053,13 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
        if ((scsw_dstat(&irb->scsw) & mask) == mask) {
-               /* for alias only and not in offline processing*/
+               /*
+                * for alias only, not in offline processing
+                * and only if not suspended
+                */
                if (!device->block && private->lcu &&
-                   !test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+                   !test_bit(DASD_FLAG_OFFLINE, &device->flags) &&
+                   !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
                        /*
                         * the state change could be caused by an alias
                         * reassignment remove device from alias handling
index 563bf8a..afe8c33 100644 (file)
@@ -516,6 +516,7 @@ struct dasd_block {
                                         */
 #define DASD_FLAG_IS_RESERVED  7       /* The device is reserved */
 #define DASD_FLAG_LOCK_STOLEN  8       /* The device lock was stolen */
+#define DASD_FLAG_SUSPENDED    9       /* The device was suspended */
 
 
 void dasd_put_device_wake(struct dasd_device *);