Fix possible crash with too fast target mode enabling/disabling or module unload
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 11 May 2009 17:06:54 +0000 (17:06 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 11 May 2009 17:06:54 +0000 (17:06 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@839 d57e44dd-8a1f-0410-8b47-8ef2f437770f

qla2x00t/qla2x00-target/qla2x00t.c

index c22b203..318f86f 100644 (file)
@@ -97,6 +97,7 @@ static struct scst_tgt_template tgt_template = {
 
 static struct kmem_cache *q2t_cmd_cachep;
 static struct qla2x_tgt_target tgt_data;
+static DEFINE_MUTEX(qla_mgmt_mutex);
 
 /*
  * Functions
@@ -377,6 +378,8 @@ static int q2t_target_release(struct scst_tgt *scst_tgt)
 
        wait_event(tgt->waitQ, test_tgt_sess_count(tgt, ha));
 
+       mutex_lock(&qla_mgmt_mutex);
+
        /* big hammer */
        if (!ha->flags.host_shutting_down)
                tgt_data.disable_lun(ha);
@@ -394,6 +397,8 @@ static int q2t_target_release(struct scst_tgt *scst_tgt)
        ha->tgt = NULL;
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+       mutex_unlock(&qla_mgmt_mutex);
+
        kfree(tgt);
 
        TRACE_EXIT_RES(res);
@@ -2031,7 +2036,6 @@ static void q2t_host_action(scsi_qla_host_t *ha,
        struct q2t_tgt *tgt = NULL;
        unsigned long flags = 0;
 
-
        TRACE_ENTRY();
 
        sBUG_ON(ha == NULL);
@@ -2076,6 +2080,8 @@ static void q2t_host_action(scsi_qla_host_t *ha,
                        goto out;
                }
 
+               mutex_lock(&qla_mgmt_mutex);
+
                tgt->scst_tgt = scst_register(&tgt_template, wwn);
                kfree(wwn);
                if (!tgt->scst_tgt) {
@@ -2083,7 +2089,7 @@ static void q2t_host_action(scsi_qla_host_t *ha,
                                    "failed for host %ld(%p)", ha->host_no,
                                    ha->host_no, ha);
                        kfree(tgt);
-                       goto out;
+                       goto out_unlock;
                }
 
                scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize);
@@ -2097,9 +2103,12 @@ static void q2t_host_action(scsi_qla_host_t *ha,
                          ha->host_no, ha->host_no, ha);
                tgt_data.enable_lun(ha);
 
+               mutex_unlock(&qla_mgmt_mutex);
                break;
        }
        case DISABLE_TARGET_MODE:
+               mutex_lock(&qla_mgmt_mutex);
+
                spin_lock_irqsave(&ha->hardware_lock, flags);
                if (ha->tgt == NULL) {
                        /* ensure target mode is marked as off */
@@ -2109,13 +2118,15 @@ static void q2t_host_action(scsi_qla_host_t *ha,
                        if (!ha->flags.host_shutting_down)
                                tgt_data.disable_lun(ha);
 
-                       goto out;
+                       goto out_unlock;
                }
 
                tgt = ha->tgt;
                ha->tgt = NULL; /* ensure no one gets in behind us */
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+               mutex_unlock(&qla_mgmt_mutex);
+
                TRACE_DBG("Shutting down host %ld(%ld,%p)",
                          ha->host_no, ha->host_no, ha);
                scst_unregister(tgt->scst_tgt);
@@ -2134,6 +2145,10 @@ static void q2t_host_action(scsi_qla_host_t *ha,
 out:
        TRACE_EXIT();
        return;
+
+out_unlock:
+       mutex_unlock(&qla_mgmt_mutex);
+       goto out;
 }
 
 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)