s390: dasd deadlock after state change pending interrupt.
Subsystems (2)
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
@@ -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
@@ -534,6 +534,7 @@ int dasd_add_sysfs_files(struct ccw_devivoid 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 );