]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.fixes/libiscsi-fix-data-corruption
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / libiscsi-fix-data-corruption
CommitLineData
82094b55
AF
1From: Mike Christie <michaelc@cs.wisc.edu>
2Date: Wed, 24 Sep 2008 11:46:09 -0500
3Subject: libiscsi: fix data corruption when target has to resend data-in packets
4References: bnc#472432
5X-Git: 1d9edf0270cb5a434d32e95279ce9493581906b3
6
7iscsi_tcp was updating the exp_statsn (exp_statsn acknowledges
8status and tells the target it is ok to let the resources for
9a iscsi pdu to be reused) before it got all the data for pdu read
10into OS buffers. Data corruption was occuring if something happens
11to a packet and the network layer requests a retransmit, and the
12initiator has told the target about the udpated exp_statsn ack,
13then the target may be sending data from a buffer it has reused
14for a new iscsi pdu. This fixes the problem by having the LLD
15(iscsi_tcp in this case) just handle the transferring of data, and
16has libiscsi handle the processing of status (libiscsi completion
17processing is done after LLD data transfers are complete).
18
19Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
20Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
21Signed-off-by: Hannes Reinecke <hare@suse.de>
22---
23 drivers/scsi/iscsi_tcp.c | 29 +++++------------------------
24 drivers/scsi/libiscsi.c | 41 +++++++++++++++++++++++++++++++++++------
25 2 files changed, 40 insertions(+), 30 deletions(-)
26
27diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
28index 25094c9..babe81a 100644
29--- a/drivers/scsi/iscsi_tcp.c
30+++ b/drivers/scsi/iscsi_tcp.c
31@@ -530,22 +530,20 @@ iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task)
32 EXPORT_SYMBOL_GPL(iscsi_tcp_cleanup_task);
33
34 /**
35- * iscsi_data_rsp - SCSI Data-In Response processing
36+ * iscsi_data_in - SCSI Data-In Response processing
37 * @conn: iscsi connection
38 * @task: scsi command task
39 **/
40 static int
41-iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
42+iscsi_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
43 {
44 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
45 struct iscsi_tcp_task *tcp_task = task->dd_data;
46 struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
47- struct iscsi_session *session = conn->session;
48- struct scsi_cmnd *sc = task->sc;
49 int datasn = be32_to_cpu(rhdr->datasn);
50- unsigned total_in_length = scsi_in(sc)->length;
51+ unsigned total_in_length = scsi_in(task->sc)->length;
52
53- iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
54+ iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
55 if (tcp_conn->in.datalen == 0)
56 return 0;
57
58@@ -565,23 +563,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
59 return ISCSI_ERR_DATA_OFFSET;
60 }
61
62- if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
63- sc->result = (DID_OK << 16) | rhdr->cmd_status;
64- conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
65- if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
66- ISCSI_FLAG_DATA_OVERFLOW)) {
67- int res_count = be32_to_cpu(rhdr->residual_count);
68-
69- if (res_count > 0 &&
70- (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
71- res_count <= total_in_length))
72- scsi_in(sc)->resid = res_count;
73- else
74- sc->result = (DID_BAD_TARGET << 16) |
75- rhdr->cmd_status;
76- }
77- }
78-
79 conn->datain_pdus_cnt++;
80 return 0;
81 }
82@@ -781,7 +762,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
83 if (!task)
84 rc = ISCSI_ERR_BAD_ITT;
85 else
86- rc = iscsi_data_rsp(conn, task);
87+ rc = iscsi_data_in(conn, task);
88 if (rc) {
89 spin_unlock(&conn->session->lock);
90 break;
91diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
92index e7624db..8905895 100644
93--- a/drivers/scsi/libiscsi.c
94+++ b/drivers/scsi/libiscsi.c
95@@ -645,6 +645,40 @@ out:
96 __iscsi_put_task(task);
97 }
98
99+/**
100+ * iscsi_data_in_rsp - SCSI Data-In Response processing
101+ * @conn: iscsi connection
102+ * @hdr: iscsi pdu
103+ * @task: scsi command task
104+ **/
105+static void
106+iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
107+ struct iscsi_task *task)
108+{
109+ struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)hdr;
110+ struct scsi_cmnd *sc = task->sc;
111+
112+ if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
113+ return;
114+
115+ sc->result = (DID_OK << 16) | rhdr->cmd_status;
116+ conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
117+ if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW |
118+ ISCSI_FLAG_DATA_OVERFLOW)) {
119+ int res_count = be32_to_cpu(rhdr->residual_count);
120+
121+ if (res_count > 0 &&
122+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
123+ res_count <= scsi_in(sc)->length))
124+ scsi_in(sc)->resid = res_count;
125+ else
126+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
127+ }
128+
129+ conn->scsirsp_pdus_cnt++;
130+ __iscsi_put_task(task);
131+}
132+
133 static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
134 {
135 struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
136@@ -911,12 +945,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
137 iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen);
138 break;
139 case ISCSI_OP_SCSI_DATA_IN:
140- if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
141- conn->scsirsp_pdus_cnt++;
142- iscsi_update_cmdsn(session,
143- (struct iscsi_nopin*) hdr);
144- __iscsi_put_task(task);
145- }
146+ iscsi_data_in_rsp(conn, hdr, task);
147 break;
148 case ISCSI_OP_LOGOUT_RSP:
149 iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
150--
1511.6.0.2
152