diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
| -rw-r--r-- | drivers/scsi/libiscsi.c | 78 |
1 files changed, 38 insertions, 40 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c542d0e95e68..5d8862189485 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -481,8 +481,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 481 | break; | 481 | break; |
| 482 | case ISCSI_OP_ASYNC_EVENT: | 482 | case ISCSI_OP_ASYNC_EVENT: |
| 483 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 483 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
| 484 | /* we need sth like iscsi_async_event_rsp() */ | 484 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
| 485 | rc = ISCSI_ERR_BAD_OPCODE; | 485 | rc = ISCSI_ERR_CONN_FAILED; |
| 486 | break; | 486 | break; |
| 487 | default: | 487 | default: |
| 488 | rc = ISCSI_ERR_BAD_OPCODE; | 488 | rc = ISCSI_ERR_BAD_OPCODE; |
| @@ -578,6 +578,27 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | |||
| 578 | } | 578 | } |
| 579 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); | 579 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); |
| 580 | 580 | ||
| 581 | static int iscsi_xmit_imm_task(struct iscsi_conn *conn) | ||
| 582 | { | ||
| 583 | struct iscsi_hdr *hdr = conn->mtask->hdr; | ||
| 584 | int rc, was_logout = 0; | ||
| 585 | |||
| 586 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) { | ||
| 587 | conn->session->state = ISCSI_STATE_IN_RECOVERY; | ||
| 588 | iscsi_block_session(session_to_cls(conn->session)); | ||
| 589 | was_logout = 1; | ||
| 590 | } | ||
| 591 | rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); | ||
| 592 | if (rc) | ||
| 593 | return rc; | ||
| 594 | |||
| 595 | if (was_logout) { | ||
| 596 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
| 597 | return -ENODATA; | ||
| 598 | } | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 581 | /** | 602 | /** |
| 582 | * iscsi_data_xmit - xmit any command into the scheduled connection | 603 | * iscsi_data_xmit - xmit any command into the scheduled connection |
| 583 | * @conn: iscsi connection | 604 | * @conn: iscsi connection |
| @@ -623,7 +644,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
| 623 | conn->ctask = NULL; | 644 | conn->ctask = NULL; |
| 624 | } | 645 | } |
| 625 | if (conn->mtask) { | 646 | if (conn->mtask) { |
| 626 | rc = tt->xmit_mgmt_task(conn, conn->mtask); | 647 | rc = iscsi_xmit_imm_task(conn); |
| 627 | if (rc) | 648 | if (rc) |
| 628 | goto again; | 649 | goto again; |
| 629 | /* done with this in-progress mtask */ | 650 | /* done with this in-progress mtask */ |
| @@ -638,7 +659,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
| 638 | list_add_tail(&conn->mtask->running, | 659 | list_add_tail(&conn->mtask->running, |
| 639 | &conn->mgmt_run_list); | 660 | &conn->mgmt_run_list); |
| 640 | spin_unlock_bh(&conn->session->lock); | 661 | spin_unlock_bh(&conn->session->lock); |
| 641 | rc = tt->xmit_mgmt_task(conn, conn->mtask); | 662 | rc = iscsi_xmit_imm_task(conn); |
| 642 | if (rc) | 663 | if (rc) |
| 643 | goto again; | 664 | goto again; |
| 644 | } | 665 | } |
| @@ -661,8 +682,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
| 661 | spin_unlock_bh(&conn->session->lock); | 682 | spin_unlock_bh(&conn->session->lock); |
| 662 | 683 | ||
| 663 | rc = tt->xmit_cmd_task(conn, conn->ctask); | 684 | rc = tt->xmit_cmd_task(conn, conn->ctask); |
| 664 | if (rc) | ||
| 665 | goto again; | ||
| 666 | 685 | ||
| 667 | spin_lock_bh(&conn->session->lock); | 686 | spin_lock_bh(&conn->session->lock); |
| 668 | __iscsi_put_ctask(conn->ctask); | 687 | __iscsi_put_ctask(conn->ctask); |
| @@ -778,6 +797,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 778 | } | 797 | } |
| 779 | 798 | ||
| 780 | conn = session->leadconn; | 799 | conn = session->leadconn; |
| 800 | if (!conn) { | ||
| 801 | reason = FAILURE_SESSION_FREED; | ||
| 802 | goto fault; | ||
| 803 | } | ||
| 781 | 804 | ||
| 782 | if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, | 805 | if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, |
| 783 | sizeof(void*))) { | 806 | sizeof(void*))) { |
| @@ -952,13 +975,13 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) | |||
| 952 | if (session->state == ISCSI_STATE_TERMINATE) { | 975 | if (session->state == ISCSI_STATE_TERMINATE) { |
| 953 | failed: | 976 | failed: |
| 954 | debug_scsi("failing host reset: session terminated " | 977 | debug_scsi("failing host reset: session terminated " |
| 955 | "[CID %d age %d]", conn->id, session->age); | 978 | "[CID %d age %d]\n", conn->id, session->age); |
| 956 | spin_unlock_bh(&session->lock); | 979 | spin_unlock_bh(&session->lock); |
| 957 | return FAILED; | 980 | return FAILED; |
| 958 | } | 981 | } |
| 959 | 982 | ||
| 960 | if (sc->SCp.phase == session->age) { | 983 | if (sc->SCp.phase == session->age) { |
| 961 | debug_scsi("failing connection CID %d due to SCSI host reset", | 984 | debug_scsi("failing connection CID %d due to SCSI host reset\n", |
| 962 | conn->id); | 985 | conn->id); |
| 963 | fail_session = 1; | 986 | fail_session = 1; |
| 964 | } | 987 | } |
| @@ -1031,7 +1054,8 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | |||
| 1031 | NULL, 0); | 1054 | NULL, 0); |
| 1032 | if (rc) { | 1055 | if (rc) { |
| 1033 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1056 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
| 1034 | debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); | 1057 | debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt, |
| 1058 | rc); | ||
| 1035 | return rc; | 1059 | return rc; |
| 1036 | } | 1060 | } |
| 1037 | 1061 | ||
| @@ -1048,7 +1072,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | |||
| 1048 | conn->tmabort_timer.function = iscsi_tmabort_timedout; | 1072 | conn->tmabort_timer.function = iscsi_tmabort_timedout; |
| 1049 | conn->tmabort_timer.data = (unsigned long)ctask; | 1073 | conn->tmabort_timer.data = (unsigned long)ctask; |
| 1050 | add_timer(&conn->tmabort_timer); | 1074 | add_timer(&conn->tmabort_timer); |
| 1051 | debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); | 1075 | debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); |
| 1052 | } | 1076 | } |
| 1053 | spin_unlock_bh(&session->lock); | 1077 | spin_unlock_bh(&session->lock); |
| 1054 | mutex_unlock(&conn->xmitmutex); | 1078 | mutex_unlock(&conn->xmitmutex); |
| @@ -1377,7 +1401,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
| 1377 | } | 1401 | } |
| 1378 | 1402 | ||
| 1379 | spin_lock_init(&session->lock); | 1403 | spin_lock_init(&session->lock); |
| 1380 | INIT_LIST_HEAD(&session->connections); | ||
| 1381 | 1404 | ||
| 1382 | /* initialize immediate command pool */ | 1405 | /* initialize immediate command pool */ |
| 1383 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, | 1406 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, |
| @@ -1580,16 +1603,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
| 1580 | kfree(conn->persistent_address); | 1603 | kfree(conn->persistent_address); |
| 1581 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1604 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
| 1582 | sizeof(void*)); | 1605 | sizeof(void*)); |
| 1583 | list_del(&conn->item); | 1606 | if (session->leadconn == conn) { |
| 1584 | if (list_empty(&session->connections)) | ||
| 1585 | session->leadconn = NULL; | 1607 | session->leadconn = NULL; |
| 1586 | if (session->leadconn && session->leadconn == conn) | ||
| 1587 | session->leadconn = container_of(session->connections.next, | ||
| 1588 | struct iscsi_conn, item); | ||
| 1589 | |||
| 1590 | if (session->leadconn == NULL) | ||
| 1591 | /* no connections exits.. reset sequencing */ | 1608 | /* no connections exits.. reset sequencing */ |
| 1592 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; | 1609 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; |
| 1610 | } | ||
| 1593 | spin_unlock_bh(&session->lock); | 1611 | spin_unlock_bh(&session->lock); |
| 1594 | 1612 | ||
| 1595 | kfifo_free(conn->immqueue); | 1613 | kfifo_free(conn->immqueue); |
| @@ -1777,32 +1795,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
| 1777 | struct iscsi_cls_conn *cls_conn, int is_leading) | 1795 | struct iscsi_cls_conn *cls_conn, int is_leading) |
| 1778 | { | 1796 | { |
| 1779 | struct iscsi_session *session = class_to_transport_session(cls_session); | 1797 | struct iscsi_session *session = class_to_transport_session(cls_session); |
| 1780 | struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; | 1798 | struct iscsi_conn *conn = cls_conn->dd_data; |
| 1781 | 1799 | ||
| 1782 | /* lookup for existing connection */ | ||
| 1783 | spin_lock_bh(&session->lock); | 1800 | spin_lock_bh(&session->lock); |
| 1784 | list_for_each_entry(tmp, &session->connections, item) { | ||
| 1785 | if (tmp == conn) { | ||
| 1786 | if (conn->c_stage != ISCSI_CONN_STOPPED || | ||
| 1787 | conn->stop_stage == STOP_CONN_TERM) { | ||
| 1788 | printk(KERN_ERR "iscsi: can't bind " | ||
| 1789 | "non-stopped connection (%d:%d)\n", | ||
| 1790 | conn->c_stage, conn->stop_stage); | ||
| 1791 | spin_unlock_bh(&session->lock); | ||
| 1792 | return -EIO; | ||
| 1793 | } | ||
| 1794 | break; | ||
| 1795 | } | ||
| 1796 | } | ||
| 1797 | if (tmp != conn) { | ||
| 1798 | /* bind new iSCSI connection to session */ | ||
| 1799 | conn->session = session; | ||
| 1800 | list_add(&conn->item, &session->connections); | ||
| 1801 | } | ||
| 1802 | spin_unlock_bh(&session->lock); | ||
| 1803 | |||
| 1804 | if (is_leading) | 1801 | if (is_leading) |
| 1805 | session->leadconn = conn; | 1802 | session->leadconn = conn; |
| 1803 | spin_unlock_bh(&session->lock); | ||
| 1806 | 1804 | ||
| 1807 | /* | 1805 | /* |
| 1808 | * Unblock xmitworker(), Login Phase will pass through. | 1806 | * Unblock xmitworker(), Login Phase will pass through. |
