diff options
| author | Andreas Herrmann <aherrman@de.ibm.com> | 2005-06-13 07:18:56 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.(none)> | 2005-06-13 22:30:05 -0400 |
| commit | 64b29a130901d5b8578e9f602cf2dae56aaff224 (patch) | |
| tree | fb543d8a7c007416d99128246d4e71580ecd94ff | |
| parent | 516a4201bacfd61ea957039d6f47276ee9c32a0d (diff) | |
[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: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
| -rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 2 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 24 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 15 |
3 files changed, 16 insertions, 25 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 08369b9dad68..37982058e4d9 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
| @@ -751,6 +751,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); | |||
| 751 | /** | 751 | /** |
| 752 | * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els | 752 | * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els |
| 753 | * @adapter: adapter where request is sent from | 753 | * @adapter: adapter where request is sent from |
| 754 | * @port: port where ELS is destinated (port reference count has to be increased) | ||
| 754 | * @d_id: destiniation id of port where request is sent to | 755 | * @d_id: destiniation id of port where request is sent to |
| 755 | * @req: scatter-gather list for request | 756 | * @req: scatter-gather list for request |
| 756 | * @resp: scatter-gather list for response | 757 | * @resp: scatter-gather list for response |
| @@ -765,6 +766,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); | |||
| 765 | */ | 766 | */ |
| 766 | struct zfcp_send_els { | 767 | struct zfcp_send_els { |
| 767 | struct zfcp_adapter *adapter; | 768 | struct zfcp_adapter *adapter; |
| 769 | struct zfcp_port *port; | ||
| 768 | fc_id_t d_id; | 770 | fc_id_t d_id; |
| 769 | struct scatterlist *req; | 771 | struct scatterlist *req; |
| 770 | struct scatterlist *resp; | 772 | struct scatterlist *resp; |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 60ba1ba112d6..41c67e1ec4f7 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include "zfcp_ext.h" | 36 | #include "zfcp_ext.h" |
| 37 | 37 | ||
| 38 | static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t); | 38 | static int zfcp_erp_adisc(struct zfcp_port *); |
| 39 | static void zfcp_erp_adisc_handler(unsigned long); | 39 | static void zfcp_erp_adisc_handler(unsigned long); |
| 40 | 40 | ||
| 41 | static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); | 41 | 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 | 295 | ||
| 296 | /** | 296 | /** |
| 297 | * zfcp_erp_adisc - send ADISC ELS command | 297 | * zfcp_erp_adisc - send ADISC ELS command |
| 298 | * @adapter: adapter structure | 298 | * @port: port structure |
| 299 | * @d_id: d_id of port where ADISC is sent to | ||
| 300 | */ | 299 | */ |
| 301 | int | 300 | int |
| 302 | zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) | 301 | zfcp_erp_adisc(struct zfcp_port *port) |
| 303 | { | 302 | { |
| 303 | struct zfcp_adapter *adapter = port->adapter; | ||
| 304 | struct zfcp_send_els *send_els; | 304 | struct zfcp_send_els *send_els; |
| 305 | struct zfcp_ls_adisc *adisc; | 305 | struct zfcp_ls_adisc *adisc; |
| 306 | void *address = NULL; | 306 | void *address = NULL; |
| @@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) | |||
| 332 | send_els->req_count = send_els->resp_count = 1; | 332 | send_els->req_count = send_els->resp_count = 1; |
| 333 | 333 | ||
| 334 | send_els->adapter = adapter; | 334 | send_els->adapter = adapter; |
| 335 | send_els->d_id = d_id; | 335 | send_els->port = port; |
| 336 | send_els->d_id = port->d_id; | ||
| 336 | send_els->handler = zfcp_erp_adisc_handler; | 337 | send_els->handler = zfcp_erp_adisc_handler; |
| 337 | send_els->handler_data = (unsigned long) send_els; | 338 | send_els->handler_data = (unsigned long) send_els; |
| 338 | 339 | ||
| @@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) | |||
| 350 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " | 351 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " |
| 351 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " | 352 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " |
| 352 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", | 353 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", |
| 353 | adapter->s_id, d_id, (wwn_t) adisc->wwpn, | 354 | adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn, |
| 354 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, | 355 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, |
| 355 | adisc->nport_id); | 356 | adisc->nport_id); |
| 356 | 357 | ||
| @@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) | |||
| 367 | retval = zfcp_fsf_send_els(send_els); | 368 | retval = zfcp_fsf_send_els(send_els); |
| 368 | if (retval != 0) { | 369 | if (retval != 0) { |
| 369 | ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " | 370 | ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " |
| 370 | "0x%08x on adapter %s\n", d_id, | 371 | "0x%08x on adapter %s\n", send_els->d_id, |
| 371 | zfcp_get_busid_by_adapter(adapter)); | 372 | zfcp_get_busid_by_adapter(adapter)); |
| 372 | del_timer(send_els->timer); | 373 | del_timer(send_els->timer); |
| 373 | goto freemem; | 374 | goto freemem; |
| @@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data) | |||
| 411 | del_timer(send_els->timer); | 412 | del_timer(send_els->timer); |
| 412 | 413 | ||
| 413 | adapter = send_els->adapter; | 414 | adapter = send_els->adapter; |
| 415 | port = send_els->port; | ||
| 414 | d_id = send_els->d_id; | 416 | d_id = send_els->d_id; |
| 415 | 417 | ||
| 416 | read_lock(&zfcp_data.config_lock); | ||
| 417 | port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id); | ||
| 418 | read_unlock(&zfcp_data.config_lock); | ||
| 419 | |||
| 420 | BUG_ON(port == NULL); | ||
| 421 | |||
| 422 | /* request rejected or timed out */ | 418 | /* request rejected or timed out */ |
| 423 | if (send_els->status != 0) { | 419 | if (send_els->status != 0) { |
| 424 | ZFCP_LOG_NORMAL("ELS request rejected/timed out, " | 420 | ZFCP_LOG_NORMAL("ELS request rejected/timed out, " |
| @@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port) | |||
| 482 | int retval; | 478 | int retval; |
| 483 | 479 | ||
| 484 | zfcp_port_get(port); | 480 | zfcp_port_get(port); |
| 485 | retval = zfcp_erp_adisc(port->adapter, port->d_id); | 481 | retval = zfcp_erp_adisc(port); |
| 486 | if (retval != 0) { | 482 | if (retval != 0) { |
| 487 | zfcp_port_put(port); | 483 | zfcp_port_put(port); |
| 488 | ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " | 484 | ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index bf66fc6d8a97..21a6d7633475 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -1771,8 +1771,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
| 1771 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | 1771 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) |
| 1772 | { | 1772 | { |
| 1773 | struct zfcp_adapter *adapter; | 1773 | struct zfcp_adapter *adapter; |
| 1774 | fc_id_t d_id; | ||
| 1775 | struct zfcp_port *port; | 1774 | struct zfcp_port *port; |
| 1775 | fc_id_t d_id; | ||
| 1776 | struct fsf_qtcb_header *header; | 1776 | struct fsf_qtcb_header *header; |
| 1777 | struct fsf_qtcb_bottom_support *bottom; | 1777 | struct fsf_qtcb_bottom_support *bottom; |
| 1778 | struct zfcp_send_els *send_els; | 1778 | struct zfcp_send_els *send_els; |
| @@ -1781,6 +1781,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | |||
| 1781 | 1781 | ||
| 1782 | send_els = fsf_req->data.send_els; | 1782 | send_els = fsf_req->data.send_els; |
| 1783 | adapter = send_els->adapter; | 1783 | adapter = send_els->adapter; |
| 1784 | port = send_els->port; | ||
| 1784 | d_id = send_els->d_id; | 1785 | d_id = send_els->d_id; |
| 1785 | header = &fsf_req->qtcb->header; | 1786 | header = &fsf_req->qtcb->header; |
| 1786 | bottom = &fsf_req->qtcb->bottom.support; | 1787 | bottom = &fsf_req->qtcb->bottom.support; |
| @@ -1817,13 +1818,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | |||
| 1817 | switch (header->fsf_status_qual.word[0]){ | 1818 | switch (header->fsf_status_qual.word[0]){ |
| 1818 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1819 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
| 1819 | debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); | 1820 | debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); |
| 1820 | if (send_els->ls_code != ZFCP_LS_ADISC) { | 1821 | if (port && (send_els->ls_code != ZFCP_LS_ADISC)) |
| 1821 | read_lock(&zfcp_data.config_lock); | 1822 | zfcp_test_link(port); |
| 1822 | port = zfcp_get_port_by_did(adapter, d_id); | ||
| 1823 | if (port) | ||
| 1824 | zfcp_test_link(port); | ||
| 1825 | read_unlock(&zfcp_data.config_lock); | ||
| 1826 | } | ||
| 1827 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1823 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
| 1828 | break; | 1824 | break; |
| 1829 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1825 | 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 | } | 1909 | } |
| 1914 | } | 1910 | } |
| 1915 | debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); | 1911 | debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); |
| 1916 | read_lock(&zfcp_data.config_lock); | ||
| 1917 | port = zfcp_get_port_by_did(adapter, d_id); | ||
| 1918 | if (port != NULL) | 1912 | if (port != NULL) |
| 1919 | zfcp_erp_port_access_denied(port); | 1913 | zfcp_erp_port_access_denied(port); |
| 1920 | read_unlock(&zfcp_data.config_lock); | ||
| 1921 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1914 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
| 1922 | break; | 1915 | break; |
| 1923 | 1916 | ||
