diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:18 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:22 -0400 |
commit | 913e5bf435617aa529919a4f7567f849f9f35f9f (patch) | |
tree | db7357d78d7d6f20358d61bf88a8137ad044a5a5 /drivers/scsi/iscsi_tcp.c | |
parent | 3cf7b233ffc45d4fc381221f74d24f10e692c4ea (diff) |
[SCSI] libiscsi, iser, tcp: remove recv_lock
The recv lock was defined so the iscsi layer could block
the recv path from processing IO during recovery. It
turns out iser just set a lock to that pointer which was pointless.
We now disconnect the transport connection before doing recovery
so we do not need the recv lock. For iscsi_tcp we still stop
the recv path incase older tools are being used.
This patch also has iscsi_itt_to_ctask user grab the session lock
and has the caller access the task with the lock or get a ref
to it in case the target is broken and sends a tmf success response
then sends data or a response for the command that was supposed to
be affected bty the tmf.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 73 |
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 | |||
741 | iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 741 | iscsi_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 | |||
1578 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | 1577 | iscsi_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 | /* |