aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c78
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}
579EXPORT_SYMBOL_GPL(iscsi_conn_failure); 579EXPORT_SYMBOL_GPL(iscsi_conn_failure);
580 580
581static 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) {
953failed: 976failed:
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.