[PATCH] s390: deadlock in dasd_devmap

Reintroduce a read-only copy of the devmap features in the device struct.
This is necessary to solve a deadlock on the dasd_devmap_lock which is
acquired by dasd_get_features called from the dasd tasklet.  The current
implementation of devmap doesn't allow to call any devmap function from
interrupt or softirq context.

Signed-off-by: Horst Hummel <horst.hummel@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 980c555..789595b 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.45 $
+ * $Revision: 1.47 $
  *
  * i/o controls for the dasd driver.
  */
@@ -296,7 +296,6 @@
 {
 	struct dasd_device *device;
 	struct format_data_t fdata;
-	int feature_ro;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -308,10 +307,7 @@
 	if (device == NULL)
 		return -ENODEV;
 
-	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
-	if (feature_ro < 0)
-		return feature_ro;
-	if (feature_ro)
+	if (device->features & DASD_FEATURE_READONLY)
 		return -EROFS;
 	if (copy_from_user(&fdata, (void __user *) args,
 			   sizeof (struct format_data_t)))
@@ -384,7 +380,7 @@
 	struct dasd_device *device;
 	struct dasd_information2_t *dasd_info;
 	unsigned long flags;
-	int rc, feature_ro;
+	int rc;
 	struct ccw_device *cdev;
 
 	device = bdev->bd_disk->private_data;
@@ -394,10 +390,6 @@
 	if (!device->discipline->fill_info)
 		return -EINVAL;
 
-	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
-	if (feature_ro < 0)
-		return feature_ro;
-
 	dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
 	if (dasd_info == NULL)
 		return -ENOMEM;
@@ -427,7 +419,8 @@
 	    (dasd_check_blocksize(device->bp_block)))
 		dasd_info->format = DASD_FORMAT_NONE;
 
-	dasd_info->features |= feature_ro;
+	dasd_info->features |=
+		((device->features & DASD_FEATURE_READONLY) != 0);
 
 	if (device->discipline)
 		memcpy(dasd_info->type, device->discipline->name, 4);