[SCSI] zfcp: fix: problem in send_els_handler when D_ID assignment changes
authorAndreas Herrmann <aherrman@de.ibm.com>
Mon, 13 Jun 2005 11:18:56 +0000 (13:18 +0200)
committerJames Bottomley <jejb@mulgrave.(none)>
Tue, 14 Jun 2005 02:30:05 +0000 (21:30 -0500)
From: Maxim Shchetynin <maxim@de.ibm.com>

Fixes a bug in zfcp_send_els_handler.  If D_ID assignments for ports
are changing between initiation of one ELS request and its completion
the wrong port might be accessed in the completion for that ELS
request. Thus a pointer to the port has to be passed for ELS requests
to identify the port structure if required.

Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c

index 08369b9dad683981e3d83bb0b0d5b862b6318274..37982058e4d967f341879f14f04b2326154497b6 100644 (file)
@@ -751,6 +751,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
 /**
  * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
  * @adapter: adapter where request is sent from
+ * @port: port where ELS is destinated (port reference count has to be increased)
  * @d_id: destiniation id of port where request is sent to
  * @req: scatter-gather list for request
  * @resp: scatter-gather list for response
@@ -765,6 +766,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
  */
 struct zfcp_send_els {
        struct zfcp_adapter *adapter;
+       struct zfcp_port *port;
        fc_id_t d_id;
        struct scatterlist *req;
        struct scatterlist *resp;
index 60ba1ba112d60423a9c80ea22684397e76e8d6d0..41c67e1ec4f785e7cf57a7bf9c70c5d776ebd33c 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "zfcp_ext.h"
 
-static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t);
+static int zfcp_erp_adisc(struct zfcp_port *);
 static void zfcp_erp_adisc_handler(unsigned long);
 
 static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
@@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
 
 /**
  * zfcp_erp_adisc - send ADISC ELS command
- * @adapter: adapter structure
- * @d_id: d_id of port where ADISC is sent to
+ * @port: port structure
  */
 int
-zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
+zfcp_erp_adisc(struct zfcp_port *port)
 {
+       struct zfcp_adapter *adapter = port->adapter;
        struct zfcp_send_els *send_els;
        struct zfcp_ls_adisc *adisc;
        void *address = NULL;
@@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
        send_els->req_count = send_els->resp_count = 1;
 
        send_els->adapter = adapter;
-       send_els->d_id = d_id;
+       send_els->port = port;
+       send_els->d_id = port->d_id;
        send_els->handler = zfcp_erp_adisc_handler;
        send_els->handler_data = (unsigned long) send_els;
 
@@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
        ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
                      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
                      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-                     adapter->s_id, d_id, (wwn_t) adisc->wwpn,
+                     adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
                      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
                      adisc->nport_id);
 
@@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
        retval = zfcp_fsf_send_els(send_els);
        if (retval != 0) {
                ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
-                               "0x%08x on adapter %s\n", d_id,
+                               "0x%08x on adapter %s\n", send_els->d_id,
                                zfcp_get_busid_by_adapter(adapter));
                del_timer(send_els->timer);
                goto freemem;
@@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data)
        del_timer(send_els->timer);
 
        adapter = send_els->adapter;
+       port = send_els->port;
        d_id = send_els->d_id;
 
-       read_lock(&zfcp_data.config_lock);
-       port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id);
-       read_unlock(&zfcp_data.config_lock);
-
-       BUG_ON(port == NULL);
-
        /* request rejected or timed out */
        if (send_els->status != 0) {
                ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
@@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port)
        int retval;
 
        zfcp_port_get(port);
-       retval = zfcp_erp_adisc(port->adapter, port->d_id);
+       retval = zfcp_erp_adisc(port);
        if (retval != 0) {
                zfcp_port_put(port);
                ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
index bf66fc6d8a97d458f0bf7c58bf8e4cec491ec1c5..21a6d7633475712a85f51f8127778dd3f5d671c1 100644 (file)
@@ -1771,8 +1771,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
 static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter;
-       fc_id_t d_id;
        struct zfcp_port *port;
+       fc_id_t d_id;
        struct fsf_qtcb_header *header;
        struct fsf_qtcb_bottom_support *bottom;
        struct zfcp_send_els *send_els;
@@ -1781,6 +1781,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 
        send_els = fsf_req->data.send_els;
        adapter = send_els->adapter;
+       port = send_els->port;
        d_id = send_els->d_id;
        header = &fsf_req->qtcb->header;
        bottom = &fsf_req->qtcb->bottom.support;
@@ -1817,13 +1818,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                switch (header->fsf_status_qual.word[0]){
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
-                       if (send_els->ls_code != ZFCP_LS_ADISC) {
-                               read_lock(&zfcp_data.config_lock);
-                               port = zfcp_get_port_by_did(adapter, d_id);
-                               if (port)
-                                       zfcp_test_link(port);
-                               read_unlock(&zfcp_data.config_lock);
-                       }
+                       if (port && (send_els->ls_code != ZFCP_LS_ADISC))
+                               zfcp_test_link(port);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
@@ -1913,11 +1909,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                        }
                }
                debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
-               read_lock(&zfcp_data.config_lock);
-               port = zfcp_get_port_by_did(adapter, d_id);
                if (port != NULL)
                        zfcp_erp_port_access_denied(port);
-               read_unlock(&zfcp_data.config_lock);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;