aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-05-30 13:57:20 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-02 15:35:10 -0400
commitdbdb016d92603619d972082167c10b8c74e605cc (patch)
treed100bfe35f17f5fa8bc5be3e0f1a8feb9b0434b4
parent1548271ece9e9312fd5feb41fd58773b56a71d39 (diff)
[SCSI] iscsi_tcp: fix handling of data buffer padding
If we got the padding, data and header in different skbs, we were not handling the padding correctly because we attributed it to the data's skb. This resulted in the initiator reading from pad bytes + skb offset instead of the correct offset. If you could not connect with the open solaris target, this will fix the lock up problem you were hitting. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/iscsi_tcp.c61
-rw-r--r--drivers/scsi/iscsi_tcp.h1
2 files changed, 43 insertions, 19 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index eca4d611dd49..6eaa2e3a9252 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -896,11 +896,27 @@ more:
896 } 896 }
897 } 897 }
898 898
899 if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { 899 if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
900 tcp_conn->in.copy) {
900 uint32_t recv_digest; 901 uint32_t recv_digest;
901 902
902 debug_tcp("extra data_recv offset %d copy %d\n", 903 debug_tcp("extra data_recv offset %d copy %d\n",
903 tcp_conn->in.offset, tcp_conn->in.copy); 904 tcp_conn->in.offset, tcp_conn->in.copy);
905
906 if (!tcp_conn->data_copied) {
907 if (tcp_conn->in.padding) {
908 debug_tcp("padding -> %d\n",
909 tcp_conn->in.padding);
910 memset(pad, 0, tcp_conn->in.padding);
911 sg_init_one(&sg, pad, tcp_conn->in.padding);
912 crypto_hash_update(&tcp_conn->rx_hash,
913 &sg, sg.length);
914 }
915 crypto_hash_final(&tcp_conn->rx_hash,
916 (u8 *) &tcp_conn->in.datadgst);
917 debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
918 }
919
904 rc = iscsi_tcp_copy(conn, sizeof(uint32_t)); 920 rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
905 if (rc) { 921 if (rc) {
906 if (rc == -EAGAIN) 922 if (rc == -EAGAIN)
@@ -925,8 +941,7 @@ more:
925 } 941 }
926 942
927 if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV && 943 if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
928 tcp_conn->in.copy) { 944 tcp_conn->in.copy) {
929
930 debug_tcp("data_recv offset %d copy %d\n", 945 debug_tcp("data_recv offset %d copy %d\n",
931 tcp_conn->in.offset, tcp_conn->in.copy); 946 tcp_conn->in.offset, tcp_conn->in.copy);
932 947
@@ -937,24 +952,32 @@ more:
937 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 952 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
938 return 0; 953 return 0;
939 } 954 }
940 tcp_conn->in.copy -= tcp_conn->in.padding; 955
941 tcp_conn->in.offset += tcp_conn->in.padding; 956 if (tcp_conn->in.padding)
942 if (conn->datadgst_en) { 957 tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
943 if (tcp_conn->in.padding) { 958 else if (conn->datadgst_en)
944 debug_tcp("padding -> %d\n",
945 tcp_conn->in.padding);
946 memset(pad, 0, tcp_conn->in.padding);
947 sg_init_one(&sg, pad, tcp_conn->in.padding);
948 crypto_hash_update(&tcp_conn->rx_hash,
949 &sg, sg.length);
950 }
951 crypto_hash_final(&tcp_conn->rx_hash,
952 (u8 *) &tcp_conn->in.datadgst);
953 debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
954 tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; 959 tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
955 tcp_conn->data_copied = 0; 960 else
956 } else 961 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
962 tcp_conn->data_copied = 0;
963 }
964
965 if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
966 tcp_conn->in.copy) {
967 int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
968 tcp_conn->in.copy);
969
970 tcp_conn->in.copy -= copylen;
971 tcp_conn->in.offset += copylen;
972 tcp_conn->data_copied += copylen;
973
974 if (tcp_conn->data_copied != tcp_conn->in.padding)
975 tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
976 else if (conn->datadgst_en)
977 tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
978 else
957 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; 979 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
980 tcp_conn->data_copied = 0;
958 } 981 }
959 982
960 debug_tcp("f, processed %d from out of %d padding %d\n", 983 debug_tcp("f, processed %d from out of %d padding %d\n",
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index b039160ebafd..7eba44df0a7f 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -29,6 +29,7 @@
29#define IN_PROGRESS_HEADER_GATHER 0x1 29#define IN_PROGRESS_HEADER_GATHER 0x1
30#define IN_PROGRESS_DATA_RECV 0x2 30#define IN_PROGRESS_DATA_RECV 0x2
31#define IN_PROGRESS_DDIGEST_RECV 0x3 31#define IN_PROGRESS_DDIGEST_RECV 0x3
32#define IN_PROGRESS_PAD_RECV 0x4
32 33
33/* xmit state machine */ 34/* xmit state machine */
34#define XMSTATE_IDLE 0x0 35#define XMSTATE_IDLE 0x0