Fix for long standing protection problem in the initiator driver
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 24 Jul 2008 09:04:05 +0000 (09:04 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 24 Jul 2008 09:04:05 +0000 (09:04 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@474 d57e44dd-8a1f-0410-8b47-8ef2f437770f

qla2x00t/qla2x00-target/qla2x00t.c
qla2x00t/qla_attr.c
qla2x00t/qla_def.h
qla2x00t/qla_init.c
qla2x00t/qla_mid.c
qla2x00t/qla_os.c

index 3e0e78d..b08c66b 100644 (file)
@@ -1315,7 +1315,7 @@ static char *q2t_find_name(scsi_qla_host_t *ha, int loop_id)
        }
 
        /* Find the WWN in the port db given the loop_id */
-       list_for_each_entry(fcl, &ha->fcports, list) {
+       list_for_each_entry_rcu(fcl, &ha->fcports, list) {
            if (loop_id == (fcl->loop_id & 0xFF)) {
                sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
                        fcl->port_name[0], fcl->port_name[1],
index c1b5e9c..0b40584 100644 (file)
@@ -240,8 +240,8 @@ out_free:
                        id_iter += ha->gid_list_info_size;
                }
        }
-get_id_failed:
 
+get_id_failed:
        if (size < max_size) {
                fc_port_t *fcport;
                char * state;
@@ -250,7 +250,7 @@ get_id_failed:
                size += scnprintf(buf+size, max_size-size,
                                 "\nfc_ports database\n");
 
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                        if (size >= max_size)
                                goto out;
                        switch (atomic_read(&fcport->state)) {
@@ -1237,7 +1237,7 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
        fc_port_t *fcport;
        u64 node_name = 0;
 
-       list_for_each_entry(fcport, &ha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                if (fcport->rport &&
                    starget->id == fcport->rport->scsi_target_id) {
                        node_name = wwn_to_u64(fcport->node_name);
@@ -1256,7 +1256,7 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
        fc_port_t *fcport;
        u64 port_name = 0;
 
-       list_for_each_entry(fcport, &ha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                if (fcport->rport &&
                    starget->id == fcport->rport->scsi_target_id) {
                        port_name = wwn_to_u64(fcport->port_name);
@@ -1275,7 +1275,7 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
        fc_port_t *fcport;
        uint32_t port_id = ~0U;
 
-       list_for_each_entry(fcport, &ha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                if (fcport->rport &&
                    starget->id == fcport->rport->scsi_target_id) {
                        port_id = fcport->d_id.b.domain << 16 |
index 4ae216d..1a1c676 100644 (file)
@@ -2407,7 +2407,14 @@ typedef struct scsi_qla_host {
 
        struct list_head        work_list;
 
-       /* Fibre Channel Device List. */
+       /*
+        * Fibre Channel Device List.
+        *
+        * This list can be accessed from many contexts, including concurrently.
+        * So, although anything never deleted from this list, it needs the
+        * corresponding protection anyway. Let's do it by making access to
+        * it using RCU functions.
+        */
        struct list_head        fcports;
 
        /* RSCN queue. */
index fdd699b..7f262bc 100644 (file)
@@ -2107,7 +2107,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
        /*
         * Mark local devices that were present with FCF_DEVICE_LOST for now.
         */
-       list_for_each_entry(fcport, &pha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                if (fcport->vp_idx != ha->vp_idx)
                        continue;
 
@@ -2172,7 +2172,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
                /* Check for matching device in port list. */
                found = 0;
                fcport = NULL;
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (fcport->vp_idx != ha->vp_idx)
                                continue;
 
@@ -2201,7 +2201,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
                                list_add_tail(&new_fcport->vp_fcport,
                                    &ha->vp_fcports);
                        }
-                       list_add_tail(&new_fcport->list, &pha->fcports);
+                       list_add_tail_rcu(&new_fcport->list, &pha->fcports);
 
                        /* Allocate a new replacement fcport. */
                        fcport = new_fcport;
@@ -2441,7 +2441,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
                 * Logout all previous fabric devices marked lost, except
                 * tape devices.
                 */
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (fcport->vp_idx !=ha->vp_idx)
                                continue;
 
@@ -2475,7 +2475,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
                 * Scan through our port list and login entries that need to be
                 * logged in.
                 */
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (fcport->vp_idx != ha->vp_idx)
                                continue;
 
@@ -2530,10 +2530,13 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
                                fcport->vp_idx = ha->vp_idx;
                                list_add_tail(&fcport->vp_fcport,
                                    &ha->vp_fcports);
-                               list_move_tail(&fcport->list,
+                               list_del(&fcport->list);
+                               list_add_tail_rcu(&fcport->list,
                                    &ha->parent->fcports);
-                       } else
-                               list_move_tail(&fcport->list, &ha->fcports);
+                       } else {
+                               list_del(&fcport->list);
+                               list_add_tail_rcu(&fcport->list, &ha->fcports);
+                       }
                }
        } while (0);
 
@@ -2716,7 +2719,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
 
                /* Locate matching device in database. */
                found = 0;
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (new_fcport->vp_idx != fcport->vp_idx)
                                continue;
                        if (memcmp(new_fcport->port_name, fcport->port_name,
@@ -2846,7 +2849,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev)
                /* Check for loop ID being already in use. */
                found = 0;
                fcport = NULL;
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (fcport->loop_id == dev->loop_id && fcport != dev) {
                                /* ID possibly in use */
                                found++;
@@ -2960,7 +2963,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
 
                rval = QLA_SUCCESS;
 
-               list_for_each_entry(fcport, &pha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                        if (fcport->vp_idx != ha->vp_idx)
                                continue;
 
@@ -3255,7 +3258,7 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
        fc_port_t *fcport;
 
        /* Go with deferred removal of rport references. */
-       list_for_each_entry(fcport, &ha->fcports, list)
+       list_for_each_entry_rcu(fcport, &ha->fcports, list)
                if (fcport->drport)
                        qla2x00_rport_del(fcport);
 }
index 62a3ad6..0fd28ac 100644 (file)
@@ -95,7 +95,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
        fc_port_t *fcport;
        scsi_qla_host_t *pha = to_qla_parent(vha);
 
-       list_for_each_entry(fcport, &pha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                if (fcport->vp_idx != vha->vp_idx)
                        continue;
 
index a7eecf6..11df40e 100644 (file)
@@ -1007,7 +1007,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
        }
 
        if (ha->flags.enable_target_reset) {
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                        if (fcport->port_type != FCT_TARGET)
                                continue;
 
@@ -1919,7 +1919,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
        fc_port_t *fcport;
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
-       list_for_each_entry(fcport, &pha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &pha->fcports, list) {
                if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
                        continue;
                /*
@@ -2352,7 +2352,7 @@ qla2x00_do_dpc(void *data)
                            ha->host_no));
 
                        next_loopid = 0;
-                       list_for_each_entry(fcport, &ha->fcports, list) {
+                       list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                                /*
                                 * If the port is not ONLINE then try to login
                                 * to it if we haven't run out of retries.
@@ -2528,7 +2528,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
         * the port it marked DEAD.
         */
        t = 0;
-       list_for_each_entry(fcport, &ha->fcports, list) {
+       list_for_each_entry_rcu(fcport, &ha->fcports, list) {
                if (fcport->port_type != FCT_TARGET)
                        continue;