Commit 64b29a13 authored by Andreas Herrmann's avatar Andreas Herrmann Committed by James Bottomley

[SCSI] zfcp: fix: problem in send_els_handler when D_ID assignment changes

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: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 516a4201
...@@ -751,6 +751,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); ...@@ -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 * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
* @adapter: adapter where request is sent from * @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 * @d_id: destiniation id of port where request is sent to
* @req: scatter-gather list for request * @req: scatter-gather list for request
* @resp: scatter-gather list for response * @resp: scatter-gather list for response
...@@ -765,6 +766,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); ...@@ -765,6 +766,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
*/ */
struct zfcp_send_els { struct zfcp_send_els {
struct zfcp_adapter *adapter; struct zfcp_adapter *adapter;
struct zfcp_port *port;
fc_id_t d_id; fc_id_t d_id;
struct scatterlist *req; struct scatterlist *req;
struct scatterlist *resp; struct scatterlist *resp;
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "zfcp_ext.h" #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 void zfcp_erp_adisc_handler(unsigned long);
static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); 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) ...@@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
/** /**
* zfcp_erp_adisc - send ADISC ELS command * zfcp_erp_adisc - send ADISC ELS command
* @adapter: adapter structure * @port: port structure
* @d_id: d_id of port where ADISC is sent to
*/ */
int 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_send_els *send_els;
struct zfcp_ls_adisc *adisc; struct zfcp_ls_adisc *adisc;
void *address = NULL; void *address = NULL;
...@@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) ...@@ -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->req_count = send_els->resp_count = 1;
send_els->adapter = adapter; 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 = zfcp_erp_adisc_handler;
send_els->handler_data = (unsigned long) send_els; send_els->handler_data = (unsigned long) send_els;
...@@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) ...@@ -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 " ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
"(wwpn=0x%016Lx, wwnn=0x%016Lx, " "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
"hard_nport_id=0x%08x, nport_id=0x%08x)\n", "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, (wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id); adisc->nport_id);
...@@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) ...@@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
retval = zfcp_fsf_send_els(send_els); retval = zfcp_fsf_send_els(send_els);
if (retval != 0) { if (retval != 0) {
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " 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)); zfcp_get_busid_by_adapter(adapter));
del_timer(send_els->timer); del_timer(send_els->timer);
goto freemem; goto freemem;
...@@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data) ...@@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data)
del_timer(send_els->timer); del_timer(send_els->timer);
adapter = send_els->adapter; adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id; 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 */ /* request rejected or timed out */
if (send_els->status != 0) { if (send_els->status != 0) {
ZFCP_LOG_NORMAL("ELS request rejected/timed out, " ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
...@@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port) ...@@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port)
int retval; int retval;
zfcp_port_get(port); zfcp_port_get(port);
retval = zfcp_erp_adisc(port->adapter, port->d_id); retval = zfcp_erp_adisc(port);
if (retval != 0) { if (retval != 0) {
zfcp_port_put(port); zfcp_port_put(port);
ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
......
...@@ -1771,8 +1771,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) ...@@ -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) static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
{ {
struct zfcp_adapter *adapter; struct zfcp_adapter *adapter;
fc_id_t d_id;
struct zfcp_port *port; struct zfcp_port *port;
fc_id_t d_id;
struct fsf_qtcb_header *header; struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom; struct fsf_qtcb_bottom_support *bottom;
struct zfcp_send_els *send_els; struct zfcp_send_els *send_els;
...@@ -1781,6 +1781,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1781,6 +1781,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
send_els = fsf_req->data.send_els; send_els = fsf_req->data.send_els;
adapter = send_els->adapter; adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id; d_id = send_els->d_id;
header = &fsf_req->qtcb->header; header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support; bottom = &fsf_req->qtcb->bottom.support;
...@@ -1817,13 +1818,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1817,13 +1818,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status_qual.word[0]){ switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
if (send_els->ls_code != ZFCP_LS_ADISC) { if (port && (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); zfcp_test_link(port);
read_unlock(&zfcp_data.config_lock);
}
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
...@@ -1913,11 +1909,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ...@@ -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"); 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) if (port != NULL)
zfcp_erp_port_access_denied(port); zfcp_erp_port_access_denied(port);
read_unlock(&zfcp_data.config_lock);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment