diff options
author | Bart Van Assche <bart.vanassche@wdc.com> | 2018-08-02 13:44:42 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-08-03 13:53:51 -0400 |
commit | 1214fd7b497400d200e3f4e64e2338b303a20949 (patch) | |
tree | 821a5ceab8732ec48ae182834d1684dcfdd7aeb0 /drivers/scsi/sr.c | |
parent | 09c2f95ad404bc6e9995f5bce04ae85d0fffc534 (diff) |
scsi: sr: Avoid that opening a CD-ROM hangs with runtime power management enabled
Surround scsi_execute() calls with scsi_autopm_get_device() and
scsi_autopm_put_device(). Note: removing sr_mutex protection from the
scsi_cd_get() and scsi_cd_put() calls is safe because the purpose of
sr_mutex is to serialize cdrom_*() calls.
This patch avoids that complaints similar to the following appear in the
kernel log if runtime power management is enabled:
INFO: task systemd-udevd:650 blocked for more than 120 seconds.
Not tainted 4.18.0-rc7-dbg+ #1
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
systemd-udevd D28176 650 513 0x00000104
Call Trace:
__schedule+0x444/0xfe0
schedule+0x4e/0xe0
schedule_preempt_disabled+0x18/0x30
__mutex_lock+0x41c/0xc70
mutex_lock_nested+0x1b/0x20
__blkdev_get+0x106/0x970
blkdev_get+0x22c/0x5a0
blkdev_open+0xe9/0x100
do_dentry_open.isra.19+0x33e/0x570
vfs_open+0x7c/0xd0
path_openat+0x6e3/0x1120
do_filp_open+0x11c/0x1c0
do_sys_open+0x208/0x2d0
__x64_sys_openat+0x59/0x70
do_syscall_64+0x77/0x230
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Cc: Maurizio Lombardi <mlombard@redhat.com>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: <stable@vger.kernel.org>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r-- | drivers/scsi/sr.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 3f3cb72e0c0c..d0389b20574d 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -523,18 +523,26 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) | |||
523 | static int sr_block_open(struct block_device *bdev, fmode_t mode) | 523 | static int sr_block_open(struct block_device *bdev, fmode_t mode) |
524 | { | 524 | { |
525 | struct scsi_cd *cd; | 525 | struct scsi_cd *cd; |
526 | struct scsi_device *sdev; | ||
526 | int ret = -ENXIO; | 527 | int ret = -ENXIO; |
527 | 528 | ||
529 | cd = scsi_cd_get(bdev->bd_disk); | ||
530 | if (!cd) | ||
531 | goto out; | ||
532 | |||
533 | sdev = cd->device; | ||
534 | scsi_autopm_get_device(sdev); | ||
528 | check_disk_change(bdev); | 535 | check_disk_change(bdev); |
529 | 536 | ||
530 | mutex_lock(&sr_mutex); | 537 | mutex_lock(&sr_mutex); |
531 | cd = scsi_cd_get(bdev->bd_disk); | 538 | ret = cdrom_open(&cd->cdi, bdev, mode); |
532 | if (cd) { | ||
533 | ret = cdrom_open(&cd->cdi, bdev, mode); | ||
534 | if (ret) | ||
535 | scsi_cd_put(cd); | ||
536 | } | ||
537 | mutex_unlock(&sr_mutex); | 539 | mutex_unlock(&sr_mutex); |
540 | |||
541 | scsi_autopm_put_device(sdev); | ||
542 | if (ret) | ||
543 | scsi_cd_put(cd); | ||
544 | |||
545 | out: | ||
538 | return ret; | 546 | return ret; |
539 | } | 547 | } |
540 | 548 | ||
@@ -562,6 +570,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
562 | if (ret) | 570 | if (ret) |
563 | goto out; | 571 | goto out; |
564 | 572 | ||
573 | scsi_autopm_get_device(sdev); | ||
574 | |||
565 | /* | 575 | /* |
566 | * Send SCSI addressing ioctls directly to mid level, send other | 576 | * Send SCSI addressing ioctls directly to mid level, send other |
567 | * ioctls to cdrom/block level. | 577 | * ioctls to cdrom/block level. |
@@ -570,15 +580,18 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
570 | case SCSI_IOCTL_GET_IDLUN: | 580 | case SCSI_IOCTL_GET_IDLUN: |
571 | case SCSI_IOCTL_GET_BUS_NUMBER: | 581 | case SCSI_IOCTL_GET_BUS_NUMBER: |
572 | ret = scsi_ioctl(sdev, cmd, argp); | 582 | ret = scsi_ioctl(sdev, cmd, argp); |
573 | goto out; | 583 | goto put; |
574 | } | 584 | } |
575 | 585 | ||
576 | ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); | 586 | ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); |
577 | if (ret != -ENOSYS) | 587 | if (ret != -ENOSYS) |
578 | goto out; | 588 | goto put; |
579 | 589 | ||
580 | ret = scsi_ioctl(sdev, cmd, argp); | 590 | ret = scsi_ioctl(sdev, cmd, argp); |
581 | 591 | ||
592 | put: | ||
593 | scsi_autopm_put_device(sdev); | ||
594 | |||
582 | out: | 595 | out: |
583 | mutex_unlock(&sr_mutex); | 596 | mutex_unlock(&sr_mutex); |
584 | return ret; | 597 | return ret; |