Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Oct 2017 15:39:38 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324689 - head/sys/dev/iscsi
Message-ID:  <201710171539.v9HFdctF002356@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Tue Oct 17 15:39:38 2017
New Revision: 324689
URL: https://svnweb.freebsd.org/changeset/base/324689

Log:
  iscsi: do not hold the global lock while tearing down a session
  
  It should be sufficient to hold the lock just for removing the session
  from the session list.  Everything else should be covered by the session
  specific lock.
  
  On top of that, at present we can get a deadlock caused by waiting on
  the CAM SIM reference count while holding the global lock.  A specific
  scenario involving ZFS is this:
  - concurrent termination of two sessions, S1 and S2
  - session S1 completed all I/Os and sleeps in CAM waiting for device
    close by ZFS;
  - session S2 is also dead now, but can not forcefully complete
    outstanding requests by calling iscsi_session_cleanup() from
    iscsi_maintenance_thread_terminate(), since it can't get the same
    global sc_lock;
  - as soon as there are unfinished requests, ZFS can not do
    spa_config_enter() as writer, and so can not close the device for
    session S1;
  - deadlock.
  
  Reported by:	Ben RUBSON <ben.rubson@gmail.com>
  Tested by:	Ben RUBSON <ben.rubson@gmail.com>
  Reviewed by:	mav, trasz
  MFC after:	2 weeks
  Differential Revision: https://reviews.freebsd.org/D12652

Modified:
  head/sys/dev/iscsi/iscsi.c

Modified: head/sys/dev/iscsi/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/iscsi.c	Tue Oct 17 14:37:12 2017	(r324688)
+++ head/sys/dev/iscsi/iscsi.c	Tue Oct 17 15:39:38 2017	(r324689)
@@ -434,6 +434,8 @@ iscsi_maintenance_thread_terminate(struct iscsi_sessio
 
 	sc = is->is_softc;
 	sx_xlock(&sc->sc_lock);
+	TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
+	sx_xunlock(&sc->sc_lock);
 
 	icl_conn_close(is->is_conn);
 	callout_drain(&is->is_callout);
@@ -465,8 +467,6 @@ iscsi_maintenance_thread_terminate(struct iscsi_sessio
 #ifdef ICL_KERNEL_PROXY
 	cv_destroy(&is->is_login_cv);
 #endif
-	TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
-	sx_xunlock(&sc->sc_lock);
 
 	ISCSI_SESSION_DEBUG(is, "terminated");
 	free(is, M_ISCSI);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710171539.v9HFdctF002356>