aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
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 /drivers/scsi
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c30
-rw-r--r--drivers/scsi/iscsi_tcp.h1
-rw-r--r--drivers/scsi/libiscsi.c25
3 files changed, 24 insertions, 32 deletions
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;