aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0beb4c620962..0d7914fd8ef3 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -37,6 +37,9 @@
37#include <scsi/scsi_transport_iscsi.h> 37#include <scsi/scsi_transport_iscsi.h>
38#include <scsi/libiscsi.h> 38#include <scsi/libiscsi.h>
39 39
40static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
41 int err);
42
40struct iscsi_session * 43struct iscsi_session *
41class_to_transport_session(struct iscsi_cls_session *cls_session) 44class_to_transport_session(struct iscsi_cls_session *cls_session)
42{ 45{
@@ -122,6 +125,20 @@ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
122} 125}
123EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); 126EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
124 127
128static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
129{
130 unsigned exp_len = ctask->hdr_len + len;
131
132 if (exp_len > ctask->hdr_max) {
133 WARN_ON(1);
134 return -EINVAL;
135 }
136
137 WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */
138 ctask->hdr_len = exp_len;
139 return 0;
140}
141
125/** 142/**
126 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu 143 * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
127 * @ctask: iscsi cmd task 144 * @ctask: iscsi cmd task
@@ -129,13 +146,19 @@ EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
129 * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set 146 * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
130 * fields like dlength or final based on how much data it sends 147 * fields like dlength or final based on how much data it sends
131 */ 148 */
132static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) 149static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
133{ 150{
134 struct iscsi_conn *conn = ctask->conn; 151 struct iscsi_conn *conn = ctask->conn;
135 struct iscsi_session *session = conn->session; 152 struct iscsi_session *session = conn->session;
136 struct iscsi_cmd *hdr = ctask->hdr; 153 struct iscsi_cmd *hdr = ctask->hdr;
137 struct scsi_cmnd *sc = ctask->sc; 154 struct scsi_cmnd *sc = ctask->sc;
155 unsigned hdrlength;
156 int rc;
138 157
158 ctask->hdr_len = 0;
159 rc = iscsi_add_hdr(ctask, sizeof(*hdr));
160 if (rc)
161 return rc;
139 hdr->opcode = ISCSI_OP_SCSI_CMD; 162 hdr->opcode = ISCSI_OP_SCSI_CMD;
140 hdr->flags = ISCSI_ATTR_SIMPLE; 163 hdr->flags = ISCSI_ATTR_SIMPLE;
141 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); 164 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
@@ -199,6 +222,15 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
199 hdr->flags |= ISCSI_FLAG_CMD_READ; 222 hdr->flags |= ISCSI_FLAG_CMD_READ;
200 } 223 }
201 224
225 /* calculate size of additional header segments (AHSs) */
226 hdrlength = ctask->hdr_len - sizeof(*hdr);
227
228 WARN_ON(hdrlength & (ISCSI_PAD_LEN-1));
229 hdrlength /= ISCSI_PAD_LEN;
230
231 WARN_ON(hdrlength >= 256);
232 hdr->hlength = hdrlength & 0xFF;
233
202 conn->scsicmd_pdus_cnt++; 234 conn->scsicmd_pdus_cnt++;
203 235
204 debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " 236 debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
@@ -206,6 +238,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
206 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", 238 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
207 conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc), 239 conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
208 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); 240 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
241 return 0;
209} 242}
210 243
211/** 244/**
@@ -744,7 +777,10 @@ check_mgmt:
744 777
745 conn->ctask = list_entry(conn->xmitqueue.next, 778 conn->ctask = list_entry(conn->xmitqueue.next,
746 struct iscsi_cmd_task, running); 779 struct iscsi_cmd_task, running);
747 iscsi_prep_scsi_cmd_pdu(conn->ctask); 780 if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
781 fail_command(conn, conn->ctask, DID_ABORT << 16);
782 continue;
783 }
748 conn->session->tt->init_cmd_task(conn->ctask); 784 conn->session->tt->init_cmd_task(conn->ctask);
749 conn->ctask->state = ISCSI_TASK_RUNNING; 785 conn->ctask->state = ISCSI_TASK_RUNNING;
750 list_move_tail(conn->xmitqueue.next, &conn->run_list); 786 list_move_tail(conn->xmitqueue.next, &conn->run_list);
@@ -1534,6 +1570,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
1534 if (cmd_task_size) 1570 if (cmd_task_size)
1535 ctask->dd_data = &ctask[1]; 1571 ctask->dd_data = &ctask[1];
1536 ctask->itt = cmd_i; 1572 ctask->itt = cmd_i;
1573 ctask->hdr_max = sizeof(struct iscsi_cmd);
1537 INIT_LIST_HEAD(&ctask->running); 1574 INIT_LIST_HEAD(&ctask->running);
1538 } 1575 }
1539 1576