aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHorst Hummel <horst.hummel@de.ibm.com>2005-09-03 18:57:58 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:26 -0400
commitc6eb7b7703ac4b3401b74f411c8c51ded214bf19 (patch)
tree1cb3563cb83f80347dbc3e4bd30c4635d401e87a
parent942eaabd5d77522223a311ed9bddaaa3cefde27d (diff)
[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>
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_devmap.c8
-rw-r--r--drivers/s390/block/dasd_genhd.c10
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c17
-rw-r--r--drivers/s390/block/dasd_proc.c8
6 files changed, 24 insertions, 41 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d5f53980749b..8fc891a9d47f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9 * 9 *
10 * $Revision: 1.165 $ 10 * $Revision: 1.167 $
11 */ 11 */
12 12
13#include <linux/config.h> 13#include <linux/config.h>
@@ -1131,17 +1131,13 @@ __dasd_process_blk_queue(struct dasd_device * device)
1131 request_queue_t *queue; 1131 request_queue_t *queue;
1132 struct request *req; 1132 struct request *req;
1133 struct dasd_ccw_req *cqr; 1133 struct dasd_ccw_req *cqr;
1134 int nr_queued, feature_ro; 1134 int nr_queued;
1135 1135
1136 queue = device->request_queue; 1136 queue = device->request_queue;
1137 /* No queue ? Then there is nothing to do. */ 1137 /* No queue ? Then there is nothing to do. */
1138 if (queue == NULL) 1138 if (queue == NULL)
1139 return; 1139 return;
1140 1140
1141 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
1142 if (feature_ro < 0) /* no devmap */
1143 return;
1144
1145 /* 1141 /*
1146 * We requeue request from the block device queue to the ccw 1142 * We requeue request from the block device queue to the ccw
1147 * queue only in two states. In state DASD_STATE_READY the 1143 * queue only in two states. In state DASD_STATE_READY the
@@ -1162,7 +1158,8 @@ __dasd_process_blk_queue(struct dasd_device * device)
1162 nr_queued < DASD_CHANQ_MAX_SIZE) { 1158 nr_queued < DASD_CHANQ_MAX_SIZE) {
1163 req = elv_next_request(queue); 1159 req = elv_next_request(queue);
1164 1160
1165 if (feature_ro && rq_data_dir(req) == WRITE) { 1161 if (device->features & DASD_FEATURE_READONLY &&
1162 rq_data_dir(req) == WRITE) {
1166 DBF_DEV_EVENT(DBF_ERR, device, 1163 DBF_DEV_EVENT(DBF_ERR, device,
1167 "Rejecting write request %p", 1164 "Rejecting write request %p",
1168 req); 1165 req);
@@ -1814,17 +1811,13 @@ dasd_generic_set_online (struct ccw_device *cdev,
1814 1811
1815{ 1812{
1816 struct dasd_device *device; 1813 struct dasd_device *device;
1817 int feature_diag, rc; 1814 int rc;
1818 1815
1819 device = dasd_create_device(cdev); 1816 device = dasd_create_device(cdev);
1820 if (IS_ERR(device)) 1817 if (IS_ERR(device))
1821 return PTR_ERR(device); 1818 return PTR_ERR(device);
1822 1819
1823 feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG); 1820 if (device->features & DASD_FEATURE_USEDIAG) {
1824 if (feature_diag < 0)
1825 return feature_diag;
1826
1827 if (feature_diag) {
1828 if (!dasd_diag_discipline_pointer) { 1821 if (!dasd_diag_discipline_pointer) {
1829 printk (KERN_WARNING 1822 printk (KERN_WARNING
1830 "dasd_generic couldn't online device %s " 1823 "dasd_generic couldn't online device %s "
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d948566bb24a..bda896d9d788 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,7 @@
11 * functions may not be called from interrupt context. In particular 11 * functions may not be called from interrupt context. In particular
12 * dasd_get_device is a no-no from interrupt context. 12 * dasd_get_device is a no-no from interrupt context.
13 * 13 *
14 * $Revision: 1.40 $ 14 * $Revision: 1.43 $
15 */ 15 */
16 16
17#include <linux/config.h> 17#include <linux/config.h>
@@ -513,6 +513,7 @@ dasd_create_device(struct ccw_device *cdev)
513 if (!devmap->device) { 513 if (!devmap->device) {
514 devmap->device = device; 514 devmap->device = device;
515 device->devindex = devmap->devindex; 515 device->devindex = devmap->devindex;
516 device->features = devmap->features;
516 get_device(&cdev->dev); 517 get_device(&cdev->dev);
517 device->cdev = cdev; 518 device->cdev = cdev;
518 rc = 0; 519 rc = 0;
@@ -643,6 +644,8 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf
643 devmap->features |= DASD_FEATURE_READONLY; 644 devmap->features |= DASD_FEATURE_READONLY;
644 else 645 else
645 devmap->features &= ~DASD_FEATURE_READONLY; 646 devmap->features &= ~DASD_FEATURE_READONLY;
647 if (devmap->device)
648 devmap->device->features = devmap->features;
646 if (devmap->device && devmap->device->gdp) 649 if (devmap->device && devmap->device->gdp)
647 set_disk_ro(devmap->device->gdp, ro_flag); 650 set_disk_ro(devmap->device->gdp, ro_flag);
648 spin_unlock(&dasd_devmap_lock); 651 spin_unlock(&dasd_devmap_lock);
@@ -758,7 +761,8 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
758 devmap->features |= feature; 761 devmap->features |= feature;
759 else 762 else
760 devmap->features &= ~feature; 763 devmap->features &= ~feature;
761 764 if (devmap->device)
765 devmap->device->features = devmap->features;
762 spin_unlock(&dasd_devmap_lock); 766 spin_unlock(&dasd_devmap_lock);
763 return 0; 767 return 0;
764} 768}
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 96c49349701f..a601c9a33541 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * gendisk related functions for the dasd driver. 10 * gendisk related functions for the dasd driver.
11 * 11 *
12 * $Revision: 1.50 $ 12 * $Revision: 1.51 $
13 */ 13 */
14 14
15#include <linux/config.h> 15#include <linux/config.h>
@@ -31,16 +31,12 @@ int
31dasd_gendisk_alloc(struct dasd_device *device) 31dasd_gendisk_alloc(struct dasd_device *device)
32{ 32{
33 struct gendisk *gdp; 33 struct gendisk *gdp;
34 int len, feature_ro; 34 int len;
35 35
36 /* Make sure the minor for this device exists. */ 36 /* Make sure the minor for this device exists. */
37 if (device->devindex >= DASD_PER_MAJOR) 37 if (device->devindex >= DASD_PER_MAJOR)
38 return -EBUSY; 38 return -EBUSY;
39 39
40 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
41 if (feature_ro < 0)
42 return feature_ro;
43
44 gdp = alloc_disk(1 << DASD_PARTN_BITS); 40 gdp = alloc_disk(1 << DASD_PARTN_BITS);
45 if (!gdp) 41 if (!gdp)
46 return -ENOMEM; 42 return -ENOMEM;
@@ -75,7 +71,7 @@ dasd_gendisk_alloc(struct dasd_device *device)
75 71
76 sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id); 72 sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
77 73
78 if (feature_ro) 74 if (device->features & DASD_FEATURE_READONLY)
79 set_disk_ro(gdp, 1); 75 set_disk_ro(gdp, 1);
80 gdp->private_data = device; 76 gdp->private_data = device;
81 gdp->queue = device->request_queue; 77 gdp->queue = device->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a9f38b235981..9fab04f3056d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
6 * Bugreports.to..: <Linux390@de.ibm.com> 6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
8 * 8 *
9 * $Revision: 1.64 $ 9 * $Revision: 1.65 $
10 */ 10 */
11 11
12#ifndef DASD_INT_H 12#ifndef DASD_INT_H
@@ -286,6 +286,7 @@ struct dasd_device {
286 unsigned int bp_block; /* bytes per block */ 286 unsigned int bp_block; /* bytes per block */
287 unsigned int s2b_shift; /* log2 (bp_block/512) */ 287 unsigned int s2b_shift; /* log2 (bp_block/512) */
288 unsigned long flags; /* per device flags */ 288 unsigned long flags; /* per device flags */
289 unsigned short features; /* copy of devmap-features (read-only!) */
289 290
290 /* Device discipline stuff. */ 291 /* Device discipline stuff. */
291 struct dasd_discipline *discipline; 292 struct dasd_discipline *discipline;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 980c555aa538..789595b3fa09 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9 * 9 *
10 * $Revision: 1.45 $ 10 * $Revision: 1.47 $
11 * 11 *
12 * i/o controls for the dasd driver. 12 * i/o controls for the dasd driver.
13 */ 13 */
@@ -296,7 +296,6 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
296{ 296{
297 struct dasd_device *device; 297 struct dasd_device *device;
298 struct format_data_t fdata; 298 struct format_data_t fdata;
299 int feature_ro;
300 299
301 if (!capable(CAP_SYS_ADMIN)) 300 if (!capable(CAP_SYS_ADMIN))
302 return -EACCES; 301 return -EACCES;
@@ -308,10 +307,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
308 if (device == NULL) 307 if (device == NULL)
309 return -ENODEV; 308 return -ENODEV;
310 309
311 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); 310 if (device->features & DASD_FEATURE_READONLY)
312 if (feature_ro < 0)
313 return feature_ro;
314 if (feature_ro)
315 return -EROFS; 311 return -EROFS;
316 if (copy_from_user(&fdata, (void __user *) args, 312 if (copy_from_user(&fdata, (void __user *) args,
317 sizeof (struct format_data_t))) 313 sizeof (struct format_data_t)))
@@ -384,7 +380,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
384 struct dasd_device *device; 380 struct dasd_device *device;
385 struct dasd_information2_t *dasd_info; 381 struct dasd_information2_t *dasd_info;
386 unsigned long flags; 382 unsigned long flags;
387 int rc, feature_ro; 383 int rc;
388 struct ccw_device *cdev; 384 struct ccw_device *cdev;
389 385
390 device = bdev->bd_disk->private_data; 386 device = bdev->bd_disk->private_data;
@@ -394,10 +390,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
394 if (!device->discipline->fill_info) 390 if (!device->discipline->fill_info)
395 return -EINVAL; 391 return -EINVAL;
396 392
397 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
398 if (feature_ro < 0)
399 return feature_ro;
400
401 dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); 393 dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
402 if (dasd_info == NULL) 394 if (dasd_info == NULL)
403 return -ENOMEM; 395 return -ENOMEM;
@@ -427,7 +419,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
427 (dasd_check_blocksize(device->bp_block))) 419 (dasd_check_blocksize(device->bp_block)))
428 dasd_info->format = DASD_FORMAT_NONE; 420 dasd_info->format = DASD_FORMAT_NONE;
429 421
430 dasd_info->features |= feature_ro; 422 dasd_info->features |=
423 ((device->features & DASD_FEATURE_READONLY) != 0);
431 424
432 if (device->discipline) 425 if (device->discipline)
433 memcpy(dasd_info->type, device->discipline->name, 4); 426 memcpy(dasd_info->type, device->discipline->name, 4);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 43c34f8c5e68..fff9020d4886 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * /proc interface for the dasd driver. 10 * /proc interface for the dasd driver.
11 * 11 *
12 * $Revision: 1.32 $ 12 * $Revision: 1.33 $
13 */ 13 */
14 14
15#include <linux/config.h> 15#include <linux/config.h>
@@ -55,7 +55,6 @@ dasd_devices_show(struct seq_file *m, void *v)
55{ 55{
56 struct dasd_device *device; 56 struct dasd_device *device;
57 char *substr; 57 char *substr;
58 int feature;
59 58
60 device = dasd_device_from_devindex((unsigned long) v - 1); 59 device = dasd_device_from_devindex((unsigned long) v - 1);
61 if (IS_ERR(device)) 60 if (IS_ERR(device))
@@ -79,10 +78,7 @@ dasd_devices_show(struct seq_file *m, void *v)
79 else 78 else
80 seq_printf(m, " is ????????"); 79 seq_printf(m, " is ????????");
81 /* Print devices features. */ 80 /* Print devices features. */
82 feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); 81 substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
83 if (feature < 0)
84 return 0;
85 substr = feature ? "(ro)" : " ";
86 seq_printf(m, "%4s: ", substr); 82 seq_printf(m, "%4s: ", substr);
87 /* Print device status information. */ 83 /* Print device status information. */
88 switch ((device != NULL) ? device->state : -1) { 84 switch ((device != NULL) ? device->state : -1) {