diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2017-03-17 20:02:02 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-03-19 13:16:17 -0400 |
commit | 7cb689fe42927281b8d98606ae5450173fcc66a9 (patch) | |
tree | 802764e7495d034b88a3868e6e23d1c4d75e6bfa | |
parent | 625fe857e4fac6518716f3c0ff5e5deb8ec6d238 (diff) |
scsi: scsi_dh_alua: Ensure that alua_activate() calls the completion function
Callers of scsi_dh_activate(), e.g. dm-mpath, assume that this function
either returns an error code or calls the completion function. Make
alua_activate() call the completion function even if scsi_device_get()
fails.
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 | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e0b15f3dd303..b6849d3ecefe 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -113,7 +113,7 @@ struct alua_queue_data { | |||
113 | #define ALUA_POLICY_SWITCH_ALL 1 | 113 | #define ALUA_POLICY_SWITCH_ALL 1 |
114 | 114 | ||
115 | static void alua_rtpg_work(struct work_struct *work); | 115 | static void alua_rtpg_work(struct work_struct *work); |
116 | static void alua_rtpg_queue(struct alua_port_group *pg, | 116 | static bool alua_rtpg_queue(struct alua_port_group *pg, |
117 | struct scsi_device *sdev, | 117 | struct scsi_device *sdev, |
118 | struct alua_queue_data *qdata, bool force); | 118 | struct alua_queue_data *qdata, bool force); |
119 | static void alua_check(struct scsi_device *sdev, bool force); | 119 | static void alua_check(struct scsi_device *sdev, bool force); |
@@ -862,7 +862,13 @@ static void alua_rtpg_work(struct work_struct *work) | |||
862 | kref_put(&pg->kref, release_port_group); | 862 | kref_put(&pg->kref, release_port_group); |
863 | } | 863 | } |
864 | 864 | ||
865 | static void alua_rtpg_queue(struct alua_port_group *pg, | 865 | /** |
866 | * alua_rtpg_queue() - cause RTPG to be submitted asynchronously | ||
867 | * | ||
868 | * Returns true if and only if alua_rtpg_work() will be called asynchronously. | ||
869 | * That function is responsible for calling @qdata->fn(). | ||
870 | */ | ||
871 | static bool alua_rtpg_queue(struct alua_port_group *pg, | ||
866 | struct scsi_device *sdev, | 872 | struct scsi_device *sdev, |
867 | struct alua_queue_data *qdata, bool force) | 873 | struct alua_queue_data *qdata, bool force) |
868 | { | 874 | { |
@@ -871,7 +877,7 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
871 | struct workqueue_struct *alua_wq = kaluad_wq; | 877 | struct workqueue_struct *alua_wq = kaluad_wq; |
872 | 878 | ||
873 | if (!pg || scsi_device_get(sdev)) | 879 | if (!pg || scsi_device_get(sdev)) |
874 | return; | 880 | return false; |
875 | 881 | ||
876 | spin_lock_irqsave(&pg->lock, flags); | 882 | spin_lock_irqsave(&pg->lock, flags); |
877 | if (qdata) { | 883 | if (qdata) { |
@@ -907,6 +913,8 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
907 | } | 913 | } |
908 | if (sdev) | 914 | if (sdev) |
909 | scsi_device_put(sdev); | 915 | scsi_device_put(sdev); |
916 | |||
917 | return true; | ||
910 | } | 918 | } |
911 | 919 | ||
912 | /* | 920 | /* |
@@ -1007,11 +1015,13 @@ static int alua_activate(struct scsi_device *sdev, | |||
1007 | mutex_unlock(&h->init_mutex); | 1015 | mutex_unlock(&h->init_mutex); |
1008 | goto out; | 1016 | goto out; |
1009 | } | 1017 | } |
1010 | fn = NULL; | ||
1011 | rcu_read_unlock(); | 1018 | rcu_read_unlock(); |
1012 | mutex_unlock(&h->init_mutex); | 1019 | mutex_unlock(&h->init_mutex); |
1013 | 1020 | ||
1014 | alua_rtpg_queue(pg, sdev, qdata, true); | 1021 | if (alua_rtpg_queue(pg, sdev, qdata, true)) |
1022 | fn = NULL; | ||
1023 | else | ||
1024 | err = SCSI_DH_DEV_OFFLINED; | ||
1015 | kref_put(&pg->kref, release_port_group); | 1025 | kref_put(&pg->kref, release_port_group); |
1016 | out: | 1026 | out: |
1017 | if (fn) | 1027 | if (fn) |