diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2017-03-17 20:02:01 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-03-19 13:15:50 -0400 |
commit | 625fe857e4fac6518716f3c0ff5e5deb8ec6d238 (patch) | |
tree | 02ac94b193a3b39c009c5ba6e0d635877057eabc | |
parent | bf33f87dd04c371ea33feb821b60d63d754e3124 (diff) |
scsi: scsi_dh_alua: Check scsi_device_get() return value
Do not queue ALUA work nor call scsi_device_put() if the
scsi_device_get() call fails. This patch fixes the following crash:
general protection fault: 0000 [#1] SMP
RIP: 0010:scsi_device_put+0xb/0x30
Call Trace:
scsi_disk_put+0x2d/0x40
sd_release+0x3d/0xb0
__blkdev_put+0x29e/0x360
blkdev_put+0x49/0x170
dm_put_table_device+0x58/0xc0 [dm_mod]
dm_put_device+0x70/0xc0 [dm_mod]
free_priority_group+0x92/0xc0 [dm_multipath]
free_multipath+0x70/0xc0 [dm_multipath]
multipath_dtr+0x19/0x20 [dm_multipath]
dm_table_destroy+0x67/0x120 [dm_mod]
dev_suspend+0xde/0x240 [dm_mod]
ctl_ioctl+0x1f5/0x520 [dm_mod]
dm_ctl_ioctl+0xe/0x20 [dm_mod]
do_vfs_ioctl+0x8f/0x700
SyS_ioctl+0x3c/0x70
entry_SYSCALL_64_fastpath+0x18/0xad
Fixes: commit 03197b61c5ec ("scsi_dh_alua: Use workqueue for RTPG")
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Tang Junhui <tang.junhui@zte.com.cn>
Cc: <stable@vger.kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 48e200102221..e0b15f3dd303 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -870,7 +870,7 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
870 | unsigned long flags; | 870 | unsigned long flags; |
871 | struct workqueue_struct *alua_wq = kaluad_wq; | 871 | struct workqueue_struct *alua_wq = kaluad_wq; |
872 | 872 | ||
873 | if (!pg) | 873 | if (!pg || scsi_device_get(sdev)) |
874 | return; | 874 | return; |
875 | 875 | ||
876 | spin_lock_irqsave(&pg->lock, flags); | 876 | spin_lock_irqsave(&pg->lock, flags); |
@@ -884,14 +884,12 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
884 | pg->flags |= ALUA_PG_RUN_RTPG; | 884 | pg->flags |= ALUA_PG_RUN_RTPG; |
885 | kref_get(&pg->kref); | 885 | kref_get(&pg->kref); |
886 | pg->rtpg_sdev = sdev; | 886 | pg->rtpg_sdev = sdev; |
887 | scsi_device_get(sdev); | ||
888 | start_queue = 1; | 887 | start_queue = 1; |
889 | } else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force) { | 888 | } else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force) { |
890 | pg->flags |= ALUA_PG_RUN_RTPG; | 889 | pg->flags |= ALUA_PG_RUN_RTPG; |
891 | /* Do not queue if the worker is already running */ | 890 | /* Do not queue if the worker is already running */ |
892 | if (!(pg->flags & ALUA_PG_RUNNING)) { | 891 | if (!(pg->flags & ALUA_PG_RUNNING)) { |
893 | kref_get(&pg->kref); | 892 | kref_get(&pg->kref); |
894 | sdev = NULL; | ||
895 | start_queue = 1; | 893 | start_queue = 1; |
896 | } | 894 | } |
897 | } | 895 | } |
@@ -900,13 +898,15 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
900 | alua_wq = kaluad_sync_wq; | 898 | alua_wq = kaluad_sync_wq; |
901 | spin_unlock_irqrestore(&pg->lock, flags); | 899 | spin_unlock_irqrestore(&pg->lock, flags); |
902 | 900 | ||
903 | if (start_queue && | 901 | if (start_queue) { |
904 | !queue_delayed_work(alua_wq, &pg->rtpg_work, | 902 | if (queue_delayed_work(alua_wq, &pg->rtpg_work, |
905 | msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) { | 903 | msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) |
906 | if (sdev) | 904 | sdev = NULL; |
907 | scsi_device_put(sdev); | 905 | else |
908 | kref_put(&pg->kref, release_port_group); | 906 | kref_put(&pg->kref, release_port_group); |
909 | } | 907 | } |
908 | if (sdev) | ||
909 | scsi_device_put(sdev); | ||
910 | } | 910 | } |
911 | 911 | ||
912 | /* | 912 | /* |