aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-08-31 18:09:24 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-02 14:37:04 -0400
commitffd0436ed2e5a741c8d30062b489b989acf0a526 (patch)
tree037433a76a116c67d3f074c5a83305be8241a8e5
parente5b3cd42960a10c1bc3701d4f00767463c88ec9d (diff)
[SCSI] libiscsi, iscsi_tcp, iscsi_iser: check that burst lengths are valid.
iSCSI RFC states that the first burst length must be smaller than the max burst length. We currently assume targets will be good, but that may not be the case, so this patch adds a check. This patch also moves the unsol data out offset to the lib so the LLDs do not have to track it. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c18
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h1
-rw-r--r--drivers/scsi/iscsi_tcp.c30
-rw-r--r--drivers/scsi/iscsi_tcp.h1
-rw-r--r--drivers/scsi/libiscsi.c25
-rw-r--r--include/scsi/libiscsi.h5
6 files changed, 31 insertions, 49 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 1437d7ee3b19..101e407eaa43 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -141,18 +141,11 @@ iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
141 141
142 if (sc->sc_data_direction == DMA_TO_DEVICE) { 142 if (sc->sc_data_direction == DMA_TO_DEVICE) {
143 BUG_ON(ctask->total_length == 0); 143 BUG_ON(ctask->total_length == 0);
144 /* bytes to be sent via RDMA operations */
145 iser_ctask->rdma_data_count = ctask->total_length -
146 ctask->imm_count -
147 ctask->unsol_count;
148 144
149 debug_scsi("cmd [itt %x total %d imm %d unsol_data %d " 145 debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
150 "rdma_data %d]\n",
151 ctask->itt, ctask->total_length, ctask->imm_count, 146 ctask->itt, ctask->total_length, ctask->imm_count,
152 ctask->unsol_count, iser_ctask->rdma_data_count); 147 ctask->unsol_count);
153 } else 148 }
154 /* bytes to be sent via RDMA operations */
155 iser_ctask->rdma_data_count = ctask->total_length;
156 149
157 iser_ctask_rdma_init(iser_ctask); 150 iser_ctask_rdma_init(iser_ctask);
158} 151}
@@ -196,13 +189,10 @@ iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
196{ 189{
197 struct iscsi_data hdr; 190 struct iscsi_data hdr;
198 int error = 0; 191 int error = 0;
199 struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
200 192
201 /* Send data-out PDUs while there's still unsolicited data to send */ 193 /* Send data-out PDUs while there's still unsolicited data to send */
202 while (ctask->unsol_count > 0) { 194 while (ctask->unsol_count > 0) {
203 iscsi_prep_unsolicit_data_pdu(ctask, &hdr, 195 iscsi_prep_unsolicit_data_pdu(ctask, &hdr);
204 iser_ctask->rdma_data_count);
205
206 debug_scsi("Sending data-out: itt 0x%x, data count %d\n", 196 debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
207 hdr.itt, ctask->data_count); 197 hdr.itt, ctask->data_count);
208 198
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 3350ba690cfe..7c3d0c96d889 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -257,7 +257,6 @@ struct iscsi_iser_conn {
257struct iscsi_iser_cmd_task { 257struct iscsi_iser_cmd_task {
258 struct iser_desc desc; 258 struct iser_desc desc;
259 struct iscsi_iser_conn *iser_conn; 259 struct iscsi_iser_conn *iser_conn;
260 int rdma_data_count;/* RDMA bytes */
261 enum iser_task_status status; 260 enum iser_task_status status;
262 int command_sent; /* set if command sent */ 261 int command_sent; /* set if command sent */
263 int dir[ISER_DIRS_NUM]; /* set if dir use*/ 262 int dir[ISER_DIRS_NUM]; /* set if dir use*/
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 058f094f945a..a97a3a4e99eb 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1264,19 +1264,6 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1264 r2t->data_count); 1264 r2t->data_count);
1265} 1265}
1266 1266
1267static void
1268iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1269{
1270 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1271 struct iscsi_data_task *dtask;
1272
1273 dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
1274 iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
1275 tcp_ctask->r2t_data_count);
1276 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
1277 sizeof(struct iscsi_hdr));
1278}
1279
1280/** 1267/**
1281 * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands 1268 * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
1282 * @conn: iscsi connection 1269 * @conn: iscsi connection
@@ -1326,14 +1313,11 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
1326 if (ctask->unsol_count) 1313 if (ctask->unsol_count)
1327 tcp_ctask->xmstate |= XMSTATE_UNS_HDR | 1314 tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
1328 XMSTATE_UNS_INIT; 1315 XMSTATE_UNS_INIT;
1329 tcp_ctask->r2t_data_count = ctask->total_length -
1330 ctask->imm_count -
1331 ctask->unsol_count;
1332 1316
1333 debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d " 1317 debug_scsi("cmd [itt 0x%x total %d imm_data %d "
1334 "r2t_data %d]\n", 1318 "unsol count %d, unsol offset %d]\n",
1335 ctask->itt, ctask->total_length, ctask->imm_count, 1319 ctask->itt, ctask->total_length, ctask->imm_count,
1336 ctask->unsol_count, tcp_ctask->r2t_data_count); 1320 ctask->unsol_count, ctask->unsol_offset);
1337 } else 1321 } else
1338 tcp_ctask->xmstate = XMSTATE_R_HDR; 1322 tcp_ctask->xmstate = XMSTATE_R_HDR;
1339 1323
@@ -1531,8 +1515,10 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1531 1515
1532 tcp_ctask->xmstate |= XMSTATE_UNS_DATA; 1516 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1533 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { 1517 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
1534 iscsi_unsolicit_data_init(conn, ctask); 1518 dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
1535 dtask = tcp_ctask->dtask; 1519 iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr);
1520 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
1521 sizeof(struct iscsi_hdr));
1536 if (conn->hdrdgst_en) 1522 if (conn->hdrdgst_en)
1537 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1523 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1538 (u8*)dtask->hdrext); 1524 (u8*)dtask->hdrext);
@@ -1720,7 +1706,6 @@ data_out_done:
1720 * Done with this R2T. Check if there are more 1706 * Done with this R2T. Check if there are more
1721 * outstanding R2Ts ready to be processed. 1707 * outstanding R2Ts ready to be processed.
1722 */ 1708 */
1723 BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
1724 if (conn->datadgst_en) { 1709 if (conn->datadgst_en) {
1725 rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, 1710 rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
1726 &dtask->digest, 1); 1711 &dtask->digest, 1);
@@ -1732,7 +1717,6 @@ data_out_done:
1732 debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); 1717 debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
1733 } 1718 }
1734 1719
1735 tcp_ctask->r2t_data_count -= r2t->data_length;
1736 tcp_ctask->r2t = NULL; 1720 tcp_ctask->r2t = NULL;
1737 spin_lock_bh(&session->lock); 1721 spin_lock_bh(&session->lock);
1738 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); 1722 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 6a4ee704e46e..aace8f70dfd7 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -157,7 +157,6 @@ struct iscsi_tcp_cmd_task {
157 struct scatterlist *bad_sg; /* assert statement */ 157 struct scatterlist *bad_sg; /* assert statement */
158 int sg_count; /* SG's to process */ 158 int sg_count; /* SG's to process */
159 uint32_t exp_r2tsn; 159 uint32_t exp_r2tsn;
160 int r2t_data_count; /* R2T Data-Out bytes */
161 int data_offset; 160 int data_offset;
162 struct iscsi_r2t_info *r2t; /* in progress R2T */ 161 struct iscsi_r2t_info *r2t; /* in progress R2T */
163 struct iscsi_queue r2tpool; 162 struct iscsi_queue r2tpool;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5884cd26d53a..a7c6e70f4ef8 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -68,8 +68,7 @@ iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
68EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); 68EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
69 69
70void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, 70void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
71 struct iscsi_data *hdr, 71 struct iscsi_data *hdr)
72 int transport_data_cnt)
73{ 72{
74 struct iscsi_conn *conn = ctask->conn; 73 struct iscsi_conn *conn = ctask->conn;
75 74
@@ -82,14 +81,12 @@ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
82 81
83 hdr->itt = ctask->hdr->itt; 82 hdr->itt = ctask->hdr->itt;
84 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); 83 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
85 84 hdr->offset = cpu_to_be32(ctask->unsol_offset);
86 hdr->offset = cpu_to_be32(ctask->total_length -
87 transport_data_cnt -
88 ctask->unsol_count);
89 85
90 if (ctask->unsol_count > conn->max_xmit_dlength) { 86 if (ctask->unsol_count > conn->max_xmit_dlength) {
91 hton24(hdr->dlength, conn->max_xmit_dlength); 87 hton24(hdr->dlength, conn->max_xmit_dlength);
92 ctask->data_count = conn->max_xmit_dlength; 88 ctask->data_count = conn->max_xmit_dlength;
89 ctask->unsol_offset += ctask->data_count;
93 hdr->flags = 0; 90 hdr->flags = 0;
94 } else { 91 } else {
95 hton24(hdr->dlength, ctask->unsol_count); 92 hton24(hdr->dlength, ctask->unsol_count);
@@ -125,6 +122,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
125 memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); 122 memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
126 memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); 123 memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
127 124
125 ctask->data_count = 0;
128 if (sc->sc_data_direction == DMA_TO_DEVICE) { 126 if (sc->sc_data_direction == DMA_TO_DEVICE) {
129 hdr->flags |= ISCSI_FLAG_CMD_WRITE; 127 hdr->flags |= ISCSI_FLAG_CMD_WRITE;
130 /* 128 /*
@@ -143,6 +141,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
143 */ 141 */
144 ctask->imm_count = 0; 142 ctask->imm_count = 0;
145 ctask->unsol_count = 0; 143 ctask->unsol_count = 0;
144 ctask->unsol_offset = 0;
146 ctask->unsol_datasn = 0; 145 ctask->unsol_datasn = 0;
147 146
148 if (session->imm_data_en) { 147 if (session->imm_data_en) {
@@ -156,9 +155,12 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
156 } else 155 } else
157 zero_data(ctask->hdr->dlength); 156 zero_data(ctask->hdr->dlength);
158 157
159 if (!session->initial_r2t_en) 158 if (!session->initial_r2t_en) {
160 ctask->unsol_count = min(session->first_burst, 159 ctask->unsol_count = min(session->first_burst,
161 ctask->total_length) - ctask->imm_count; 160 ctask->total_length) - ctask->imm_count;
161 ctask->unsol_offset = ctask->imm_count;
162 }
163
162 if (!ctask->unsol_count) 164 if (!ctask->unsol_count)
163 /* No unsolicit Data-Out's */ 165 /* No unsolicit Data-Out's */
164 ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; 166 ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
@@ -1520,11 +1522,18 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
1520 struct iscsi_conn *conn = cls_conn->dd_data; 1522 struct iscsi_conn *conn = cls_conn->dd_data;
1521 struct iscsi_session *session = conn->session; 1523 struct iscsi_session *session = conn->session;
1522 1524
1523 if (session == NULL) { 1525 if (!session) {
1524 printk(KERN_ERR "iscsi: can't start unbound connection\n"); 1526 printk(KERN_ERR "iscsi: can't start unbound connection\n");
1525 return -EPERM; 1527 return -EPERM;
1526 } 1528 }
1527 1529
1530 if (session->first_burst > session->max_burst) {
1531 printk("iscsi: invalid burst lengths: "
1532 "first_burst %d max_burst %d\n",
1533 session->first_burst, session->max_burst);
1534 return -EINVAL;
1535 }
1536
1528 spin_lock_bh(&session->lock); 1537 spin_lock_bh(&session->lock);
1529 conn->c_stage = ISCSI_CONN_STARTED; 1538 conn->c_stage = ISCSI_CONN_STARTED;
1530 session->state = ISCSI_STATE_LOGGED_IN; 1539 session->state = ISCSI_STATE_LOGGED_IN;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 41904f611d12..4900650bd081 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -102,6 +102,8 @@ struct iscsi_cmd_task {
102 uint32_t unsol_datasn; 102 uint32_t unsol_datasn;
103 int imm_count; /* imm-data (bytes) */ 103 int imm_count; /* imm-data (bytes) */
104 int unsol_count; /* unsolicited (bytes)*/ 104 int unsol_count; /* unsolicited (bytes)*/
105 /* offset in unsolicited stream (bytes); */
106 int unsol_offset;
105 int data_count; /* remaining Data-Out */ 107 int data_count; /* remaining Data-Out */
106 struct scsi_cmnd *sc; /* associated SCSI cmd*/ 108 struct scsi_cmnd *sc; /* associated SCSI cmd*/
107 int total_length; 109 int total_length;
@@ -290,8 +292,7 @@ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
290extern int iscsi_check_assign_cmdsn(struct iscsi_session *, 292extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
291 struct iscsi_nopin *); 293 struct iscsi_nopin *);
292extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *, 294extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
293 struct iscsi_data *hdr, 295 struct iscsi_data *hdr);
294 int transport_data_cnt);
295extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, 296extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
296 char *, uint32_t); 297 char *, uint32_t);
297extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, 298extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,