diff options
| -rw-r--r-- | drivers/scsi/iscsi_tcp.c | 16 | ||||
| -rw-r--r-- | drivers/scsi/iscsi_tcp.h | 13 | ||||
| -rw-r--r-- | drivers/scsi/libiscsi.c | 41 | ||||
| -rw-r--r-- | include/scsi/iscsi_proto.h | 10 | ||||
| -rw-r--r-- | include/scsi/libiscsi.h | 33 |
5 files changed, 94 insertions, 19 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index fd88777df28b..491845f18710 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
| @@ -113,7 +113,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
| 113 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 113 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 114 | 114 | ||
| 115 | crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); | 115 | crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); |
| 116 | buf->sg.length += sizeof(u32); | 116 | buf->sg.length += ISCSI_DIGEST_SIZE; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /* | 119 | /* |
| @@ -220,6 +220,7 @@ static inline int | |||
| 220 | iscsi_tcp_chunk_done(struct iscsi_chunk *chunk) | 220 | iscsi_tcp_chunk_done(struct iscsi_chunk *chunk) |
| 221 | { | 221 | { |
| 222 | static unsigned char padbuf[ISCSI_PAD_LEN]; | 222 | static unsigned char padbuf[ISCSI_PAD_LEN]; |
| 223 | unsigned int pad; | ||
| 223 | 224 | ||
| 224 | if (chunk->copied < chunk->size) { | 225 | if (chunk->copied < chunk->size) { |
| 225 | iscsi_tcp_chunk_map(chunk); | 226 | iscsi_tcp_chunk_map(chunk); |
| @@ -243,10 +244,8 @@ iscsi_tcp_chunk_done(struct iscsi_chunk *chunk) | |||
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | /* Do we need to handle padding? */ | 246 | /* Do we need to handle padding? */ |
| 246 | if (chunk->total_copied & (ISCSI_PAD_LEN-1)) { | 247 | pad = iscsi_padding(chunk->total_copied); |
| 247 | unsigned int pad; | 248 | if (pad != 0) { |
| 248 | |||
| 249 | pad = ISCSI_PAD_LEN - (chunk->total_copied & (ISCSI_PAD_LEN-1)); | ||
| 250 | debug_tcp("consume %d pad bytes\n", pad); | 249 | debug_tcp("consume %d pad bytes\n", pad); |
| 251 | chunk->total_size += pad; | 250 | chunk->total_size += pad; |
| 252 | chunk->size = pad; | 251 | chunk->size = pad; |
| @@ -1385,11 +1384,11 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1385 | } | 1384 | } |
| 1386 | 1385 | ||
| 1387 | iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, | 1386 | iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, |
| 1388 | sizeof(struct iscsi_hdr)); | 1387 | ctask->hdr_len); |
| 1389 | 1388 | ||
| 1390 | if (conn->hdrdgst_en) | 1389 | if (conn->hdrdgst_en) |
| 1391 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1390 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
| 1392 | (u8*)tcp_ctask->hdrext); | 1391 | iscsi_next_hdr(ctask)); |
| 1393 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; | 1392 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; |
| 1394 | tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; | 1393 | tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; |
| 1395 | } | 1394 | } |
| @@ -2176,7 +2175,8 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit, | |||
| 2176 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 2175 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
| 2177 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 2176 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
| 2178 | 2177 | ||
| 2179 | ctask->hdr = &tcp_ctask->hdr; | 2178 | ctask->hdr = &tcp_ctask->hdr.cmd_hdr; |
| 2179 | ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE; | ||
| 2180 | } | 2180 | } |
| 2181 | 2181 | ||
| 2182 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { | 2182 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index f1c541151100..eb3784f949fd 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #define XMSTATE_IMM_HDR_INIT 0x1000 | 41 | #define XMSTATE_IMM_HDR_INIT 0x1000 |
| 42 | #define XMSTATE_SOL_HDR_INIT 0x2000 | 42 | #define XMSTATE_SOL_HDR_INIT 0x2000 |
| 43 | 43 | ||
| 44 | #define ISCSI_PAD_LEN 4 | ||
| 45 | #define ISCSI_SG_TABLESIZE SG_ALL | 44 | #define ISCSI_SG_TABLESIZE SG_ALL |
| 46 | #define ISCSI_TCP_MAX_CMD_LEN 16 | 45 | #define ISCSI_TCP_MAX_CMD_LEN 16 |
| 47 | 46 | ||
| @@ -130,14 +129,14 @@ struct iscsi_buf { | |||
| 130 | 129 | ||
| 131 | struct iscsi_data_task { | 130 | struct iscsi_data_task { |
| 132 | struct iscsi_data hdr; /* PDU */ | 131 | struct iscsi_data hdr; /* PDU */ |
| 133 | char hdrext[sizeof(__u32)]; /* Header-Digest */ | 132 | char hdrext[ISCSI_DIGEST_SIZE];/* Header-Digest */ |
| 134 | struct iscsi_buf digestbuf; /* digest buffer */ | 133 | struct iscsi_buf digestbuf; /* digest buffer */ |
| 135 | uint32_t digest; /* data digest */ | 134 | uint32_t digest; /* data digest */ |
| 136 | }; | 135 | }; |
| 137 | 136 | ||
| 138 | struct iscsi_tcp_mgmt_task { | 137 | struct iscsi_tcp_mgmt_task { |
| 139 | struct iscsi_hdr hdr; | 138 | struct iscsi_hdr hdr; |
| 140 | char hdrext[sizeof(__u32)]; /* Header-Digest */ | 139 | char hdrext[ISCSI_DIGEST_SIZE]; /* Header-Digest */ |
| 141 | int xmstate; /* mgmt xmit progress */ | 140 | int xmstate; /* mgmt xmit progress */ |
| 142 | struct iscsi_buf headbuf; /* header buffer */ | 141 | struct iscsi_buf headbuf; /* header buffer */ |
| 143 | struct iscsi_buf sendbuf; /* in progress buffer */ | 142 | struct iscsi_buf sendbuf; /* in progress buffer */ |
| @@ -159,9 +158,11 @@ struct iscsi_r2t_info { | |||
| 159 | }; | 158 | }; |
| 160 | 159 | ||
| 161 | struct iscsi_tcp_cmd_task { | 160 | struct iscsi_tcp_cmd_task { |
| 162 | struct iscsi_cmd hdr; | 161 | struct iscsi_hdr_buff { |
| 163 | char hdrext[4*sizeof(__u16)+ /* AHS */ | 162 | struct iscsi_cmd cmd_hdr; |
| 164 | sizeof(__u32)]; /* HeaderDigest */ | 163 | char hdrextbuf[ISCSI_MAX_AHS_SIZE + |
| 164 | ISCSI_DIGEST_SIZE]; | ||
| 165 | } hdr; | ||
| 165 | char pad[ISCSI_PAD_LEN]; | 166 | char pad[ISCSI_PAD_LEN]; |
| 166 | int pad_count; /* padded bytes */ | 167 | int pad_count; /* padded bytes */ |
| 167 | struct iscsi_buf headbuf; /* header buf (xmit) */ | 168 | struct iscsi_buf headbuf; /* header buf (xmit) */ |
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 | ||
| 40 | static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | ||
| 41 | int err); | ||
| 42 | |||
| 40 | struct iscsi_session * | 43 | struct iscsi_session * |
| 41 | class_to_transport_session(struct iscsi_cls_session *cls_session) | 44 | class_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 | } |
| 123 | EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); | 126 | EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); |
| 124 | 127 | ||
| 128 | static 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 | */ |
| 132 | static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | 149 | static 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 addition | ||
