Skip to content

Commit 5faf50e

Browse files
hreineckemartinkpetersen
authored andcommitted
scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
alua_bus_detach() might be running concurrently with alua_rtpg_work(), so we might trip over h->sdev == NULL and call BUG_ON(). The correct way of handling it is to not set h->sdev to NULL in alua_bus_detach(), and call rcu_synchronize() before the final delete to ensure that all concurrent threads have left the critical section. Then we can get rid of the BUG_ON() and replace it with a simple if condition. Link: https://lore.kernel.org/r/1600167537-12509-1-git-send-email-jitendra.khasdev@oracle.com Link: https://lore.kernel.org/r/20200924104559.26753-1-hare@suse.de Cc: Brian Bunker <brian@purestorage.com> Acked-by: Brian Bunker <brian@purestorage.com> Tested-by: Jitendra Khasdev <jitendra.khasdev@oracle.com> Reviewed-by: Jitendra Khasdev <jitendra.khasdev@oracle.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent af61bc1 commit 5faf50e

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

drivers/scsi/device_handler/scsi_dh_alua.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
658658
rcu_read_lock();
659659
list_for_each_entry_rcu(h,
660660
&tmp_pg->dh_list, node) {
661-
/* h->sdev should always be valid */
662-
BUG_ON(!h->sdev);
661+
if (!h->sdev)
662+
continue;
663663
h->sdev->access_state = desc[0];
664664
}
665665
rcu_read_unlock();
@@ -705,7 +705,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
705705
pg->expiry = 0;
706706
rcu_read_lock();
707707
list_for_each_entry_rcu(h, &pg->dh_list, node) {
708-
BUG_ON(!h->sdev);
708+
if (!h->sdev)
709+
continue;
709710
h->sdev->access_state =
710711
(pg->state & SCSI_ACCESS_STATE_MASK);
711712
if (pg->pref)
@@ -1147,7 +1148,6 @@ static void alua_bus_detach(struct scsi_device *sdev)
11471148
spin_lock(&h->pg_lock);
11481149
pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock));
11491150
rcu_assign_pointer(h->pg, NULL);
1150-
h->sdev = NULL;
11511151
spin_unlock(&h->pg_lock);
11521152
if (pg) {
11531153
spin_lock_irq(&pg->lock);
@@ -1156,6 +1156,7 @@ static void alua_bus_detach(struct scsi_device *sdev)
11561156
kref_put(&pg->kref, release_port_group);
11571157
}
11581158
sdev->handler_data = NULL;
1159+
synchronize_rcu();
11591160
kfree(h);
11601161
}
11611162

0 commit comments

Comments
 (0)