Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc3d12b7 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen
Browse files

scsi: libfc: hold disc_mutex in fc_disc_stop_rports()



fc_disc_stop_rports() is calling fc_rport_logoff(), which in turn is
acquiring the rport mutex. So we cannot use RCU list traversal here, but
rather need to hold the disc mutex to avoid list corruption while
traversing.

Fixes: a407c593 ("scsi: libfc: Fixup disc_mutex handling")
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9a26653b
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -62,20 +62,16 @@ static void fc_disc_restart(struct fc_disc *);
 */
static void fc_disc_stop_rports(struct fc_disc *disc)
{
	struct fc_lport *lport;
	struct fc_rport_priv *rdata;

	lport = fc_disc_lport(disc);
	lockdep_assert_held(&lport->lp_mutex);
	lockdep_assert_held(&disc->disc_mutex);

	rcu_read_lock();
	list_for_each_entry_rcu(rdata, &disc->rports, peers) {
	list_for_each_entry(rdata, &disc->rports, peers) {
		if (kref_get_unless_zero(&rdata->kref)) {
			fc_rport_logoff(rdata);
			kref_put(&rdata->kref, fc_rport_destroy);
		}
	}
	rcu_read_unlock();
}

/**
@@ -699,7 +695,9 @@ static void fc_disc_stop(struct fc_lport *lport)

	if (disc->pending)
		cancel_delayed_work_sync(&disc->disc_work);
	mutex_lock(&disc->disc_mutex);
	fc_disc_stop_rports(disc);
	mutex_unlock(&disc->disc_mutex);
}

/**