| From 1214fd7b497400d200e3f4e64e2338b303a20949 Mon Sep 17 00:00:00 2001 |
| From: Bart Van Assche <bart.vanassche@wdc.com> |
| Date: Thu, 2 Aug 2018 10:44:42 -0700 |
| Subject: scsi: sr: Avoid that opening a CD-ROM hangs with runtime power management enabled |
| |
| From: Bart Van Assche <bart.vanassche@wdc.com> |
| |
| commit 1214fd7b497400d200e3f4e64e2338b303a20949 upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/sr.c | 29 +++++++++++++++++++++-------- |
| 1 file changed, 21 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/scsi/sr.c |
| +++ b/drivers/scsi/sr.c |
| @@ -520,18 +520,26 @@ static int sr_init_command(struct scsi_c |
| static int sr_block_open(struct block_device *bdev, fmode_t mode) |
| { |
| struct scsi_cd *cd; |
| + struct scsi_device *sdev; |
| int ret = -ENXIO; |
| |
| + cd = scsi_cd_get(bdev->bd_disk); |
| + if (!cd) |
| + goto out; |
| + |
| + sdev = cd->device; |
| + scsi_autopm_get_device(sdev); |
| check_disk_change(bdev); |
| |
| mutex_lock(&sr_mutex); |
| - cd = scsi_cd_get(bdev->bd_disk); |
| - if (cd) { |
| - ret = cdrom_open(&cd->cdi, bdev, mode); |
| - if (ret) |
| - scsi_cd_put(cd); |
| - } |
| + ret = cdrom_open(&cd->cdi, bdev, mode); |
| mutex_unlock(&sr_mutex); |
| + |
| + scsi_autopm_put_device(sdev); |
| + if (ret) |
| + scsi_cd_put(cd); |
| + |
| +out: |
| return ret; |
| } |
| |
| @@ -559,6 +567,8 @@ static int sr_block_ioctl(struct block_d |
| if (ret) |
| goto out; |
| |
| + scsi_autopm_get_device(sdev); |
| + |
| /* |
| * Send SCSI addressing ioctls directly to mid level, send other |
| * ioctls to cdrom/block level. |
| @@ -567,15 +577,18 @@ static int sr_block_ioctl(struct block_d |
| case SCSI_IOCTL_GET_IDLUN: |
| case SCSI_IOCTL_GET_BUS_NUMBER: |
| ret = scsi_ioctl(sdev, cmd, argp); |
| - goto out; |
| + goto put; |
| } |
| |
| ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); |
| if (ret != -ENOSYS) |
| - goto out; |
| + goto put; |
| |
| ret = scsi_ioctl(sdev, cmd, argp); |
| |
| +put: |
| + scsi_autopm_put_device(sdev); |
| + |
| out: |
| mutex_unlock(&sr_mutex); |
| return ret; |