diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2016-11-01 10:19:57 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-11-01 13:32:24 -0400 |
commit | df3d422cbac685da882e4c239dfda07de33d431b (patch) | |
tree | 5d61ed8c7e551eb980a4c1772964bdce25d8c1d8 | |
parent | aac173e9618faadf8f92af6cc05e64f7acc64d79 (diff) |
scsi: scsi_dh_alua: Fix a reference counting bug
The code at the end of alua_rtpg_work() is as follows:
scsi_device_put(sdev);
kref_put(&pg->kref, release_port_group);
In other words, alua_rtpg_queue() must hold an sdev reference and a pg
reference before queueing rtpg work. If no rtpg work is queued no
additional references should be held when alua_rtpg_queue() returns. If
no rtpg work is queued, ensure that alua_rtpg_queue() only gives up the
sdev reference if that reference was obtained by the same
alua_rtpg_queue() call.
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reported-by: Tang Junhui <tang.junhui@zte.com.cn>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Tang Junhui <tang.junhui@zte.com.cn>
Cc: <stable@vger.kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index f375167f16ea..7bb20684e9fa 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -891,6 +891,7 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
891 | /* Do not queue if the worker is already running */ | 891 | /* Do not queue if the worker is already running */ |
892 | if (!(pg->flags & ALUA_PG_RUNNING)) { | 892 | if (!(pg->flags & ALUA_PG_RUNNING)) { |
893 | kref_get(&pg->kref); | 893 | kref_get(&pg->kref); |
894 | sdev = NULL; | ||
894 | start_queue = 1; | 895 | start_queue = 1; |
895 | } | 896 | } |
896 | } | 897 | } |
@@ -902,7 +903,8 @@ static void alua_rtpg_queue(struct alua_port_group *pg, | |||
902 | if (start_queue && | 903 | if (start_queue && |
903 | !queue_delayed_work(alua_wq, &pg->rtpg_work, | 904 | !queue_delayed_work(alua_wq, &pg->rtpg_work, |
904 | msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) { | 905 | msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) { |
905 | scsi_device_put(sdev); | 906 | if (sdev) |
907 | scsi_device_put(sdev); | ||
906 | kref_put(&pg->kref, release_port_group); | 908 | kref_put(&pg->kref, release_port_group); |
907 | } | 909 | } |
908 | } | 910 | } |