diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-08-31 18:09:24 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-02 14:37:04 -0400 |
commit | ffd0436ed2e5a741c8d30062b489b989acf0a526 (patch) | |
tree | 037433a76a116c67d3f074c5a83305be8241a8e5 /drivers/scsi/libiscsi.c | |
parent | e5b3cd42960a10c1bc3701d4f00767463c88ec9d (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/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 25 |
1 files changed, 17 insertions, 8 deletions
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) | |||
68 | EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); | 68 | EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); |
69 | 69 | ||
70 | void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, | 70 | void 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; |