Skip to contentSkip to conversation

s390: dasd deadlock after state change pending interrupt.

PATCH New Martin Schwidefsky 1 participant 1 message Aug 24, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 s390: dasd deadlock after state change pending interrupt.

From: Martin Schwidefsky <[email protected]>

[S390] dasd deadlock after state change pending interrupt.

The dasd_device_from_cdev function is called from interrupt context to get the struct dasd_device associated with a ccw device. The driver_data of the ccw device points to the dasd_devmap structure which contains the pointer to the dasd_device structure. The lock that protects the dasd_devmap structure is acquire with out irqsave. To prevent the deadlock in dasd_device_from_cdev if it is called from interrupt context the dependency to the dasd_devmap structure needs to be removed. Let the driver_data of the ccw device point to the dasd_device structure directly and use the ccw device lock to protect the access.

---

 drivers/s390/block/dasd.c        |    4 +-
 drivers/s390/block/dasd_devmap.c |   74 +++++++++++++++++++++++++--------------
 drivers/s390/block/dasd_int.h    |    1 
 3 files changed, 51 insertions(+), 28 deletions(-)
drivers/s390/block/dasd.c +2 -2
diff -urpN linux-2.6/drivers/s390/block/dasd.c linux-2.6-patched/drivers/s390/block/dasd.c
@@ -893,7 +893,7 @@ dasd_handle_killed_request(struct ccw_de
 
 	device = (struct dasd_device *) cqr->device;
 	if (device == NULL ||
-	    device != dasd_device_from_cdev(cdev) ||
+	    device != dasd_device_from_cdev_locked(cdev) ||
 	    strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
 		MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
 			cdev->dev.bus_id);
@@ -970,7 +970,7 @@ dasd_int_handler(struct ccw_device *cdev
 	/* first of all check for state change pending interrupt */
 	mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
 	if ((irb->scsw.dstat & mask) == mask) {
-		device = dasd_device_from_cdev(cdev);
+		device = dasd_device_from_cdev_locked(cdev);
 		if (!IS_ERR(device)) {
 			dasd_handle_state_change_pending(device);
 			dasd_put_device(device);
drivers/s390/block/dasd_devmap.c +48 -26

132 lines not on this page · raw message

drivers/s390/block/dasd_int.h +1 -0
diff -urpN linux-2.6/drivers/s390/block/dasd_int.h linux-2.6-patched/drivers/s390/block/dasd_int.h
@@ -534,6 +534,7 @@ int dasd_add_sysfs_files(struct ccw_devi
 void dasd_remove_sysfs_files(struct ccw_device *);
 
 struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
+struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
 struct dasd_device *dasd_device_from_devindex(int);
 
 int dasd_parse(void);