diff options
author | Horst Hummel <horst.hummel@de.ibm.com> | 2005-09-03 18:57:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:06:26 -0400 |
commit | c6eb7b7703ac4b3401b74f411c8c51ded214bf19 (patch) | |
tree | 1cb3563cb83f80347dbc3e4bd30c4635d401e87a /drivers/s390/block/dasd_ioctl.c | |
parent | 942eaabd5d77522223a311ed9bddaaa3cefde27d (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>
Diffstat (limited to 'drivers/s390/block/dasd_ioctl.c')
-rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 17 |
1 files changed, 5 insertions, 12 deletions
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); |