diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 69 |
1 files changed, 33 insertions, 36 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c542d0e95e68..2865ebd557ef 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*))) { |
@@ -1377,7 +1400,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
1377 | } | 1400 | } |
1378 | 1401 | ||
1379 | spin_lock_init(&session->lock); | 1402 | spin_lock_init(&session->lock); |
1380 | INIT_LIST_HEAD(&session->connections); | ||
1381 | 1403 | ||
1382 | /* initialize immediate command pool */ | 1404 | /* initialize immediate command pool */ |
1383 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, | 1405 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, |
@@ -1580,16 +1602,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1580 | kfree(conn->persistent_address); | 1602 | kfree(conn->persistent_address); |
1581 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1603 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
1582 | sizeof(void*)); | 1604 | sizeof(void*)); |
1583 | list_del(&conn->item); | 1605 | if (session->leadconn == conn) { |
1584 | if (list_empty(&session->connections)) | ||
1585 | session->leadconn = NULL; | 1606 | 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 */ | 1607 | /* no connections exits.. reset sequencing */ |
1592 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; | 1608 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; |
1609 | } | ||
1593 | spin_unlock_bh(&session->lock); | 1610 | spin_unlock_bh(&session->lock); |
1594 | 1611 | ||
1595 | kfifo_free(conn->immqueue); | 1612 | kfifo_free(conn->immqueue); |
@@ -1777,32 +1794,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
1777 | struct iscsi_cls_conn *cls_conn, int is_leading) | 1794 | struct iscsi_cls_conn *cls_conn, int is_leading) |
1778 | { | 1795 | { |
1779 | struct iscsi_session *session = class_to_transport_session(cls_session); | 1796 | struct iscsi_session *session = class_to_transport_session(cls_session); |
1780 | struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; | 1797 | struct iscsi_conn *conn = cls_conn->dd_data; |
1781 | 1798 | ||
1782 | /* lookup for existing connection */ | ||
1783 | spin_lock_bh(&session->lock); | 1799 | 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) | 1800 | if (is_leading) |
1805 | session->leadconn = conn; | 1801 | session->leadconn = conn; |
1802 | spin_unlock_bh(&session->lock); | ||
1806 | 1803 | ||
1807 | /* | 1804 | /* |
1808 | * Unblock xmitworker(), Login Phase will pass through. | 1805 | * Unblock xmitworker(), Login Phase will pass through. |