aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c73
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7552dd8a88f3..91cb1fd523f0 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -741,7 +741,6 @@ static int
741iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) 741iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
742{ 742{
743 int rc = 0, opcode, ahslen; 743 int rc = 0, opcode, ahslen;
744 struct iscsi_session *session = conn->session;
745 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 744 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
746 struct iscsi_task *task; 745 struct iscsi_task *task;
747 746
@@ -770,17 +769,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
770 769
771 switch(opcode) { 770 switch(opcode) {
772 case ISCSI_OP_SCSI_DATA_IN: 771 case ISCSI_OP_SCSI_DATA_IN:
772 spin_lock(&conn->session->lock);
773 task = iscsi_itt_to_ctask(conn, hdr->itt); 773 task = iscsi_itt_to_ctask(conn, hdr->itt);
774 if (!task) 774 if (!task)
775 return ISCSI_ERR_BAD_ITT; 775 rc = ISCSI_ERR_BAD_ITT;
776 if (!task->sc) 776 else
777 return ISCSI_ERR_NO_SCSI_CMD; 777 rc = iscsi_data_rsp(conn, task);
778 if (rc) {
779 spin_unlock(&conn->session->lock);
780 break;
781 }
778 782
779 spin_lock(&conn->session->lock);
780 rc = iscsi_data_rsp(conn, task);
781 spin_unlock(&conn->session->lock);
782 if (rc)
783 return rc;
784 if (tcp_conn->in.datalen) { 783 if (tcp_conn->in.datalen) {
785 struct iscsi_tcp_task *tcp_task = task->dd_data; 784 struct iscsi_tcp_task *tcp_task = task->dd_data;
786 struct hash_desc *rx_hash = NULL; 785 struct hash_desc *rx_hash = NULL;
@@ -801,15 +800,19 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
801 "datalen=%d)\n", tcp_conn, 800 "datalen=%d)\n", tcp_conn,
802 tcp_task->data_offset, 801 tcp_task->data_offset,
803 tcp_conn->in.datalen); 802 tcp_conn->in.datalen);
804 return iscsi_segment_seek_sg(&tcp_conn->in.segment, 803 rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
805 sdb->table.sgl, 804 sdb->table.sgl,
806 sdb->table.nents, 805 sdb->table.nents,
807 tcp_task->data_offset, 806 tcp_task->data_offset,
808 tcp_conn->in.datalen, 807 tcp_conn->in.datalen,
809 iscsi_tcp_process_data_in, 808 iscsi_tcp_process_data_in,
810 rx_hash); 809 rx_hash);
810 spin_unlock(&conn->session->lock);
811 return rc;
811 } 812 }
812 /* fall through */ 813 rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
814 spin_unlock(&conn->session->lock);
815 break;
813 case ISCSI_OP_SCSI_CMD_RSP: 816 case ISCSI_OP_SCSI_CMD_RSP:
814 if (tcp_conn->in.datalen) { 817 if (tcp_conn->in.datalen) {
815 iscsi_tcp_data_recv_prep(tcp_conn); 818 iscsi_tcp_data_recv_prep(tcp_conn);
@@ -818,20 +821,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
818 rc = iscsi_complete_pdu(conn, hdr, NULL, 0); 821 rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
819 break; 822 break;
820 case ISCSI_OP_R2T: 823 case ISCSI_OP_R2T:
824 spin_lock(&conn->session->lock);
821 task = iscsi_itt_to_ctask(conn, hdr->itt); 825 task = iscsi_itt_to_ctask(conn, hdr->itt);
822 if (!task) 826 if (!task)
823 return ISCSI_ERR_BAD_ITT; 827 rc = ISCSI_ERR_BAD_ITT;
824 if (!task->sc) 828 else if (ahslen)
825 return ISCSI_ERR_NO_SCSI_CMD;
826
827 if (ahslen)
828 rc = ISCSI_ERR_AHSLEN; 829 rc = ISCSI_ERR_AHSLEN;
829 else if (task->sc->sc_data_direction == DMA_TO_DEVICE) { 830 else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
830 spin_lock(&session->lock);
831 rc = iscsi_r2t_rsp(conn, task); 831 rc = iscsi_r2t_rsp(conn, task);
832 spin_unlock(&session->lock); 832 else
833 } else
834 rc = ISCSI_ERR_PROTO; 833 rc = ISCSI_ERR_PROTO;
834 spin_unlock(&conn->session->lock);
835 break; 835 break;
836 case ISCSI_OP_LOGIN_RSP: 836 case ISCSI_OP_LOGIN_RSP:
837 case ISCSI_OP_TEXT_RSP: 837 case ISCSI_OP_TEXT_RSP:
@@ -1553,7 +1553,6 @@ iscsi_tcp_release_conn(struct iscsi_conn *conn)
1553 1553
1554 spin_lock_bh(&session->lock); 1554 spin_lock_bh(&session->lock);
1555 tcp_conn->sock = NULL; 1555 tcp_conn->sock = NULL;
1556 conn->recv_lock = NULL;
1557 spin_unlock_bh(&session->lock); 1556 spin_unlock_bh(&session->lock);
1558 sockfd_put(sock); 1557 sockfd_put(sock);
1559} 1558}
@@ -1578,6 +1577,19 @@ static void
1578iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) 1577iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
1579{ 1578{
1580 struct iscsi_conn *conn = cls_conn->dd_data; 1579 struct iscsi_conn *conn = cls_conn->dd_data;
1580 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1581
1582 /* userspace may have goofed up and not bound us */
1583 if (!tcp_conn->sock)
1584 return;
1585 /*
1586 * Make sure our recv side is stopped.
1587 * Older tools called conn stop before ep_disconnect
1588 * so IO could still be coming in.
1589 */
1590 write_lock_bh(&tcp_conn->sock->sk->sk_callback_lock);
1591 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
1592 write_unlock_bh(&tcp_conn->sock->sk->sk_callback_lock);
1581 1593
1582 iscsi_conn_stop(cls_conn, flag); 1594 iscsi_conn_stop(cls_conn, flag);
1583 iscsi_tcp_release_conn(conn); 1595 iscsi_tcp_release_conn(conn);
@@ -1671,13 +1683,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
1671 sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ 1683 sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
1672 sk->sk_allocation = GFP_ATOMIC; 1684 sk->sk_allocation = GFP_ATOMIC;
1673 1685
1674 /* FIXME: disable Nagle's algorithm */
1675
1676 /*
1677 * Intercept TCP callbacks for sendfile like receive
1678 * processing.
1679 */
1680 conn->recv_lock = &sk->sk_callback_lock;
1681 iscsi_conn_set_callbacks(conn); 1686 iscsi_conn_set_callbacks(conn);
1682 tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; 1687 tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
1683 /* 1688 /*