diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2009-10-06 04:34:15 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2009-10-06 04:35:11 -0400 |
commit | 6fca97a958bc3c67566aa91eafc6a5be2e66d6b3 (patch) | |
tree | 9e5ca7c9c3d14c45f469feb58cab15212cee9d6b /drivers/s390/block/dasd.c | |
parent | af9d2ff9afaae8040dbf09238b2579f92c93579e (diff) |
[S390] dasd: fix race condition in resume code
There is a race while re-reading the device characteristics. After
cleaning the memory area a cqr is build which reads the device
characteristics. This may take a rather long time and the device
characteristics structure is zero during this. Now it could be
possible that the block tasklet starts working and a new cqr will be
build. The build_cp command refers to the device characteristics
structure and this may lead into a divide by zero exception.
Fix this by re-reading the device characteristics into a temporary
structur and copy the data to the original structure. Also take the
ccwdev_lock.
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index dad0449475b6..53b8c255360a 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -2508,8 +2508,6 @@ int dasd_generic_restore_device(struct ccw_device *cdev) | |||
2508 | device->stopped &= ~DASD_UNRESUMED_PM; | 2508 | device->stopped &= ~DASD_UNRESUMED_PM; |
2509 | 2509 | ||
2510 | dasd_schedule_device_bh(device); | 2510 | dasd_schedule_device_bh(device); |
2511 | if (device->block) | ||
2512 | dasd_schedule_block_bh(device->block); | ||
2513 | 2511 | ||
2514 | if (device->discipline->restore) | 2512 | if (device->discipline->restore) |
2515 | rc = device->discipline->restore(device); | 2513 | rc = device->discipline->restore(device); |
@@ -2520,6 +2518,9 @@ int dasd_generic_restore_device(struct ccw_device *cdev) | |||
2520 | */ | 2518 | */ |
2521 | device->stopped |= DASD_UNRESUMED_PM; | 2519 | device->stopped |= DASD_UNRESUMED_PM; |
2522 | 2520 | ||
2521 | if (device->block) | ||
2522 | dasd_schedule_block_bh(device->block); | ||
2523 | |||
2523 | dasd_put_device(device); | 2524 | dasd_put_device(device); |
2524 | return 0; | 2525 | return 0; |
2525 | } | 2526 | } |