diff mbox

[PATCHv2] libfc: fixup 'sleeping function called from invalid context'

Message ID 20180704115916.24962-1-hare@suse.de (mailing list archive)
State Accepted
Headers show

Commit Message

Hannes Reinecke July 4, 2018, 11:59 a.m. UTC
fc_rport_login() will be calling mutex_lock() while running inside
an RCU-protected section, triggering the warning 'sleeping function
called from invalid context'.
To fix this we can drop the rcu functions here altogether as the
disc mutex protecting the list itself is already held, preventing
any list manipulation.

Fixes: a407c593398c ("scsi: libfc: Fixup disc_mutex handling")
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_disc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Comments

Johannes Thumshirn July 4, 2018, 12:02 p.m. UTC | #1
Acked-by: Johannes Thumshirn <jth@kernel.org>
Martin K. Petersen July 11, 2018, 2:52 a.m. UTC | #2
Hannes,

> fc_rport_login() will be calling mutex_lock() while running inside
> an RCU-protected section, triggering the warning 'sleeping function
> called from invalid context'.
> To fix this we can drop the rcu functions here altogether as the
> disc mutex protecting the list itself is already held, preventing
> any list manipulation.

Applied to 4.19/scsi-queue, thanks!
diff mbox

Patch

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 6125df787200..c1756b9b3ea5 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -287,9 +287,11 @@  static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 	 * discovery, reverify or log them in.	Otherwise, log them out.
 	 * Skip ports which were never discovered.  These are the dNS port
 	 * and ports which were created by PLOGI.
+	 *
+	 * We don't need to use the _rcu variant here as the rport list
+	 * is protected by the disc mutex which is already held on entry.
 	 */
-	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))
 			continue;
 		if (rdata->disc_id) {
@@ -300,7 +302,6 @@  static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 		}
 		kref_put(&rdata->kref, fc_rport_destroy);
 	}
-	rcu_read_unlock();
 	mutex_unlock(&disc->disc_mutex);
 	disc->disc_callback(lport, event);
 	mutex_lock(&disc->disc_mutex);