[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>
This commit is contained in:
parent
1548271ece
commit
dbdb016d92
2 changed files with 43 additions and 19 deletions
|
@ -896,11 +896,27 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
|
if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV &&
|
||||||
|
tcp_conn->in.copy) {
|
||||||
uint32_t recv_digest;
|
uint32_t recv_digest;
|
||||||
|
|
||||||
debug_tcp("extra data_recv offset %d copy %d\n",
|
debug_tcp("extra data_recv offset %d copy %d\n",
|
||||||
tcp_conn->in.offset, tcp_conn->in.copy);
|
tcp_conn->in.offset, tcp_conn->in.copy);
|
||||||
|
|
||||||
|
if (!tcp_conn->data_copied) {
|
||||||
|
if (tcp_conn->in.padding) {
|
||||||
|
debug_tcp("padding -> %d\n",
|
||||||
|
tcp_conn->in.padding);
|
||||||
|
memset(pad, 0, tcp_conn->in.padding);
|
||||||
|
sg_init_one(&sg, pad, tcp_conn->in.padding);
|
||||||
|
crypto_hash_update(&tcp_conn->rx_hash,
|
||||||
|
&sg, sg.length);
|
||||||
|
}
|
||||||
|
crypto_hash_final(&tcp_conn->rx_hash,
|
||||||
|
(u8 *) &tcp_conn->in.datadgst);
|
||||||
|
debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
|
||||||
|
}
|
||||||
|
|
||||||
rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
|
rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc == -EAGAIN)
|
if (rc == -EAGAIN)
|
||||||
|
@ -925,8 +941,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
|
if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
|
||||||
tcp_conn->in.copy) {
|
tcp_conn->in.copy) {
|
||||||
|
|
||||||
debug_tcp("data_recv offset %d copy %d\n",
|
debug_tcp("data_recv offset %d copy %d\n",
|
||||||
tcp_conn->in.offset, tcp_conn->in.copy);
|
tcp_conn->in.offset, tcp_conn->in.copy);
|
||||||
|
|
||||||
|
@ -937,24 +952,32 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
|
||||||
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tcp_conn->in.copy -= tcp_conn->in.padding;
|
|
||||||
tcp_conn->in.offset += tcp_conn->in.padding;
|
if (tcp_conn->in.padding)
|
||||||
if (conn->datadgst_en) {
|
tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
|
||||||
if (tcp_conn->in.padding) {
|
else if (conn->datadgst_en)
|
||||||
debug_tcp("padding -> %d\n",
|
|
||||||
tcp_conn->in.padding);
|
|
||||||
memset(pad, 0, tcp_conn->in.padding);
|
|
||||||
sg_init_one(&sg, pad, tcp_conn->in.padding);
|
|
||||||
crypto_hash_update(&tcp_conn->rx_hash,
|
|
||||||
&sg, sg.length);
|
|
||||||
}
|
|
||||||
crypto_hash_final(&tcp_conn->rx_hash,
|
|
||||||
(u8 *) &tcp_conn->in.datadgst);
|
|
||||||
debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
|
|
||||||
tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
|
tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
|
||||||
tcp_conn->data_copied = 0;
|
else
|
||||||
} else
|
|
||||||
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
|
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
|
||||||
|
tcp_conn->data_copied = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV &&
|
||||||
|
tcp_conn->in.copy) {
|
||||||
|
int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied,
|
||||||
|
tcp_conn->in.copy);
|
||||||
|
|
||||||
|
tcp_conn->in.copy -= copylen;
|
||||||
|
tcp_conn->in.offset += copylen;
|
||||||
|
tcp_conn->data_copied += copylen;
|
||||||
|
|
||||||
|
if (tcp_conn->data_copied != tcp_conn->in.padding)
|
||||||
|
tcp_conn->in_progress = IN_PROGRESS_PAD_RECV;
|
||||||
|
else if (conn->datadgst_en)
|
||||||
|
tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
|
||||||
|
else
|
||||||
|
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
|
||||||
|
tcp_conn->data_copied = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_tcp("f, processed %d from out of %d padding %d\n",
|
debug_tcp("f, processed %d from out of %d padding %d\n",
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#define IN_PROGRESS_HEADER_GATHER 0x1
|
#define IN_PROGRESS_HEADER_GATHER 0x1
|
||||||
#define IN_PROGRESS_DATA_RECV 0x2
|
#define IN_PROGRESS_DATA_RECV 0x2
|
||||||
#define IN_PROGRESS_DDIGEST_RECV 0x3
|
#define IN_PROGRESS_DDIGEST_RECV 0x3
|
||||||
|
#define IN_PROGRESS_PAD_RECV 0x4
|
||||||
|
|
||||||
/* xmit state machine */
|
/* xmit state machine */
|
||||||
#define XMSTATE_IDLE 0x0
|
#define XMSTATE_IDLE 0x0
|
||||||
|
|
Loading…
Add table
Reference in a new issue