Fix possible crash if AEN is sent to a being shutdown session, because after unreg_done_fn() called the target driver's part of the session

should be already freed.



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1789 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-06-25 17:25:18 +00:00
parent 8d4d13fdb1
commit bb21149a73
2 changed files with 27 additions and 1 deletions

View File

@@ -416,6 +416,9 @@ enum scst_exec_context {
/* Set if session is shutting down */
#define SCST_SESS_SPH_SHUTDOWN 1
/* Set if session is shutting down */
#define SCST_SESS_SPH_UNREG_DONE_CALLING 2
/*************************************************************
** Session's async (atomic) flags
*************************************************************/
@@ -783,7 +786,13 @@ struct scst_tgt_template {
* After AEN is sent, target driver must call scst_aen_done() and,
* optionally, scst_set_aen_delivery_status().
*
* This command is expected to be NON-BLOCKING, but can sleep.
* This function is expected to be NON-BLOCKING, but can sleep.
*
* This function must be prepared to handle AENs between calls for the
* corresponding session of scst_unregister_session() and
* unreg_done_fn() callback called or before scst_unregister_session()
* returned, if its called in the blocking mode. AENs for such sessions
* should be ignored.
*
* MUST HAVE, if low-level protocol supports AENs.
*/

View File

@@ -1326,6 +1326,10 @@ void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
TRACE_ENTRY();
if ((tgt_dev->sess->init_phase != SCST_SESS_IPH_READY) ||
(tgt_dev->sess->shut_phase != SCST_SESS_SPH_READY))
goto out;
if (tgtt->report_aen != NULL) {
struct scst_aen *aen;
int rc;
@@ -1488,6 +1492,10 @@ static void scst_report_luns_changed_sess(struct scst_session *sess)
TRACE_ENTRY();
if ((sess->init_phase != SCST_SESS_IPH_READY) ||
(sess->shut_phase != SCST_SESS_SPH_READY))
goto out;
TRACE_DBG("REPORTED LUNS DATA CHANGED (sess %p)", sess);
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
@@ -4021,6 +4029,15 @@ void scst_free_session_callback(struct scst_session *sess)
c = sess->shutdown_compl;
mutex_lock(&scst_mutex);
/*
* Necessary to sync with other threads trying to queue AEN, which
* the target driver will not be able to serve and crash, because after
* unreg_done_fn() called its internal session data will be destroyed.
*/
sess->shut_phase = SCST_SESS_SPH_UNREG_DONE_CALLING;
mutex_unlock(&scst_mutex);
if (sess->unreg_done_fn) {
TRACE_DBG("Calling unreg_done_fn(%p)", sess);
sess->unreg_done_fn(sess);