aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@sandisk.com>2017-03-17 20:02:01 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2017-03-19 13:15:50 -0400
commit625fe857e4fac6518716f3c0ff5e5deb8ec6d238 (patch)
tree02ac94b193a3b39c009c5ba6e0d635877057eabc
parentbf33f87dd04c371ea33feb821b60d63d754e3124 (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.c18
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/*