Commit ffd0436ed2e5a741c8d30062b489b989acf0a526

Authored by Mike Christie
Committed by James Bottomley
1 parent e5b3cd4296

[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>

Showing 6 changed files with 31 additions and 49 deletions Side-by-side Diff

drivers/infiniband/ulp/iser/iscsi_iser.c
... ... @@ -141,18 +141,11 @@
141 141  
142 142 if (sc->sc_data_direction == DMA_TO_DEVICE) {
143 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 "
150   - "rdma_data %d]\n",
  145 + debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",
151 146 ctask->itt, ctask->total_length, ctask->imm_count,
152   - ctask->unsol_count, iser_ctask->rdma_data_count);
153   - } else
154   - /* bytes to be sent via RDMA operations */
155   - iser_ctask->rdma_data_count = ctask->total_length;
  147 + ctask->unsol_count);
  148 + }
156 149  
157 150 iser_ctask_rdma_init(iser_ctask);
158 151 }
159 152  
... ... @@ -196,13 +189,10 @@
196 189 {
197 190 struct iscsi_data hdr;
198 191 int error = 0;
199   - struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
200 192  
201 193 /* Send data-out PDUs while there's still unsolicited data to send */
202 194 while (ctask->unsol_count > 0) {
203   - iscsi_prep_unsolicit_data_pdu(ctask, &hdr,
204   - iser_ctask->rdma_data_count);
205   -
  195 + iscsi_prep_unsolicit_data_pdu(ctask, &hdr);
206 196 debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
207 197 hdr.itt, ctask->data_count);
208 198  
drivers/infiniband/ulp/iser/iscsi_iser.h
... ... @@ -257,7 +257,6 @@
257 257 struct iscsi_iser_cmd_task {
258 258 struct iser_desc desc;
259 259 struct iscsi_iser_conn *iser_conn;
260   - int rdma_data_count;/* RDMA bytes */
261 260 enum iser_task_status status;
262 261 int command_sent; /* set if command sent */
263 262 int dir[ISER_DIRS_NUM]; /* set if dir use*/
drivers/scsi/iscsi_tcp.c
... ... @@ -1264,19 +1264,6 @@
1264 1264 r2t->data_count);
1265 1265 }
1266 1266  
1267   -static void
1268   -iscsi_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 1268 * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
1282 1269 * @conn: iscsi connection
1283 1270  
1284 1271  
... ... @@ -1326,14 +1313,11 @@
1326 1313 if (ctask->unsol_count)
1327 1314 tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
1328 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 "
1334   - "r2t_data %d]\n",
  1317 + debug_scsi("cmd [itt 0x%x total %d imm_data %d "
  1318 + "unsol count %d, unsol offset %d]\n",
1335 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 1321 } else
1338 1322 tcp_ctask->xmstate = XMSTATE_R_HDR;
1339 1323  
... ... @@ -1531,8 +1515,10 @@
1531 1515  
1532 1516 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1533 1517 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
1534   - iscsi_unsolicit_data_init(conn, ctask);
1535   - dtask = tcp_ctask->dtask;
  1518 + dtask = tcp_ctask->dtask = &tcp_ctask->unsol_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 1522 if (conn->hdrdgst_en)
1537 1523 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1538 1524 (u8*)dtask->hdrext);
... ... @@ -1720,7 +1706,6 @@
1720 1706 * Done with this R2T. Check if there are more
1721 1707 * outstanding R2Ts ready to be processed.
1722 1708 */
1723   - BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
1724 1709 if (conn->datadgst_en) {
1725 1710 rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
1726 1711 &dtask->digest, 1);
... ... @@ -1732,7 +1717,6 @@
1732 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 1720 tcp_ctask->r2t = NULL;
1737 1721 spin_lock_bh(&session->lock);
1738 1722 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
drivers/scsi/iscsi_tcp.h
... ... @@ -157,7 +157,6 @@
157 157 struct scatterlist *bad_sg; /* assert statement */
158 158 int sg_count; /* SG's to process */
159 159 uint32_t exp_r2tsn;
160   - int r2t_data_count; /* R2T Data-Out bytes */
161 160 int data_offset;
162 161 struct iscsi_r2t_info *r2t; /* in progress R2T */
163 162 struct iscsi_queue r2tpool;
drivers/scsi/libiscsi.c
... ... @@ -68,8 +68,7 @@
68 68 EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
69 69  
70 70 void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
71   - struct iscsi_data *hdr,
72   - int transport_data_cnt)
  71 + struct iscsi_data *hdr)
73 72 {
74 73 struct iscsi_conn *conn = ctask->conn;
75 74  
76 75  
77 76  
... ... @@ -82,14 +81,12 @@
82 81  
83 82 hdr->itt = ctask->hdr->itt;
84 83 hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
  84 + hdr->offset = cpu_to_be32(ctask->unsol_offset);
85 85  
86   - hdr->offset = cpu_to_be32(ctask->total_length -
87   - transport_data_cnt -
88   - ctask->unsol_count);
89   -
90 86 if (ctask->unsol_count > conn->max_xmit_dlength) {
91 87 hton24(hdr->dlength, conn->max_xmit_dlength);
92 88 ctask->data_count = conn->max_xmit_dlength;
  89 + ctask->unsol_offset += ctask->data_count;
93 90 hdr->flags = 0;
94 91 } else {
95 92 hton24(hdr->dlength, ctask->unsol_count);
... ... @@ -125,6 +122,7 @@
125 122 memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
126 123 memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
127 124  
  125 + ctask->data_count = 0;
128 126 if (sc->sc_data_direction == DMA_TO_DEVICE) {
129 127 hdr->flags |= ISCSI_FLAG_CMD_WRITE;
130 128 /*
... ... @@ -143,6 +141,7 @@
143 141 */
144 142 ctask->imm_count = 0;
145 143 ctask->unsol_count = 0;
  144 + ctask->unsol_offset = 0;
146 145 ctask->unsol_datasn = 0;
147 146  
148 147 if (session->imm_data_en) {
149 148  
... ... @@ -156,9 +155,12 @@
156 155 } else
157 156 zero_data(ctask->hdr->dlength);
158 157  
159   - if (!session->initial_r2t_en)
  158 + if (!session->initial_r2t_en) {
160 159 ctask->unsol_count = min(session->first_burst,
161 160 ctask->total_length) - ctask->imm_count;
  161 + ctask->unsol_offset = ctask->imm_count;
  162 + }
  163 +
162 164 if (!ctask->unsol_count)
163 165 /* No unsolicit Data-Out's */
164 166 ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
165 167  
... ... @@ -1520,9 +1522,16 @@
1520 1522 struct iscsi_conn *conn = cls_conn->dd_data;
1521 1523 struct iscsi_session *session = conn->session;
1522 1524  
1523   - if (session == NULL) {
  1525 + if (!session) {
1524 1526 printk(KERN_ERR "iscsi: can't start unbound connection\n");
1525 1527 return -EPERM;
  1528 + }
  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;
1526 1535 }
1527 1536  
1528 1537 spin_lock_bh(&session->lock);
include/scsi/libiscsi.h
... ... @@ -102,6 +102,8 @@
102 102 uint32_t unsol_datasn;
103 103 int imm_count; /* imm-data (bytes) */
104 104 int unsol_count; /* unsolicited (bytes)*/
  105 + /* offset in unsolicited stream (bytes); */
  106 + int unsol_offset;
105 107 int data_count; /* remaining Data-Out */
106 108 struct scsi_cmnd *sc; /* associated SCSI cmd*/
107 109 int total_length;
... ... @@ -290,8 +292,7 @@
290 292 extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
291 293 struct iscsi_nopin *);
292 294 extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
293   - struct iscsi_data *hdr,
294   - int transport_data_cnt);
  295 + struct iscsi_data *hdr);
295 296 extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
296 297 char *, uint32_t);
297 298 extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,