diff options
author | Martin Petermann <martin.petermann@de.ibm.com> | 2009-05-15 07:18:19 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-05-23 16:44:15 -0400 |
commit | a17c5855643afa7838f542cbd0a1ed9a73968cef (patch) | |
tree | fec68adb1041443f15dc36cca8ed32ae18170af2 /drivers/s390 | |
parent | dceab655d9f7d99881c2033c8ff4e1c7b444e104 (diff) |
[SCSI] zfcp: Increase ref counter for port open requests
In rare cases, open port request might timeout, erp calls
zfcp_port_put, port gets dequeued. Now, the late returning (or
dismissed) fsf-port-open calls the fsf_port_open_handler that tries to
reference the port data structure leading to a kernel oops.
Signed-off-by: Martin Petermann <martin.petermann@de.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b550c249389d..6fae2688fede 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -1402,7 +1402,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1402 | struct fsf_plogi *plogi; | 1402 | struct fsf_plogi *plogi; |
1403 | 1403 | ||
1404 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1404 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1405 | return; | 1405 | goto out; |
1406 | 1406 | ||
1407 | switch (header->fsf_status) { | 1407 | switch (header->fsf_status) { |
1408 | case FSF_PORT_ALREADY_OPEN: | 1408 | case FSF_PORT_ALREADY_OPEN: |
@@ -1464,6 +1464,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1464 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1464 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
1465 | break; | 1465 | break; |
1466 | } | 1466 | } |
1467 | |||
1468 | out: | ||
1469 | zfcp_port_put(port); | ||
1467 | } | 1470 | } |
1468 | 1471 | ||
1469 | /** | 1472 | /** |
@@ -1476,6 +1479,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1476 | struct qdio_buffer_element *sbale; | 1479 | struct qdio_buffer_element *sbale; |
1477 | struct zfcp_adapter *adapter = erp_action->adapter; | 1480 | struct zfcp_adapter *adapter = erp_action->adapter; |
1478 | struct zfcp_fsf_req *req; | 1481 | struct zfcp_fsf_req *req; |
1482 | struct zfcp_port *port = erp_action->port; | ||
1479 | int retval = -EIO; | 1483 | int retval = -EIO; |
1480 | 1484 | ||
1481 | spin_lock_bh(&adapter->req_q_lock); | 1485 | spin_lock_bh(&adapter->req_q_lock); |
@@ -1496,16 +1500,18 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1496 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1500 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1497 | 1501 | ||
1498 | req->handler = zfcp_fsf_open_port_handler; | 1502 | req->handler = zfcp_fsf_open_port_handler; |
1499 | req->qtcb->bottom.support.d_id = erp_action->port->d_id; | 1503 | req->qtcb->bottom.support.d_id = port->d_id; |
1500 | req->data = erp_action->port; | 1504 | req->data = port; |
1501 | req->erp_action = erp_action; | 1505 | req->erp_action = erp_action; |
1502 | erp_action->fsf_req = req; | 1506 | erp_action->fsf_req = req; |
1507 | zfcp_port_get(port); | ||
1503 | 1508 | ||
1504 | zfcp_fsf_start_erp_timer(req); | 1509 | zfcp_fsf_start_erp_timer(req); |
1505 | retval = zfcp_fsf_req_send(req); | 1510 | retval = zfcp_fsf_req_send(req); |
1506 | if (retval) { | 1511 | if (retval) { |
1507 | zfcp_fsf_req_free(req); | 1512 | zfcp_fsf_req_free(req); |
1508 | erp_action->fsf_req = NULL; | 1513 | erp_action->fsf_req = NULL; |
1514 | zfcp_port_put(port); | ||
1509 | } | 1515 | } |
1510 | out: | 1516 | out: |
1511 | spin_unlock_bh(&adapter->req_q_lock); | 1517 | spin_unlock_bh(&adapter->req_q_lock); |