Print this page
903 Improperly initialized variable in iSCSI error path
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
+++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 *
25 25 * iSCSI Pseudo HBA Driver
26 26 */
27 27
28 28 #include <sys/socket.h> /* networking stuff */
29 29 #include <sys/t_kuser.h> /* networking stuff */
30 30 #include <sys/tihdr.h> /* networking stuff */
31 31 #include <sys/strsubr.h> /* networking stuff */
32 32 #include <netinet/tcp.h> /* TCP_NODELAY */
33 33 #include <sys/socketvar.h> /* _ALLOC_SLEEP */
34 34 #include <sys/strsun.h> /* DB_TYPE() */
35 35 #include <sys/scsi/generic/sense.h>
36 36
37 37 #include "iscsi.h" /* iscsi driver */
38 38 #include <sys/iscsi_protocol.h> /* iscsi protocol */
39 39
40 40 #define ISCSI_INI_TASK_TTT 0xffffffff
41 41 #define ISCSI_CONN_TIEMOUT_DETECT 20
42 42
43 43 boolean_t iscsi_io_logging = B_FALSE;
44 44
45 45 #define ISCSI_CHECK_SCSI_READ(ICHK_CMD, ICHK_HDR, ICHK_LEN, ICHK_TYPE) \
46 46 if (idm_pattern_checking) { \
47 47 struct scsi_pkt *pkt = (ICHK_CMD)->cmd_un.scsi.pkt; \
48 48 if (((ICHK_HDR)->response == 0) && \
49 49 ((ICHK_HDR)->cmd_status == 0) && \
50 50 ((pkt->pkt_cdbp[0] == SCMD_READ_G1) || \
51 51 (pkt->pkt_cdbp[0] == SCMD_READ_G4) || \
52 52 (pkt->pkt_cdbp[0] == SCMD_READ) || \
53 53 (pkt->pkt_cdbp[0] == SCMD_READ_G5))) { \
54 54 idm_buf_t *idb = (ICHK_CMD)->cmd_un.scsi.ibp_ibuf; \
55 55 IDM_BUFPAT_CHECK(idb, ICHK_LEN, ICHK_TYPE); \
56 56 } \
57 57 }
58 58
59 59 /* Size of structure scsi_arq_status without sense data. */
60 60 #define ISCSI_ARQ_STATUS_NOSENSE_LEN (sizeof (struct scsi_arq_status) - \
61 61 sizeof (struct scsi_extended_sense))
62 62
63 63 /* generic io helpers */
64 64 static uint32_t n2h24(uchar_t *ptr);
65 65 static int iscsi_sna_lt(uint32_t n1, uint32_t n2);
66 66 void iscsi_update_flow_control(iscsi_sess_t *isp,
67 67 uint32_t max, uint32_t exp);
68 68 static iscsi_status_t iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp,
69 69 idm_conn_t *ic, iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp);
70 70 static iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
71 71 iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
72 72 static void iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
73 73 idm_status_t status);
74 74 static void iscsi_drop_conn_cleanup(iscsi_conn_t *icp);
75 75 static boolean_t iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp);
76 76 /* callbacks from idm */
77 77 static idm_pdu_cb_t iscsi_tx_done;
78 78
79 79 /* receivers */
80 80 static idm_status_t iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu);
81 81 static idm_status_t iscsi_rx_process_data_rsp(idm_conn_t *ic,
82 82 idm_pdu_t *pdu);
83 83 static idm_status_t iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu);
84 84 static idm_status_t iscsi_rx_process_reject_rsp(idm_conn_t *ic,
85 85 idm_pdu_t *pdu);
86 86
87 87 static idm_status_t iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic,
88 88 iscsi_hdr_t *old_ihp);
89 89 static idm_status_t iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic,
90 90 idm_pdu_t *pdu);
91 91 static idm_status_t iscsi_rx_process_logout_rsp(idm_conn_t *ic,
92 92 idm_pdu_t *pdu);
93 93 static idm_status_t iscsi_rx_process_async_rsp(idm_conn_t *ic,
94 94 idm_pdu_t *pdu);
95 95 static idm_status_t iscsi_rx_process_text_rsp(idm_conn_t *ic,
96 96 idm_pdu_t *pdu);
97 97
98 98 /* senders */
99 99 static iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
100 100 static iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
101 101 static iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
102 102 static iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
103 103 static iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
104 104 static iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
105 105
106 106
107 107 /* helpers */
108 108 static void iscsi_logout_start(void *arg);
109 109 static void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
110 110 static void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
111 111
112 112 static void iscsi_timeout_checks(iscsi_sess_t *isp);
113 113 static void iscsi_nop_checks(iscsi_sess_t *isp);
114 114 static boolean_t iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp);
115 115 static void iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
116 116 iscsi_conn_t *icp);
117 117
118 118 /*
119 119 * This file contains the main guts of the iSCSI protocol layer.
120 120 * It's broken into 5 sections; Basic helper functions, RX IO path,
121 121 * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
122 122 *
123 123 * The IO flow model is similiar to the below diagram. The
124 124 * iscsi session, connection and command state machines are used
125 125 * to drive IO through this flow diagram. Reference those files
126 126 * to get a detailed description of their respective state models
127 127 * prior to their xxx_state_machine_function().
128 128 *
129 129 * tran_start() -> CMD_E1 TX_THREAD RX_THREAD
130 130 * | T T
131 131 * V T T
132 132 * PENDING_Q --CMD_E2--> ACTIVE_Q - --CMD_E3--+
133 133 * T \ C T |
134 134 * T \M T |
135 135 * D T |
136 136 * WD_THREAD TT|TT T |
137 137 * /E T |
138 138 * / 6 T |
139 139 * ABORTING_Q<- --CMD_E3--+
140 140 * T |
141 141 * T T |
142 142 * T |
143 143 * callback() <--CMD_E#-- COMPLETION_Q <------------+
144 144 * T
145 145 * T
146 146 * IC_THREAD
147 147 *
148 148 * External and internal command are ran thru this same state
149 149 * machine. All commands enter the state machine by receiving an
150 150 * ISCSI_CMD_EVENT_E1. This event places the command into the
151 151 * PENDING_Q. Next when resources are available the TX_THREAD
152 152 * issues a E2 event on the command. This sends the command
153 153 * to the TCP stack and places the command on the ACTIVE_Q. While
154 154 * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
155 155 * WD_THREAD to ensure the pkt_time has not elapsed. If elapsed the
156 156 * command is issued an E6(timeout) event which moves either (if pending)
157 157 * completed the command or (if active) moves the command to the
158 158 * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
159 159 * to cancel the IO request. If the original command is completed
160 160 * or the TASK MANAGEMENT command completes the command is moved
161 161 * to the COMPLETION_Q via a E3 event. The IC_THREAD then processes
162 162 * the COMPLETION_Q and issues the scsi_pkt callback. This
163 163 * callback can not be processed directly from the RX_THREAD
164 164 * because the callback might call back into the iscsi driver
165 165 * causing a deadlock condition.
166 166 *
167 167 * For more details on the complete CMD state machine reference
168 168 * the state machine diagram in iscsi_cmd.c. The connection state
169 169 * machine is driven via IO events in this file. Then session
170 170 * events are driven by the connection events. For complete
171 171 * details on these state machines reference iscsi_sess.c and
172 172 * iscsi_conn.c
173 173 */
174 174
175 175
176 176 /*
177 177 * +--------------------------------------------------------------------+
178 178 * | io helper routines |
179 179 * +--------------------------------------------------------------------+
180 180 */
181 181
182 182 /*
183 183 * n2h24 - native to host 24 bit integer translation.
184 184 */
185 185 static uint32_t
186 186 n2h24(uchar_t *ptr)
187 187 {
188 188 uint32_t idx;
189 189 bcopy(ptr, &idx, 3);
190 190 return (ntohl(idx) >> 8);
191 191 }
192 192
193 193 /*
194 194 * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
195 195 */
196 196 static int
197 197 iscsi_sna_lt(uint32_t n1, uint32_t n2)
198 198 {
199 199 return ((n1 != n2) &&
200 200 (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
201 201 ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
202 202 }
203 203
204 204 /*
205 205 * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
206 206 * RFC1982
207 207 */
208 208 int
209 209 iscsi_sna_lte(uint32_t n1, uint32_t n2)
210 210 {
211 211 return ((n1 == n2) ||
212 212 (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
213 213 ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
214 214 }
215 215
216 216 /*
217 217 * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
218 218 * flow control information for a session
219 219 */
220 220 void
221 221 iscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
222 222 {
223 223 ASSERT(isp != NULL);
224 224 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
225 225
226 226 if (!iscsi_sna_lt(max, (exp - 1))) {
227 227
228 228 if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
229 229 isp->sess_expcmdsn = exp;
230 230 }
231 231
232 232 if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
233 233 isp->sess_maxcmdsn = max;
234 234 if (iscsi_sna_lte(isp->sess_cmdsn,
235 235 isp->sess_maxcmdsn)) {
236 236 /*
237 237 * the window is open again - schedule
238 238 * to send any held tasks soon
239 239 */
240 240 iscsi_sess_redrive_io(isp);
241 241 }
242 242 }
243 243 }
244 244 }
245 245
246 246
247 247 /*
248 248 * +--------------------------------------------------------------------+
249 249 * | io receive and processing routines |
250 250 * +--------------------------------------------------------------------+
251 251 */
252 252
253 253 /*
254 254 * iscsi_rx_scsi_rsp - called from idm
255 255 * For each opcode type fan out the processing.
256 256 */
257 257 void
258 258 iscsi_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
259 259 {
260 260 iscsi_conn_t *icp;
261 261 iscsi_sess_t *isp;
262 262 iscsi_hdr_t *ihp;
263 263 idm_status_t status;
264 264
265 265 ASSERT(ic != NULL);
266 266 ASSERT(pdu != NULL);
267 267 icp = ic->ic_handle;
268 268 ASSERT(icp != NULL);
269 269 ihp = (iscsi_hdr_t *)pdu->isp_hdr;
270 270 ASSERT(ihp != NULL);
271 271 isp = icp->conn_sess;
272 272 ASSERT(isp != NULL);
273 273
274 274 /* reset the session timer when we receive the response */
275 275 isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
276 276
277 277 /* fan out the hdr processing */
278 278 switch (ihp->opcode & ISCSI_OPCODE_MASK) {
279 279 case ISCSI_OP_SCSI_DATA_RSP:
280 280 status = iscsi_rx_process_data_rsp(ic, pdu);
281 281 break;
282 282 case ISCSI_OP_SCSI_RSP:
283 283 status = iscsi_rx_process_cmd_rsp(ic, pdu);
284 284 idm_pdu_complete(pdu, status);
285 285 break;
286 286 default:
287 287 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
288 288 "received pdu with unsupported opcode 0x%02x",
289 289 icp->conn_oid, ihp->opcode);
290 290 status = IDM_STATUS_PROTOCOL_ERROR;
291 291 }
292 292 iscsi_process_rsp_status(isp, icp, status);
293 293 }
294 294
295 295 void
296 296 iscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp)
297 297 {
298 298 struct buf *bp;
299 299 idm_buf_t *ibp, *obp;
300 300 idm_task_t *itp;
301 301
302 302 itp = icmdp->cmd_itp;
303 303 ASSERT(itp != NULL);
304 304 ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
305 305 (opcode == ISCSI_OP_SCSI_RSP));
306 306
307 307 bp = icmdp->cmd_un.scsi.bp;
308 308 ibp = icmdp->cmd_un.scsi.ibp_ibuf;
309 309 obp = icmdp->cmd_un.scsi.ibp_obuf;
310 310 ISCSI_IO_LOG(CE_NOTE, "DEBUG: task_cleanup: itp: %p opcode: %d "
311 311 "icmdp: %p bp: %p ibp: %p", (void *)itp, opcode,
312 312 (void *)icmdp, (void *)bp, (void *)ibp);
313 313 if (bp && bp->b_bcount) {
314 314 if (ibp != NULL && bp->b_flags & B_READ) {
315 315 idm_buf_unbind_in(itp, ibp);
316 316 idm_buf_free(ibp);
317 317 icmdp->cmd_un.scsi.ibp_ibuf = NULL;
318 318 } else if (obp != NULL && !(bp->b_flags & B_READ)) {
319 319 idm_buf_unbind_out(itp, obp);
320 320 idm_buf_free(obp);
321 321 icmdp->cmd_un.scsi.ibp_obuf = NULL;
322 322 }
323 323 }
324 324
325 325 idm_task_done(itp);
326 326 }
327 327
328 328 idm_status_t
329 329 iscsi_rx_chk(iscsi_conn_t *icp, iscsi_sess_t *isp,
330 330 iscsi_scsi_rsp_hdr_t *irhp, iscsi_cmd_t **icmdp)
331 331 {
332 332 iscsi_status_t rval;
333 333
334 334 mutex_enter(&isp->sess_cmdsn_mutex);
335 335
336 336 if (icp->conn_expstatsn == ntohl(irhp->statsn)) {
337 337 icp->conn_expstatsn++;
338 338 } else {
339 339 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
340 340 "received status out of order itt:0x%x statsn:0x%x "
341 341 "expstatsn:0x%x", icp->conn_oid, irhp->opcode,
342 342 irhp->itt, ntohl(irhp->statsn), icp->conn_expstatsn);
343 343 mutex_exit(&isp->sess_cmdsn_mutex);
344 344 return (IDM_STATUS_PROTOCOL_ERROR);
345 345 }
346 346
347 347 /* get icmdp so we can cleanup on error */
348 348 if ((irhp->opcode == ISCSI_OP_SCSI_DATA_RSP) ||
349 349 (irhp->opcode == ISCSI_OP_SCSI_RSP)) {
350 350 rval = iscsi_rx_process_scsi_itt_to_icmdp(isp, icp->conn_ic,
351 351 irhp, icmdp);
352 352 } else {
353 353 rval = iscsi_rx_process_itt_to_icmdp(isp,
354 354 (iscsi_hdr_t *)irhp, icmdp);
355 355 }
356 356
357 357 if (!ISCSI_SUCCESS(rval)) {
358 358 mutex_exit(&isp->sess_cmdsn_mutex);
359 359 return (IDM_STATUS_PROTOCOL_ERROR);
360 360 }
361 361
362 362 /* update expcmdsn and maxcmdsn */
363 363 iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
364 364 ntohl(irhp->expcmdsn));
365 365 mutex_exit(&isp->sess_cmdsn_mutex);
366 366 return (IDM_STATUS_SUCCESS);
367 367 }
368 368
369 369 static void
370 370 iscsi_cmd_rsp_chk(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp)
371 371 {
372 372 struct scsi_pkt *pkt;
373 373 size_t data_transferred;
374 374
375 375 pkt = icmdp->cmd_un.scsi.pkt;
376 376 pkt->pkt_resid = 0;
377 377 data_transferred = icmdp->cmd_un.scsi.data_transferred;
378 378 /* Check the residual count */
379 379 if ((icmdp->cmd_un.scsi.bp) &&
380 380 (data_transferred != icmdp->cmd_un.scsi.bp->b_bcount)) {
381 381 /*
382 382 * We didn't xfer the expected amount of data -
383 383 * the residual_count in the header is only
384 384 * valid if the underflow flag is set.
385 385 */
386 386 if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
387 387 pkt->pkt_resid = ntohl(issrhp->residual_count);
388 388 } else {
389 389 if (icmdp->cmd_un.scsi.bp->b_bcount >
390 390 data_transferred) {
391 391 /*
392 392 * Some data fell on the floor
393 393 * somehow - probably a CRC error
394 394 */
395 395 pkt->pkt_resid =
396 396 icmdp->cmd_un.scsi.bp->b_bcount -
397 397 data_transferred;
398 398 }
399 399 }
400 400 ISCSI_IO_LOG(CE_NOTE,
401 401 "DEBUG: iscsi_rx_cmd_rsp_chk: itt: %u"
402 402 "data_trans != b_count data_transferred: %lu "
403 403 "b_count: %lu cmd_status: %d flags: %d resid: %lu",
404 404 issrhp->itt, data_transferred,
405 405 icmdp->cmd_un.scsi.bp->b_bcount,
406 406 issrhp->cmd_status & STATUS_MASK,
407 407 issrhp->flags, pkt->pkt_resid);
408 408 }
409 409 /* set flags that tell SCSA that the command is complete */
410 410 if (icmdp->cmd_crc_error_seen == B_FALSE) {
411 411 /* Set successful completion */
412 412 pkt->pkt_reason = CMD_CMPLT;
413 413 if (icmdp->cmd_un.scsi.bp) {
414 414 pkt->pkt_state |= (STATE_XFERRED_DATA |
415 415 STATE_GOT_STATUS);
416 416 } else {
417 417 pkt->pkt_state |= STATE_GOT_STATUS;
418 418 }
419 419 } else {
420 420 /*
421 421 * Some of the data was found to have an incorrect
422 422 * error at the protocol error.
423 423 */
424 424 pkt->pkt_reason = CMD_PER_FAIL;
425 425 pkt->pkt_statistics |= STAT_PERR;
426 426 if (icmdp->cmd_un.scsi.bp) {
427 427 pkt->pkt_resid =
428 428 icmdp->cmd_un.scsi.bp->b_bcount;
429 429 } else {
430 430 pkt->pkt_resid = 0;
431 431 }
432 432 }
433 433 }
434 434
435 435 static boolean_t
436 436 iscsi_cmd_rsp_cmd_status(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp,
437 437 uint8_t *data)
438 438 {
439 439 int32_t dlength;
440 440 struct scsi_arq_status *arqstat;
441 441 size_t senselen;
442 442 int32_t statuslen;
443 443 int32_t sensebuf_len;
444 444 struct scsi_pkt *pkt;
445 445 boolean_t affect = B_FALSE;
446 446 int32_t senselen_to_copy;
447 447
448 448 pkt = icmdp->cmd_un.scsi.pkt;
449 449 dlength = n2h24(issrhp->dlength);
450 450
451 451 /*
452 452 * Process iSCSI Cmd Response Status
453 453 * RFC 3720 Sectionn 10.4.2.
454 454 */
455 455 switch (issrhp->cmd_status & STATUS_MASK) {
456 456 case STATUS_GOOD:
457 457 /* pass SCSI status up stack */
458 458 if (pkt->pkt_scbp) {
459 459 pkt->pkt_scbp[0] = issrhp->cmd_status;
460 460 }
461 461 break;
462 462 case STATUS_CHECK:
463 463 /*
464 464 * Verify we received a sense buffer and
465 465 * that there is the correct amount of
466 466 * request sense space to copy it to.
467 467 */
468 468 if ((dlength > 1) &&
469 469 (pkt->pkt_scbp != NULL) &&
470 470 (icmdp->cmd_un.scsi.statuslen >=
471 471 sizeof (struct scsi_arq_status))) {
472 472 /*
473 473 * If a bad command status is received we
474 474 * need to reset the pkt_resid to zero.
475 475 * The target driver compares its value
476 476 * before checking other error flags.
477 477 * (ex. check conditions)
478 478 */
479 479 pkt->pkt_resid = 0;
480 480
481 481 /* get sense length from first 2 bytes */
482 482 senselen = ((data[0] << 8) | data[1]) &
483 483 (size_t)0xFFFF;
484 484 ISCSI_IO_LOG(CE_NOTE,
485 485 "DEBUG: iscsi_rx_cmd_rsp_cmd_status status_check: "
486 486 "dlen: %d scbp: %p statuslen: %d arq: %d senselen:"
487 487 " %lu", dlength, (void *)pkt->pkt_scbp,
488 488 icmdp->cmd_un.scsi.statuslen,
489 489 (int)sizeof (struct scsi_arq_status),
490 490 senselen);
491 491
492 492 /* Sanity-check on the sense length */
493 493 if ((senselen + 2) > dlength) {
494 494 senselen = dlength - 2;
495 495 }
496 496
497 497 /*
498 498 * If there was a Data Digest error then
499 499 * the sense data cannot be trusted.
500 500 */
501 501 if (icmdp->cmd_crc_error_seen) {
502 502 senselen = 0;
503 503 }
504 504
505 505 /* automatic request sense */
506 506 arqstat =
507 507 (struct scsi_arq_status *)pkt->pkt_scbp;
508 508
509 509 /* pass SCSI status up stack */
510 510 *((uchar_t *)&arqstat->sts_status) =
511 511 issrhp->cmd_status;
512 512
513 513 /*
514 514 * Set the status for the automatic
515 515 * request sense command
516 516 */
517 517 arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
518 518 STATE_GOT_TARGET | STATE_SENT_CMD |
519 519 STATE_XFERRED_DATA | STATE_GOT_STATUS |
520 520 STATE_ARQ_DONE);
521 521
522 522 *((uchar_t *)&arqstat->sts_rqpkt_status) =
523 523 STATUS_GOOD;
524 524
525 525 arqstat->sts_rqpkt_reason = CMD_CMPLT;
526 526 statuslen = icmdp->cmd_un.scsi.statuslen;
527 527
528 528 if (senselen == 0) {
529 529 /* auto request sense failed */
530 530 arqstat->sts_rqpkt_status.sts_chk = 1;
531 531 arqstat->sts_rqpkt_resid = statuslen;
532 532 } else if (senselen < statuslen) {
533 533 /* auto request sense short */
534 534 arqstat->sts_rqpkt_resid = statuslen - senselen;
535 535 } else {
536 536 /* auto request sense complete */
537 537 arqstat->sts_rqpkt_resid = 0;
538 538 }
539 539 arqstat->sts_rqpkt_statistics = 0;
540 540 pkt->pkt_state |= STATE_ARQ_DONE;
541 541
542 542 if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_XARQ) {
543 543 pkt->pkt_state |= STATE_XARQ_DONE;
544 544 }
545 545
546 546 /*
547 547 * Calculate size of space reserved for sense data in
548 548 * pkt->pkt_scbp.
549 549 */
550 550 sensebuf_len = statuslen - ISCSI_ARQ_STATUS_NOSENSE_LEN;
551 551
552 552 /* copy auto request sense */
553 553 senselen_to_copy = min(senselen, sensebuf_len);
554 554 if (senselen_to_copy > 0) {
555 555 bcopy(&data[2], (uchar_t *)&arqstat->
556 556 sts_sensedata, senselen_to_copy);
557 557
558 558 affect = iscsi_decode_sense(
559 559 (uint8_t *)&arqstat->sts_sensedata, icmdp);
560 560 }
561 561 arqstat->sts_rqpkt_resid = sensebuf_len -
562 562 senselen_to_copy;
563 563 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_cmd_rsp_cmd_status:"
564 564 " sts_rqpkt_resid: %d pkt_scblen: %d senselen: %lu"
565 565 " sensebuf_len: %d senselen_to_copy: %d affect: %d",
566 566 arqstat->sts_rqpkt_resid, pkt->pkt_scblen, senselen,
567 567 sensebuf_len, senselen_to_copy, affect);
568 568 break;
569 569 }
570 570 /* FALLTHRU */
571 571 case STATUS_BUSY:
572 572 case STATUS_RESERVATION_CONFLICT:
573 573 case STATUS_QFULL:
574 574 case STATUS_ACA_ACTIVE:
575 575 default:
576 576 /*
577 577 * If a bad command status is received we need to
578 578 * reset the pkt_resid to zero. The target driver
579 579 * compares its value before checking other error
580 580 * flags. (ex. check conditions)
581 581 */
582 582 ISCSI_IO_LOG(CE_NOTE,
583 583 "DEBUG: iscsi_rx_cmd_rsp_cmd_status: status: "
584 584 "%d cmd_status: %d dlen: %u scbp: %p statuslen: %d "
585 585 "arg_len: %d", issrhp->cmd_status & STATUS_MASK,
586 586 issrhp->cmd_status, dlength, (void *)pkt->pkt_scbp,
587 587 icmdp->cmd_un.scsi.statuslen,
588 588 (int)sizeof (struct scsi_arq_status));
589 589 pkt->pkt_resid = 0;
590 590 /* pass SCSI status up stack */
591 591 if (pkt->pkt_scbp) {
592 592 pkt->pkt_scbp[0] = issrhp->cmd_status;
593 593 }
594 594 }
595 595
596 596 return (affect);
597 597 }
598 598
599 599 /*
600 600 * iscsi_rx_process_login_pdup - Process login response PDU. This function
601 601 * copies the data into the connection context so that the login code can
602 602 * interpret it.
603 603 */
604 604
605 605 idm_status_t
606 606 iscsi_rx_process_login_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
607 607 {
608 608 iscsi_conn_t *icp;
609 609
610 610 icp = ic->ic_handle;
611 611
612 612 /*
613 613 * Copy header and data into connection structure so iscsi_login()
614 614 * can process it.
615 615 */
616 616 mutex_enter(&icp->conn_login_mutex);
617 617 /*
618 618 * If conn_login_state != LOGIN_TX then we are not ready to handle
619 619 * this login response and we should just drop it.
620 620 */
621 621 if (icp->conn_login_state == LOGIN_TX) {
622 622 icp->conn_login_datalen = pdu->isp_datalen;
623 623 bcopy(pdu->isp_hdr, &icp->conn_login_resp_hdr,
624 624 sizeof (iscsi_hdr_t));
625 625 /*
626 626 * Login code is sloppy with it's NULL handling so make sure
627 627 * we don't leave any stale data in there.
628 628 */
629 629 bzero(icp->conn_login_data, icp->conn_login_max_data_length);
630 630 bcopy(pdu->isp_data, icp->conn_login_data,
631 631 MIN(pdu->isp_datalen, icp->conn_login_max_data_length));
632 632 iscsi_login_update_state_locked(icp, LOGIN_RX);
633 633 }
634 634 mutex_exit(&icp->conn_login_mutex);
635 635
636 636 return (IDM_STATUS_SUCCESS);
637 637 }
638 638
639 639 /*
640 640 * iscsi_rx_process_cmd_rsp - Process received scsi command response. This
641 641 * will contain sense data if the command was not successful. This data needs
642 642 * to be copied into the scsi_pkt. Otherwise we just complete the IO.
643 643 */
644 644 static idm_status_t
645 645 iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
646 646 {
647 647 iscsi_conn_t *icp = ic->ic_handle;
648 648 iscsi_sess_t *isp = icp->conn_sess;
649 649 iscsi_scsi_rsp_hdr_t *issrhp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
650 650 uint8_t *data = pdu->isp_data;
651 651 iscsi_cmd_t *icmdp = NULL;
652 652 struct scsi_pkt *pkt = NULL;
653 653 idm_status_t rval;
654 654 struct buf *bp;
655 655 boolean_t flush = B_FALSE;
656 656 uint32_t cmd_sn = 0;
657 657 uint16_t lun_num = 0;
658 658
659 659 /* make sure we get status in order */
660 660 mutex_enter(&icp->conn_queue_active.mutex);
661 661
662 662 if ((rval = iscsi_rx_chk(icp, isp, issrhp,
663 663 &icmdp)) != IDM_STATUS_SUCCESS) {
664 664 if (icmdp != NULL) {
665 665 iscsi_task_cleanup(issrhp->opcode, icmdp);
666 666 }
667 667 mutex_exit(&icp->conn_queue_active.mutex);
668 668 return (rval);
669 669 }
670 670
671 671 /*
672 672 * If we are in "idm aborting" state then we shouldn't continue
673 673 * to process this command. By definition this command is no longer
674 674 * on the active queue so we shouldn't try to remove it either.
675 675 */
676 676 mutex_enter(&icmdp->cmd_mutex);
677 677 if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
678 678 mutex_exit(&icmdp->cmd_mutex);
679 679 mutex_exit(&icp->conn_queue_active.mutex);
680 680 return (IDM_STATUS_SUCCESS);
681 681 }
682 682 mutex_exit(&icmdp->cmd_mutex);
683 683
684 684 /* Get the IDM buffer and bytes transferred */
685 685 bp = icmdp->cmd_un.scsi.bp;
686 686 if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
687 687 /* Transport tracks bytes transferred so use those counts */
688 688 if (bp && (bp->b_flags & B_READ)) {
689 689 icmdp->cmd_un.scsi.data_transferred +=
690 690 icmdp->cmd_itp->idt_rx_bytes;
691 691 } else {
692 692 icmdp->cmd_un.scsi.data_transferred +=
693 693 icmdp->cmd_itp->idt_tx_bytes;
694 694 }
695 695 } else {
696 696 /*
697 697 * Some transports cannot track the bytes transferred on
698 698 * the initiator side (like iSER) so we have to use the
699 699 * status info. If the response field indicates that
700 700 * the command actually completed then we will assume
701 701 * the data_transferred value represents the entire buffer
702 702 * unless the resid field says otherwise. This is a bit
703 703 * unintuitive but it's really impossible to know what
704 704 * has been transferred without detailed consideration
705 705 * of the SCSI status and sense key and that is outside
706 706 * the scope of the transport. Instead the target/class driver
707 707 * can consider these values along with the resid and figure
708 708 * it out. The data_transferred concept is just belt and
709 709 * suspenders anyway -- RFC 3720 actually explicitly rejects
710 710 * scoreboarding ("Initiators SHOULD NOT keep track of the
711 711 * data transferred to or from the target (scoreboarding)")
712 712 * perhaps for this very reason.
713 713 */
714 714 if (issrhp->response != 0) {
715 715 icmdp->cmd_un.scsi.data_transferred = 0;
716 716 } else {
717 717 icmdp->cmd_un.scsi.data_transferred =
718 718 (bp == NULL) ? 0 : bp->b_bcount;
719 719 if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
720 720 icmdp->cmd_un.scsi.data_transferred -=
721 721 ntohl(issrhp->residual_count);
722 722 }
723 723 }
724 724 }
725 725
726 726 ISCSI_CHECK_SCSI_READ(icmdp, issrhp,
727 727 icmdp->cmd_un.scsi.data_transferred,
728 728 BP_CHECK_THOROUGH);
729 729
730 730 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu: %p itt:"
731 731 " %x expcmdsn: %x sess_cmd: %x sess_expcmdsn: %x data_transfered:"
732 732 " %lu ibp: %p obp: %p", (void *)ic, (void *)pdu, issrhp->itt,
733 733 issrhp->expcmdsn, isp->sess_cmdsn, isp->sess_expcmdsn,
734 734 icmdp->cmd_un.scsi.data_transferred,
735 735 (void *)icmdp->cmd_un.scsi.ibp_ibuf,
736 736 (void *)icmdp->cmd_un.scsi.ibp_obuf);
737 737
738 738 iscsi_task_cleanup(issrhp->opcode, icmdp);
739 739
740 740 if (issrhp->response) {
741 741 /* The target failed the command. */
742 742 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu:"
743 743 " %p response: %d bcount: %lu", (void *)ic, (void *)pdu,
744 744 issrhp->response, icmdp->cmd_un.scsi.bp->b_bcount);
745 745 pkt = icmdp->cmd_un.scsi.pkt;
746 746 pkt->pkt_reason = CMD_TRAN_ERR;
747 747 if (icmdp->cmd_un.scsi.bp) {
748 748 pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
749 749 } else {
750 750 pkt->pkt_resid = 0;
751 751 }
752 752 } else {
753 753 /* success */
754 754 iscsi_cmd_rsp_chk(icmdp, issrhp);
755 755 flush = iscsi_cmd_rsp_cmd_status(icmdp, issrhp, data);
756 756
757 757 ASSERT(icmdp->cmd_lun == NULL || icmdp->cmd_lun->lun_num ==
758 758 (icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK));
759 759
760 760 if (flush == B_TRUE) {
761 761 cmd_sn = icmdp->cmd_sn;
762 762 lun_num = icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK;
763 763 }
764 764 }
765 765
766 766 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
767 767 if (flush == B_TRUE) {
768 768 iscsi_flush_cmd_after_reset(cmd_sn, lun_num, icp);
769 769 }
770 770 mutex_exit(&icp->conn_queue_active.mutex);
771 771 return (IDM_STATUS_SUCCESS);
772 772 }
773 773
774 774 static void
775 775 iscsi_data_rsp_pkt(iscsi_cmd_t *icmdp, iscsi_data_rsp_hdr_t *idrhp)
776 776 {
777 777 struct buf *bp = NULL;
778 778 size_t data_transferred;
779 779 struct scsi_pkt *pkt;
780 780
781 781 bp = icmdp->cmd_un.scsi.bp;
782 782 pkt = icmdp->cmd_un.scsi.pkt;
783 783 data_transferred = icmdp->cmd_un.scsi.data_transferred;
784 784 /*
785 785 * The command* must be completed now, since we won't get a command
786 786 * response PDU. The cmd_status and residual_count are
787 787 * not meaningful unless status_present is set.
788 788 */
789 789 pkt->pkt_resid = 0;
790 790 /* Check the residual count */
791 791 if (bp && (data_transferred != bp->b_bcount)) {
792 792 /*
793 793 * We didn't xfer the expected amount of data -
794 794 * the residual_count in the header is only valid
795 795 * if the underflow flag is set.
796 796 */
797 797 if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
798 798 pkt->pkt_resid = ntohl(idrhp->residual_count);
799 799 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
800 800 "underflow: itt: %d "
801 801 "transferred: %lu count: %lu", idrhp->itt,
802 802 data_transferred, bp->b_bcount);
803 803 } else {
804 804 if (bp->b_bcount > data_transferred) {
805 805 /* Some data fell on the floor somehw */
806 806 ISCSI_IO_LOG(CE_NOTE, "DEBUG: "
807 807 "iscsi_data_rsp_pkt: data fell: itt: %d "
808 808 "transferred: %lu count: %lu", idrhp->itt,
809 809 data_transferred, bp->b_bcount);
810 810 pkt->pkt_resid =
811 811 bp->b_bcount - data_transferred;
812 812 }
813 813 }
814 814 }
815 815
816 816 pkt->pkt_reason = CMD_CMPLT;
817 817 pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
818 818
819 819 if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
820 820 (icmdp->cmd_un.scsi.statuslen >=
821 821 sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
822 822
823 823 /*
824 824 * Not supposed to get exception status here!
825 825 * We have no request sense data so just do the
826 826 * best we can
827 827 */
828 828 struct scsi_arq_status *arqstat =
829 829 (struct scsi_arq_status *)pkt->pkt_scbp;
830 830
831 831
832 832 bzero(arqstat, sizeof (struct scsi_arq_status));
833 833
834 834 *((uchar_t *)&arqstat->sts_status) =
835 835 idrhp->cmd_status;
836 836
837 837 /* sense residual is set to whole size of sense buffer */
838 838 arqstat->sts_rqpkt_resid = icmdp->cmd_un.scsi.statuslen -
839 839 ISCSI_ARQ_STATUS_NOSENSE_LEN;
840 840 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
841 841 "exception status: itt: %d resid: %d",
842 842 idrhp->itt, arqstat->sts_rqpkt_resid);
843 843
844 844 } else if (pkt->pkt_scbp) {
845 845 /* just pass along the status we got */
846 846 pkt->pkt_scbp[0] = idrhp->cmd_status;
847 847 }
848 848 }
849 849
850 850 /*
851 851 * iscsi_rx_process_data_rsp -
852 852 * This currently processes the final data sequence denoted by the data response
853 853 * PDU Status bit being set. We will not receive the SCSI response.
854 854 * This bit denotes that the PDU is the successful completion of the
855 855 * command.
856 856 */
857 857 static idm_status_t
858 858 iscsi_rx_process_data_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
859 859 {
860 860 iscsi_sess_t *isp = NULL;
861 861 iscsi_data_rsp_hdr_t *idrhp = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
862 862 iscsi_cmd_t *icmdp = NULL;
863 863 struct buf *bp = NULL;
864 864 iscsi_conn_t *icp = ic->ic_handle;
865 865 idm_buf_t *ibp;
866 866 idm_status_t rval;
867 867
868 868
869 869 /* should only call this when the data rsp contains final rsp */
870 870 ASSERT(idrhp->flags & ISCSI_FLAG_DATA_STATUS);
871 871 isp = icp->conn_sess;
872 872
873 873 mutex_enter(&icp->conn_queue_active.mutex);
874 874 if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)idrhp,
875 875 &icmdp)) != IDM_STATUS_SUCCESS) {
876 876 if (icmdp != NULL) {
877 877 iscsi_task_cleanup(idrhp->opcode, icmdp);
878 878 }
879 879 mutex_exit(&icp->conn_queue_active.mutex);
880 880 return (rval);
881 881 }
882 882
883 883 /*
884 884 * If we are in "idm aborting" state then we shouldn't continue
885 885 * to process this command. By definition this command is no longer
886 886 * on the active queue so we shouldn't try to remove it either.
887 887 */
888 888 mutex_enter(&icmdp->cmd_mutex);
889 889 if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
890 890 mutex_exit(&icmdp->cmd_mutex);
891 891 mutex_exit(&icp->conn_queue_active.mutex);
892 892 return (IDM_STATUS_SUCCESS);
893 893 }
894 894 mutex_exit(&icmdp->cmd_mutex);
895 895
896 896 /*
897 897 * Holding the pending/active queue locks across the
898 898 * iscsi_rx_data call later in this function may cause
899 899 * deadlock during fault injections. Instead remove
900 900 * the cmd from the active queue and release the locks.
901 901 * Then before returning or completing the command
902 902 * return the cmd to the active queue and reacquire
903 903 * the locks.
904 904 */
905 905 iscsi_dequeue_active_cmd(icp, icmdp);
906 906
907 907 mutex_exit(&icp->conn_queue_active.mutex);
908 908
909 909 /* shorthand some values */
910 910 bp = icmdp->cmd_un.scsi.bp;
911 911
912 912 /*
913 913 * some poorly behaved targets have been observed
914 914 * sending data-in pdu's during a write operation
915 915 */
916 916 if (bp != NULL) {
917 917 if (!(bp->b_flags & B_READ)) {
918 918 cmn_err(CE_WARN,
919 919 "iscsi connection(%u) protocol error - "
920 920 "received data response during write operation "
921 921 "itt:0x%x",
922 922 icp->conn_oid, idrhp->itt);
923 923 mutex_enter(&icp->conn_queue_active.mutex);
924 924 iscsi_enqueue_active_cmd(icp, icmdp);
925 925 mutex_exit(&icp->conn_queue_active.mutex);
926 926 return (IDM_STATUS_PROTOCOL_ERROR);
927 927 }
928 928 }
929 929
930 930 ibp = icmdp->cmd_un.scsi.ibp_ibuf;
931 931 if (ibp == NULL) {
932 932 /*
933 933 * After the check of bp above we *should* have a corresponding
934 934 * idm_buf_t (ibp). It's possible that the original call
935 935 * to idm_buf_alloc failed due to a pending connection state
936 936 * transition in which case this value can be NULL. It's
937 937 * highly unlikely that the connection would be shutting down
938 938 * *and* we manage to process a data response and get to this
939 939 * point in the code but just in case we should check for it.
940 940 * This isn't really a protocol error -- we are almost certainly
941 941 * closing the connection anyway so just return a generic error.
942 942 */
943 943 mutex_enter(&icp->conn_queue_active.mutex);
944 944 iscsi_enqueue_active_cmd(icp, icmdp);
945 945 mutex_exit(&icp->conn_queue_active.mutex);
946 946 return (IDM_STATUS_FAIL);
947 947 }
948 948
949 949 if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
950 950 icmdp->cmd_un.scsi.data_transferred =
951 951 icmdp->cmd_itp->idt_rx_bytes;
952 952 } else {
953 953 icmdp->cmd_un.scsi.data_transferred = bp->b_bcount;
954 954 if (idrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
955 955 icmdp->cmd_un.scsi.data_transferred -=
956 956 ntohl(idrhp->residual_count);
957 957 }
958 958 }
959 959
960 960 ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_data_rsp: icp: %p pdu: %p "
961 961 "itt: %d ibp: %p icmdp: %p xfer_len: %lu transferred: %lu dlen: %u",
962 962 (void *)icp, (void *)pdu, idrhp->itt, (void *)bp, (void *)icmdp,
963 963 (ibp == NULL) ? 0 : ibp->idb_xfer_len,
964 964 icmdp->cmd_un.scsi.data_transferred,
965 965 n2h24(idrhp->dlength));
966 966
967 967 iscsi_task_cleanup(idrhp->opcode, icmdp);
968 968
969 969 iscsi_data_rsp_pkt(icmdp, idrhp);
970 970
971 971 mutex_enter(&icp->conn_queue_active.mutex);
972 972 iscsi_enqueue_active_cmd(icp, icmdp);
973 973 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
974 974 mutex_exit(&icp->conn_queue_active.mutex);
975 975
976 976 return (IDM_STATUS_SUCCESS);
977 977 }
978 978
979 979 /*
980 980 * iscsi_rx_process_nop - Process a received nop. If nop is in response
981 981 * to a ping we sent update stats. If initiated by the target we need
982 982 * to response back to the target with a nop. Schedule the response.
983 983 */
984 984 /* ARGSUSED */
985 985 static idm_status_t
986 986 iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu)
987 987 {
988 988 iscsi_sess_t *isp = NULL;
989 989 iscsi_nop_in_hdr_t *inihp = (iscsi_nop_in_hdr_t *)pdu->isp_hdr;
990 990 iscsi_cmd_t *icmdp = NULL;
991 991 iscsi_conn_t *icp = ic->ic_handle;
992 992
993 993 if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
994 994 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
995 995 "received status out of order itt:0x%x statsn:0x%x "
996 996 "expstatsn:0x%x", icp->conn_oid, inihp->opcode, inihp->itt,
997 997 ntohl(inihp->statsn), icp->conn_expstatsn);
998 998 return (IDM_STATUS_PROTOCOL_ERROR);
999 999 }
1000 1000 isp = icp->conn_sess;
1001 1001 ASSERT(isp != NULL);
1002 1002 mutex_enter(&isp->sess_queue_pending.mutex);
1003 1003 mutex_enter(&icp->conn_queue_active.mutex);
1004 1004 mutex_enter(&isp->sess_cmdsn_mutex);
1005 1005 if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
1006 1006 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1007 1007 isp, (iscsi_hdr_t *)inihp, &icmdp))) {
1008 1008 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1009 1009 "- can not find cmd for itt:0x%x",
1010 1010 icp->conn_oid, inihp->itt);
1011 1011 mutex_exit(&isp->sess_cmdsn_mutex);
1012 1012 mutex_exit(&icp->conn_queue_active.mutex);
1013 1013 mutex_exit(&isp->sess_queue_pending.mutex);
1014 1014 return (IDM_STATUS_PROTOCOL_ERROR);
1015 1015 }
1016 1016 }
1017 1017
1018 1018 /* update expcmdsn and maxcmdsn */
1019 1019 iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
1020 1020 ntohl(inihp->expcmdsn));
1021 1021 mutex_exit(&isp->sess_cmdsn_mutex);
1022 1022
1023 1023 if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
1024 1024 (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
1025 1025 /* This is the only type of nop that incs. the expstatsn */
1026 1026 icp->conn_expstatsn++;
1027 1027
1028 1028 /*
1029 1029 * This is a targets response to our nop
1030 1030 */
1031 1031 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1032 1032 } else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
1033 1033 /*
1034 1034 * Target requested a nop. Send one.
1035 1035 */
1036 1036 iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
1037 1037 } else {
1038 1038 /*
1039 1039 * This is a target-initiated ping that doesn't expect
1040 1040 * a response; nothing to do except update our flow control
1041 1041 * (which we do in all cases above).
1042 1042 */
1043 1043 /* EMPTY */
1044 1044 }
1045 1045 mutex_exit(&icp->conn_queue_active.mutex);
1046 1046 mutex_exit(&isp->sess_queue_pending.mutex);
1047 1047
1048 1048 return (IDM_STATUS_SUCCESS);
1049 1049 }
1050 1050
1051 1051
1052 1052 /*
1053 1053 * iscsi_rx_process_reject_rsp - The server rejected a PDU
1054 1054 */
1055 1055 static idm_status_t
1056 1056 iscsi_rx_process_reject_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1057 1057 {
1058 1058 iscsi_reject_rsp_hdr_t *irrhp = (iscsi_reject_rsp_hdr_t *)pdu->isp_hdr;
1059 1059 iscsi_sess_t *isp = NULL;
1060 1060 uint32_t dlength = 0;
1061 1061 iscsi_hdr_t *old_ihp = NULL;
1062 1062 iscsi_conn_t *icp = ic->ic_handle;
1063 1063 uint8_t *data = pdu->isp_data;
1064 1064 idm_status_t status = IDM_STATUS_SUCCESS;
1065 1065 int i = 0;
1066 1066
1067 1067 ASSERT(data != NULL);
1068 1068 isp = icp->conn_sess;
1069 1069 ASSERT(isp != NULL);
1070 1070
1071 1071 /*
1072 1072 * In RFC3720 section 10.17, this 4 bytes should be all 0xff.
1073 1073 */
1074 1074 for (i = 0; i < 4; i++) {
1075 1075 if (irrhp->must_be_ff[i] != 0xff) {
1076 1076 return (IDM_STATUS_PROTOCOL_ERROR);
1077 1077 }
1078 1078 }
1079 1079 mutex_enter(&isp->sess_cmdsn_mutex);
1080 1080
1081 1081 if (icp->conn_expstatsn == ntohl(irrhp->statsn)) {
1082 1082 icp->conn_expstatsn++;
1083 1083 } else {
1084 1084 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1085 1085 "received status out of order statsn:0x%x "
1086 1086 "expstatsn:0x%x", icp->conn_oid, irrhp->opcode,
1087 1087 ntohl(irrhp->statsn), icp->conn_expstatsn);
1088 1088 mutex_exit(&isp->sess_cmdsn_mutex);
1089 1089 return (IDM_STATUS_PROTOCOL_ERROR);
1090 1090 }
1091 1091 /* update expcmdsn and maxcmdsn */
1092 1092 iscsi_update_flow_control(isp, ntohl(irrhp->maxcmdsn),
1093 1093 ntohl(irrhp->expcmdsn));
1094 1094
1095 1095 mutex_exit(&isp->sess_cmdsn_mutex);
1096 1096
1097 1097 /* If we don't have the rejected header we can't do anything */
1098 1098 dlength = n2h24(irrhp->dlength);
1099 1099 if (dlength < sizeof (iscsi_hdr_t)) {
1100 1100 return (IDM_STATUS_PROTOCOL_ERROR);
1101 1101 }
1102 1102
1103 1103 /* map old ihp */
1104 1104 old_ihp = (iscsi_hdr_t *)data;
1105 1105
1106 1106 switch (irrhp->reason) {
1107 1107 /*
1108 1108 * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
1109 1109 * too many immediate commands (original cmd can be resent)
1110 1110 */
1111 1111 case ISCSI_REJECT_IMM_CMD_REJECT:
1112 1112 /*
1113 1113 * We have exceeded the server's capacity for outstanding
1114 1114 * immediate commands. This must be a task management
1115 1115 * command so try to find it in the abortingqueue and
1116 1116 * complete it.
1117 1117 */
1118 1118 if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
1119 1119 /* Rejecting IMM but old old_hdr wasn't IMM */
1120 1120 return (IDM_STATUS_PROTOCOL_ERROR);
1121 1121 }
1122 1122
1123 1123 /*
1124 1124 * We only send NOP and TASK_MGT as IMM. All other
1125 1125 * cases should be considered as a protocol error.
1126 1126 */
1127 1127 switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
1128 1128 case ISCSI_OP_NOOP_OUT:
1129 1129 /*
1130 1130 * A ping was rejected - treat this like
1131 1131 * ping response. The down side is we
1132 1132 * didn't get an updated MaxCmdSn.
1133 1133 */
1134 1134 break;
1135 1135 case ISCSI_OP_SCSI_TASK_MGT_MSG:
1136 1136 status =
1137 1137 iscsi_rx_process_rejected_tsk_mgt(ic, old_ihp);
1138 1138 break;
1139 1139 default:
1140 1140 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1141 1141 "- received a reject for a command(0x%02x) not "
1142 1142 "sent as an immediate", icp->conn_oid,
1143 1143 old_ihp->opcode);
1144 1144 status = IDM_STATUS_PROTOCOL_ERROR;
1145 1145 break;
1146 1146 }
1147 1147 break;
1148 1148
1149 1149 /*
1150 1150 * For the rest of the reject cases just use the general
1151 1151 * hammer of dis/reconnecting. This will resolve all
1152 1152 * noted issues although could be more graceful.
1153 1153 */
1154 1154 case ISCSI_REJECT_DATA_DIGEST_ERROR:
1155 1155 case ISCSI_REJECT_CMD_BEFORE_LOGIN:
1156 1156 case ISCSI_REJECT_SNACK_REJECT:
1157 1157 case ISCSI_REJECT_PROTOCOL_ERROR:
1158 1158 case ISCSI_REJECT_CMD_NOT_SUPPORTED:
1159 1159 case ISCSI_REJECT_TASK_IN_PROGRESS:
1160 1160 case ISCSI_REJECT_INVALID_DATA_ACK:
1161 1161 case ISCSI_REJECT_INVALID_PDU_FIELD:
1162 1162 case ISCSI_REJECT_LONG_OPERATION_REJECT:
1163 1163 case ISCSI_REJECT_NEGOTIATION_RESET:
1164 1164 default:
1165 1165 cmn_err(CE_WARN, "iscsi connection(%u/%x) closing connection - "
1166 1166 "target requested reason:0x%x",
1167 1167 icp->conn_oid, irrhp->opcode, irrhp->reason);
1168 1168 status = IDM_STATUS_PROTOCOL_ERROR;
1169 1169 break;
1170 1170 }
1171 1171
1172 1172 return (status);
1173 1173 }
1174 1174
|
↓ open down ↓ |
1174 lines elided |
↑ open up ↑ |
1175 1175
1176 1176 /*
1177 1177 * iscsi_rx_process_rejected_tsk_mgt -
1178 1178 */
1179 1179 /* ARGSUSED */
1180 1180 static idm_status_t
1181 1181 iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic, iscsi_hdr_t *old_ihp)
1182 1182 {
1183 1183 iscsi_sess_t *isp = NULL;
1184 1184 iscsi_cmd_t *icmdp = NULL;
1185 - iscsi_conn_t *icp = NULL;
1185 + iscsi_conn_t *icp = ic->ic_handle;
1186 1186
1187 1187 isp = icp->conn_sess;
1188 1188 ASSERT(old_ihp != NULL);
1189 1189 ASSERT(isp != NULL);
1190 1190
1191 1191 mutex_enter(&icp->conn_queue_active.mutex);
1192 1192 mutex_enter(&isp->sess_cmdsn_mutex);
1193 1193 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1194 1194 isp, old_ihp, &icmdp))) {
1195 1195 mutex_exit(&isp->sess_cmdsn_mutex);
1196 1196 mutex_exit(&icp->conn_queue_active.mutex);
1197 1197 return (IDM_STATUS_PROTOCOL_ERROR);
1198 1198 }
1199 1199 mutex_exit(&isp->sess_cmdsn_mutex);
1200 1200
1201 1201 switch (icmdp->cmd_type) {
1202 1202 case ISCSI_CMD_TYPE_ABORT:
1203 1203 case ISCSI_CMD_TYPE_RESET:
1204 1204 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
1205 1205 icp->conn_sess);
1206 1206 break;
1207 1207 /* We don't send any other task mgr types */
1208 1208 default:
1209 1209 ASSERT(B_FALSE);
1210 1210 break;
1211 1211 }
1212 1212 mutex_exit(&icp->conn_queue_active.mutex);
1213 1213
1214 1214 return (IDM_STATUS_SUCCESS);
1215 1215 }
1216 1216
1217 1217
1218 1218 /*
1219 1219 * iscsi_rx_process_task_mgt_rsp -
1220 1220 */
1221 1221 /* ARGSUSED */
1222 1222 static idm_status_t
1223 1223 iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1224 1224 {
1225 1225 iscsi_sess_t *isp = NULL;
1226 1226 iscsi_scsi_task_mgt_rsp_hdr_t *istmrhp = NULL;
1227 1227 iscsi_cmd_t *icmdp = NULL;
1228 1228 iscsi_conn_t *icp = ic->ic_handle;
1229 1229 idm_status_t status = IDM_STATUS_SUCCESS;
1230 1230
1231 1231 isp = icp->conn_sess;
1232 1232 istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)pdu->isp_hdr;
1233 1233
1234 1234 mutex_enter(&icp->conn_queue_active.mutex);
1235 1235 if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)istmrhp,
1236 1236 &icmdp)) != IDM_STATUS_SUCCESS) {
1237 1237 mutex_exit(&icp->conn_queue_active.mutex);
1238 1238 return (status);
1239 1239 }
1240 1240
1241 1241 switch (icmdp->cmd_type) {
1242 1242 case ISCSI_CMD_TYPE_ABORT:
1243 1243 case ISCSI_CMD_TYPE_RESET:
1244 1244 switch (istmrhp->response) {
1245 1245 case SCSI_TCP_TM_RESP_COMPLETE:
1246 1246 /* success */
1247 1247 iscsi_cmd_state_machine(icmdp,
1248 1248 ISCSI_CMD_EVENT_E3, isp);
1249 1249 break;
1250 1250 case SCSI_TCP_TM_RESP_NO_TASK:
1251 1251 /*
1252 1252 * If the array no longer knows about
1253 1253 * an ABORT RTT and we no longer have
1254 1254 * a parent SCSI command it was just
1255 1255 * completed, free this ABORT resource.
1256 1256 * Otherwise FALLTHRU this will flag a
1257 1257 * protocol problem.
1258 1258 */
1259 1259 if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
1260 1260 (icmdp->cmd_un.abort.icmdp == NULL)) {
1261 1261 iscsi_cmd_state_machine(icmdp,
1262 1262 ISCSI_CMD_EVENT_E4, isp);
1263 1263 break;
1264 1264 }
1265 1265 /* FALLTHRU */
1266 1266 case SCSI_TCP_TM_RESP_REJECTED:
1267 1267 /*
1268 1268 * If the target rejects our reset task,
1269 1269 * we should record the response and complete
1270 1270 * this command with the result.
1271 1271 */
1272 1272 if (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET) {
1273 1273 icmdp->cmd_un.reset.response =
1274 1274 istmrhp->response;
1275 1275 iscsi_cmd_state_machine(icmdp,
1276 1276 ISCSI_CMD_EVENT_E3, isp);
1277 1277 break;
1278 1278 }
1279 1279 /* FALLTHRU */
1280 1280 case SCSI_TCP_TM_RESP_NO_LUN:
1281 1281 case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
1282 1282 case SCSI_TCP_TM_RESP_NO_FAILOVER:
1283 1283 case SCSI_TCP_TM_RESP_IN_PRGRESS:
1284 1284 default:
1285 1285 /*
1286 1286 * Something is out of sync. Flush
1287 1287 * active queues and resync the
1288 1288 * the connection to try and recover
1289 1289 * to a known state.
1290 1290 */
1291 1291 status = IDM_STATUS_PROTOCOL_ERROR;
1292 1292 }
1293 1293 break;
1294 1294
1295 1295 default:
1296 1296 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1297 1297 "received a task mgt response for a non-task mgt "
1298 1298 "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
1299 1299 icmdp->cmd_type);
1300 1300 status = IDM_STATUS_PROTOCOL_ERROR;
1301 1301 break;
1302 1302 }
1303 1303
1304 1304 mutex_exit(&icp->conn_queue_active.mutex);
1305 1305 return (status);
1306 1306 }
1307 1307
1308 1308
1309 1309 /*
1310 1310 * iscsi_rx_process_logout_rsp -
1311 1311 *
1312 1312 */
1313 1313 /* ARGSUSED */
1314 1314 idm_status_t
1315 1315 iscsi_rx_process_logout_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1316 1316 {
1317 1317 iscsi_conn_t *icp = ic->ic_handle;
1318 1318 iscsi_logout_rsp_hdr_t *ilrhp =
1319 1319 (iscsi_logout_rsp_hdr_t *)pdu->isp_hdr;
1320 1320 iscsi_cmd_t *icmdp = NULL;
1321 1321 iscsi_sess_t *isp;
1322 1322 idm_status_t status = IDM_STATUS_SUCCESS;
1323 1323
1324 1324 isp = icp->conn_sess;
1325 1325
1326 1326 if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
1327 1327 cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1328 1328 "received status out of order itt:0x%x statsn:0x%x "
1329 1329 "expstatsn:0x%x", icp->conn_oid, ilrhp->opcode, ilrhp->itt,
1330 1330 ntohl(ilrhp->statsn), icp->conn_expstatsn);
1331 1331 return (IDM_STATUS_PROTOCOL_ERROR);
1332 1332 }
1333 1333
1334 1334 mutex_enter(&icp->conn_queue_active.mutex);
1335 1335 mutex_enter(&isp->sess_cmdsn_mutex);
1336 1336 if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
1337 1337 if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1338 1338 isp, (iscsi_hdr_t *)ilrhp, &icmdp))) {
1339 1339 mutex_exit(&isp->sess_cmdsn_mutex);
1340 1340 mutex_exit(&icp->conn_queue_active.mutex);
1341 1341 return (IDM_STATUS_PROTOCOL_ERROR);
1342 1342 }
1343 1343 }
1344 1344
1345 1345 /* update expcmdsn and maxcmdsn */
1346 1346 iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
1347 1347 ntohl(ilrhp->expcmdsn));
1348 1348 mutex_exit(&isp->sess_cmdsn_mutex);
1349 1349
1350 1350 ISCSI_IO_LOG(CE_NOTE,
1351 1351 "DEBUG: iscsi_rx_process_logout_rsp: response: %d",
1352 1352 ilrhp->response);
1353 1353 switch (ilrhp->response) {
1354 1354 case ISCSI_LOGOUT_CID_NOT_FOUND:
1355 1355 /*
1356 1356 * If the target doesn't know about our connection
1357 1357 * then we can consider our self disconnected.
1358 1358 */
1359 1359 /* FALLTHRU */
1360 1360 case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
1361 1361 /*
1362 1362 * We don't support ErrorRecovery levels above 0
1363 1363 * currently so consider this success.
1364 1364 */
1365 1365 /* FALLTHRU */
1366 1366 case ISCSI_LOGOUT_CLEANUP_FAILED:
1367 1367 /*
1368 1368 * per spec. "cleanup failed for various reasons."
1369 1369 * Although those various reasons are undefined.
1370 1370 * Not sure what to do here. So fake success,
1371 1371 * which will disconnect the connection.
1372 1372 */
1373 1373 /* FALLTHRU */
1374 1374 case ISCSI_LOGOUT_SUCCESS:
1375 1375 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1376 1376 mutex_exit(&icp->conn_queue_active.mutex);
1377 1377 iscsi_drop_conn_cleanup(icp);
1378 1378 break;
1379 1379 default:
1380 1380 mutex_exit(&icp->conn_queue_active.mutex);
1381 1381 status = IDM_STATUS_PROTOCOL_ERROR;
1382 1382 break;
1383 1383
1384 1384 }
1385 1385 return (status);
1386 1386 }
1387 1387
1388 1388 /*
1389 1389 * iscsi_rx_process_async_rsp
1390 1390 *
1391 1391 */
1392 1392 /* ARGSUSED */
1393 1393 static idm_status_t
1394 1394 iscsi_rx_process_async_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1395 1395 {
1396 1396 iscsi_conn_t *icp = ic->ic_handle;
1397 1397 iscsi_sess_t *isp = icp->conn_sess;
1398 1398 idm_status_t rval = IDM_STATUS_SUCCESS;
1399 1399 iscsi_task_t *itp;
1400 1400 iscsi_async_evt_hdr_t *iaehp =
1401 1401 (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
1402 1402
1403 1403 ASSERT(icp != NULL);
1404 1404 ASSERT(pdu != NULL);
1405 1405 ASSERT(isp != NULL);
1406 1406
1407 1407 mutex_enter(&isp->sess_cmdsn_mutex);
1408 1408 if (icp->conn_expstatsn == ntohl(iaehp->statsn)) {
1409 1409 icp->conn_expstatsn++;
1410 1410 } else {
1411 1411 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1412 1412 "received status out of order statsn:0x%x "
1413 1413 "expstatsn:0x%x", icp->conn_oid,
1414 1414 ntohl(iaehp->statsn), icp->conn_expstatsn);
1415 1415 mutex_exit(&isp->sess_cmdsn_mutex);
1416 1416 return (IDM_STATUS_PROTOCOL_ERROR);
1417 1417 }
1418 1418 mutex_exit(&isp->sess_cmdsn_mutex);
1419 1419
1420 1420 switch (iaehp->async_event) {
1421 1421 case ISCSI_ASYNC_EVENT_SCSI_EVENT:
1422 1422 /*
1423 1423 * SCSI asynchronous event is reported in
1424 1424 * the sense data. Sense data that accompanies
1425 1425 * the report in the data segment identifies the
1426 1426 * condition. If the target supports SCSI
1427 1427 * asynchronous events reporting (see [SAM2])
1428 1428 * as indicated in the stardard INQUIRY data
1429 1429 * (see [SPC3]), its use may be enabled by
1430 1430 * parameters in the SCSI control mode page
1431 1431 * (see [SPC3]).
1432 1432 *
1433 1433 * T-10 has removed SCSI asunchronous events
1434 1434 * from the standard. Although we have seen
1435 1435 * a couple targets still spending these requests.
1436 1436 * Those targets were specifically sending them
1437 1437 * for notification of a LUN/Volume change
1438 1438 * (ex. LUN addition/removal). Fire the enumeration
1439 1439 * to handle the change.
1440 1440 */
1441 1441 if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1442 1442 rw_enter(&isp->sess_state_rwlock, RW_READER);
1443 1443 if (isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) {
1444 1444 (void) iscsi_sess_enum_request(isp, B_FALSE,
1445 1445 isp->sess_state_event_count);
1446 1446 }
1447 1447 rw_exit(&isp->sess_state_rwlock);
1448 1448 }
1449 1449 break;
1450 1450
1451 1451 case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
1452 1452 /*
1453 1453 * We've been asked to logout by the target --
1454 1454 * we need to treat this differently from a normal logout
1455 1455 * due to a discovery failure. Normal logouts result in
1456 1456 * an N3 event to the session state machine and an offline
1457 1457 * of the lun. In this case we want to put the connection
1458 1458 * into "failed" state and generate N5 to the session state
1459 1459 * machine since the initiator logged out at the target's
1460 1460 * request. To track this we set a flag indicating we
1461 1461 * received this async logout request from the tharget
1462 1462 */
1463 1463 mutex_enter(&icp->conn_state_mutex);
1464 1464 icp->conn_async_logout = B_TRUE;
1465 1465 mutex_exit(&icp->conn_state_mutex);
1466 1466
1467 1467 /* Hold is released in iscsi_handle_logout. */
1468 1468 idm_conn_hold(ic);
1469 1469
1470 1470 /* Target has requested this connection to logout. */
1471 1471 itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1472 1472 itp->t_arg = icp;
1473 1473 itp->t_blocking = B_FALSE;
1474 1474 if (ddi_taskq_dispatch(isp->sess_login_taskq,
1475 1475 (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1476 1476 DDI_SUCCESS) {
1477 1477 idm_conn_rele(ic);
1478 1478 /* Disconnect if we couldn't dispatch the task */
1479 1479 idm_ini_conn_disconnect(ic);
1480 1480 }
1481 1481 break;
1482 1482
1483 1483 case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
1484 1484 /*
1485 1485 * Target is going to drop our connection.
1486 1486 * param1 - CID which will be dropped.
1487 1487 * param2 - Min time to reconnect.
1488 1488 * param3 - Max time to reconnect.
1489 1489 *
1490 1490 * For now just let fail as another disconnect.
1491 1491 *
1492 1492 * MC/S Once we support > 1 connections then
1493 1493 * we need to check the CID and drop that
1494 1494 * specific connection.
1495 1495 */
1496 1496 iscsi_conn_set_login_min_max(icp, iaehp->param2,
1497 1497 iaehp->param3);
1498 1498 idm_ini_conn_disconnect(ic);
1499 1499 break;
1500 1500
1501 1501 case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
1502 1502 /*
1503 1503 * Target is going to drop ALL connections.
1504 1504 * param2 - Min time to reconnect.
1505 1505 * param3 - Max time to reconnect.
1506 1506 *
1507 1507 * For now just let fail as anyother disconnect.
1508 1508 *
1509 1509 * MC/S Once we support more than > 1 connections
1510 1510 * then we need to drop all connections on the
1511 1511 * session.
1512 1512 */
1513 1513 iscsi_conn_set_login_min_max(icp, iaehp->param2,
1514 1514 iaehp->param3);
1515 1515 idm_ini_conn_disconnect(ic);
1516 1516 break;
1517 1517
1518 1518 case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
1519 1519 /*
1520 1520 * Target requests parameter negotiation
1521 1521 * on this connection.
1522 1522 *
1523 1523 * The initiator must honor this request. For
1524 1524 * now we will request a logout. We can't
1525 1525 * just ignore this or it might force corruption?
1526 1526 */
1527 1527
1528 1528 /* Hold is released in iscsi_handle_logout */
1529 1529 idm_conn_hold(ic);
1530 1530 itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1531 1531 itp->t_arg = icp;
1532 1532 itp->t_blocking = B_FALSE;
1533 1533 if (ddi_taskq_dispatch(isp->sess_login_taskq,
1534 1534 (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1535 1535 DDI_SUCCESS) {
1536 1536 /* Disconnect if we couldn't dispatch the task */
1537 1537 idm_conn_rele(ic);
1538 1538 idm_ini_conn_disconnect(ic);
1539 1539 }
1540 1540 break;
1541 1541
1542 1542 case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
1543 1543 /*
1544 1544 * We currently don't handle any vendor
1545 1545 * specific async events. So just ignore
1546 1546 * the request.
1547 1547 */
1548 1548 idm_ini_conn_disconnect(ic);
1549 1549 break;
1550 1550 default:
1551 1551 rval = IDM_STATUS_PROTOCOL_ERROR;
1552 1552 }
1553 1553
1554 1554 return (rval);
1555 1555 }
1556 1556
1557 1557 /*
1558 1558 * iscsi_rx_process_text_rsp - processes iSCSI text response. It sets
1559 1559 * the cmd_result field of the command data structure with the actual
1560 1560 * status value instead of returning the status value. The return value
1561 1561 * is SUCCESS in order to let iscsi_handle_text control the operation of
1562 1562 * a text request.
1563 1563 * Text requests are a handled a little different than other types of
1564 1564 * iSCSI commands because the initiator sends additional empty text requests
1565 1565 * in order to obtain the remaining responses required to complete the
1566 1566 * request. iscsi_handle_text controls the operation of text request, while
1567 1567 * iscsi_rx_process_text_rsp just process the current response.
1568 1568 */
1569 1569 static idm_status_t
1570 1570 iscsi_rx_process_text_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1571 1571 {
1572 1572 iscsi_sess_t *isp = NULL;
1573 1573 iscsi_text_rsp_hdr_t *ithp =
1574 1574 (iscsi_text_rsp_hdr_t *)pdu->isp_hdr;
1575 1575 iscsi_conn_t *icp = ic->ic_handle;
1576 1576 iscsi_cmd_t *icmdp = NULL;
1577 1577 boolean_t final = B_FALSE;
1578 1578 uint32_t data_len;
1579 1579 uint8_t *data = pdu->isp_data;
1580 1580 idm_status_t rval;
1581 1581
1582 1582 isp = icp->conn_sess;
1583 1583
1584 1584 mutex_enter(&icp->conn_queue_active.mutex);
1585 1585 if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)ithp,
1586 1586 &icmdp)) != IDM_STATUS_SUCCESS) {
1587 1587 mutex_exit(&icp->conn_queue_active.mutex);
1588 1588 return (rval);
1589 1589 }
1590 1590
1591 1591 /* update local final response flag */
1592 1592 if (ithp->flags & ISCSI_FLAG_FINAL) {
1593 1593 final = B_TRUE;
1594 1594 }
1595 1595
1596 1596 /*
1597 1597 * validate received TTT value. RFC3720 specifies the following:
1598 1598 * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
1599 1599 * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
1600 1600 * In addition, the received TTT value must not change between
1601 1601 * responses of a long text response
1602 1602 */
1603 1603 if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
1604 1604 ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
1605 1605 icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1606 1606 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1607 1607 mutex_exit(&icp->conn_queue_active.mutex);
1608 1608 cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1609 1609 "received text response with invalid flags:0x%x or "
1610 1610 "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
1611 1611 return (IDM_STATUS_PROTOCOL_ERROR);
1612 1612 }
1613 1613
1614 1614 if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
1615 1615 (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
1616 1616 (final == B_FALSE)) {
1617 1617 /* TTT should have matched reserved value */
1618 1618 icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1619 1619 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1620 1620 mutex_exit(&icp->conn_queue_active.mutex);
1621 1621 cmn_err(CE_WARN, "iscsi connection(%u) protocol "
1622 1622 "error - received text response with invalid "
1623 1623 "ttt:0x%x", icp->conn_oid, ithp->ttt);
1624 1624 return (IDM_STATUS_PROTOCOL_ERROR);
1625 1625 }
1626 1626
1627 1627 /*
1628 1628 * If this is first response, save away TTT value for later use
1629 1629 * in a long text request/response sequence
1630 1630 */
1631 1631 if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
1632 1632 icmdp->cmd_un.text.ttt = ithp->ttt;
1633 1633 }
1634 1634
1635 1635 data_len = ntoh24(ithp->dlength);
1636 1636
1637 1637 /* check whether enough buffer available to copy data */
1638 1638 if ((icmdp->cmd_un.text.total_rx_len + data_len) >
1639 1639 icmdp->cmd_un.text.buf_len) {
1640 1640 icmdp->cmd_un.text.total_rx_len += data_len;
1641 1641 icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
1642 1642 /*
1643 1643 * DATA_OVERFLOW will result in a SUCCESS return so that
1644 1644 * iscsi_handle_text can continue to obtain the remaining
1645 1645 * text response if needed.
1646 1646 */
1647 1647 } else {
1648 1648 char *buf_data = (icmdp->cmd_un.text.buf +
1649 1649 icmdp->cmd_un.text.offset);
1650 1650
1651 1651 bcopy(data, buf_data, data_len);
1652 1652 icmdp->cmd_un.text.offset += data_len;
1653 1653 icmdp->cmd_un.text.total_rx_len += data_len;
1654 1654 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
1655 1655 bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
1656 1656 sizeof (icmdp->cmd_un.text.lun));
1657 1657 }
1658 1658
1659 1659 /* update stage */
1660 1660 if (final == B_TRUE) {
1661 1661 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1662 1662 } else {
1663 1663 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
1664 1664 }
1665 1665
1666 1666 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1667 1667 mutex_exit(&icp->conn_queue_active.mutex);
1668 1668 return (IDM_STATUS_SUCCESS);
1669 1669 }
1670 1670
1671 1671 /*
1672 1672 * iscsi_rx_process_scsi_itt_to_icmdp - Lookup itt using IDM to find matching
1673 1673 * icmdp. Verify itt in hdr and icmdp are the same.
1674 1674 */
1675 1675 static iscsi_status_t
1676 1676 iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp, idm_conn_t *ic,
1677 1677 iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp)
1678 1678 {
1679 1679 idm_task_t *itp;
1680 1680
1681 1681 ASSERT(isp != NULL);
1682 1682 ASSERT(ihp != NULL);
1683 1683 ASSERT(icmdp != NULL);
1684 1684 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1685 1685 itp = idm_task_find_and_complete(ic, ihp->itt, ISCSI_INI_TASK_TTT);
1686 1686 if (itp == NULL) {
1687 1687 cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1688 1688 "received unknown itt:0x%x - protocol error",
1689 1689 isp->sess_oid, ihp->itt);
1690 1690 return (ISCSI_STATUS_INTERNAL_ERROR);
1691 1691 }
1692 1692 *icmdp = itp->idt_private;
1693 1693
1694 1694 idm_task_rele(itp);
1695 1695
1696 1696 return (ISCSI_STATUS_SUCCESS);
1697 1697
1698 1698 }
1699 1699
1700 1700 /*
1701 1701 * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
1702 1702 * cmd table to find matching icmdp. Verify itt in hdr and
1703 1703 * icmdp are the same.
1704 1704 */
1705 1705 static iscsi_status_t
1706 1706 iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
1707 1707 iscsi_cmd_t **icmdp)
1708 1708 {
1709 1709 int cmd_table_idx = 0;
1710 1710
1711 1711 ASSERT(isp != NULL);
1712 1712 ASSERT(ihp != NULL);
1713 1713 ASSERT(icmdp != NULL);
1714 1714 ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1715 1715
1716 1716 /* try to find an associated iscsi_pkt */
1717 1717 cmd_table_idx = (ihp->itt - IDM_TASKIDS_MAX) % ISCSI_CMD_TABLE_SIZE;
1718 1718 if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
1719 1719 cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1720 1720 "received unknown itt:0x%x - protocol error",
1721 1721 isp->sess_oid, ihp->itt);
1722 1722 return (ISCSI_STATUS_INTERNAL_ERROR);
1723 1723 }
1724 1724
1725 1725 /* verify itt */
1726 1726 if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
1727 1727 cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1728 1728 " which is out of sync with itt:0x%x", isp->sess_oid,
1729 1729 ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
1730 1730 return (ISCSI_STATUS_INTERNAL_ERROR);
1731 1731 }
1732 1732
1733 1733 /* ensure that icmdp is still in Active state */
1734 1734 if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
1735 1735 ISCSI_CMD_STATE_ACTIVE) {
1736 1736 cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1737 1737 "but icmdp (%p) is not in active state",
1738 1738 isp->sess_oid, ihp->itt,
1739 1739 (void *)isp->sess_cmd_table[cmd_table_idx]);
1740 1740 return (ISCSI_STATUS_INTERNAL_ERROR);
1741 1741 }
1742 1742
1743 1743 /* make sure this is a SCSI cmd */
1744 1744 *icmdp = isp->sess_cmd_table[cmd_table_idx];
1745 1745
1746 1746 return (ISCSI_STATUS_SUCCESS);
1747 1747 }
1748 1748
1749 1749 /*
1750 1750 * +--------------------------------------------------------------------+
1751 1751 * | End of protocol receive routines |
1752 1752 * +--------------------------------------------------------------------+
1753 1753 */
1754 1754
1755 1755 /*
1756 1756 * +--------------------------------------------------------------------+
1757 1757 * | Beginning of protocol send routines |
1758 1758 * +--------------------------------------------------------------------+
1759 1759 */
1760 1760
1761 1761
1762 1762 /*
1763 1763 * iscsi_tx_thread - This thread is the driving point for all
1764 1764 * iSCSI PDUs after login. No PDUs should call idm_pdu_tx()
1765 1765 * directly they should be funneled through iscsi_tx_thread.
1766 1766 */
1767 1767 void
1768 1768 iscsi_tx_thread(iscsi_thread_t *thread, void *arg)
1769 1769 {
1770 1770 iscsi_conn_t *icp = (iscsi_conn_t *)arg;
1771 1771 iscsi_sess_t *isp = NULL;
1772 1772 iscsi_cmd_t *icmdp = NULL;
1773 1773 clock_t tout;
1774 1774 int ret = 1;
1775 1775
1776 1776 ASSERT(icp != NULL);
1777 1777 isp = icp->conn_sess;
1778 1778 ASSERT(isp != NULL);
1779 1779 ASSERT(thread != NULL);
1780 1780 ASSERT(thread->signature == SIG_ISCSI_THREAD);
1781 1781
1782 1782 tout = SEC_TO_TICK(1);
1783 1783 /*
1784 1784 * Transfer icmdps until shutdown by owning session.
1785 1785 */
1786 1786 while (ret != 0) {
1787 1787
1788 1788 isp->sess_window_open = B_TRUE;
1789 1789 /*
1790 1790 * While the window is open, there are commands available
1791 1791 * to send and the session state allows those commands to
1792 1792 * be sent try to transfer them.
1793 1793 */
1794 1794 mutex_enter(&isp->sess_queue_pending.mutex);
1795 1795 while ((isp->sess_window_open == B_TRUE) &&
1796 1796 ((icmdp = isp->sess_queue_pending.head) != NULL)) {
1797 1797 if (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
1798 1798 (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
1799 1799 (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN)) {
1800 1800
1801 1801 /* update command with this connection info */
1802 1802 icmdp->cmd_conn = icp;
1803 1803 /* attempt to send this command */
1804 1804 iscsi_cmd_state_machine(icmdp,
1805 1805 ISCSI_CMD_EVENT_E2, isp);
1806 1806
1807 1807 ASSERT(!mutex_owned(
1808 1808 &isp->sess_queue_pending.mutex));
1809 1809 mutex_enter(&isp->sess_queue_pending.mutex);
1810 1810 } else {
1811 1811 while (icmdp != NULL) {
1812 1812 if ((icmdp->cmd_type !=
1813 1813 ISCSI_CMD_TYPE_SCSI) &&
1814 1814 (ISCSI_CONN_STATE_FULL_FEATURE
1815 1815 (icp->conn_state) != B_TRUE)) {
1816 1816 icmdp->cmd_misc_flags |=
1817 1817 ISCSI_CMD_MISCFLAG_STUCK;
1818 1818 } else if (icp->conn_state !=
1819 1819 ISCSI_CONN_STATE_LOGGED_IN) {
1820 1820 icmdp->cmd_misc_flags |=
1821 1821 ISCSI_CMD_MISCFLAG_STUCK;
1822 1822 }
1823 1823 icmdp = icmdp->cmd_next;
1824 1824 }
1825 1825 break;
1826 1826 }
1827 1827 }
1828 1828 mutex_exit(&isp->sess_queue_pending.mutex);
1829 1829
1830 1830 /*
1831 1831 * Go to sleep until there is something new
1832 1832 * to process (awoken via cv_boardcast).
1833 1833 * Or the timer goes off.
1834 1834 */
1835 1835 ret = iscsi_thread_wait(thread, tout);
1836 1836 }
1837 1837
1838 1838 }
1839 1839
1840 1840
1841 1841 /*
1842 1842 * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
1843 1843 *
1844 1844 * Just prior to sending the command to the networking layer the
1845 1845 * pending queue lock will be dropped. At this point only local
1846 1846 * resources will be used, not the icmdp. Holding the queue lock
1847 1847 * across the networking call can lead to a hang. (This is due
1848 1848 * to the the target driver and networking layers competing use
1849 1849 * of the timeout() resources and the queue lock being held for
1850 1850 * both sides.) Upon the completion of this command the lock
1851 1851 * will have been re-acquired.
1852 1852 */
1853 1853 iscsi_status_t
1854 1854 iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1855 1855 {
1856 1856 iscsi_status_t rval = ISCSI_STATUS_INTERNAL_ERROR;
1857 1857
1858 1858 ASSERT(isp != NULL);
1859 1859 ASSERT(icmdp != NULL);
1860 1860
1861 1861 /* transfer specific command type */
1862 1862 switch (icmdp->cmd_type) {
1863 1863 case ISCSI_CMD_TYPE_SCSI:
1864 1864 rval = iscsi_tx_scsi(isp, icmdp);
1865 1865 break;
1866 1866 case ISCSI_CMD_TYPE_NOP:
1867 1867 rval = iscsi_tx_nop(isp, icmdp);
1868 1868 break;
1869 1869 case ISCSI_CMD_TYPE_ABORT:
1870 1870 rval = iscsi_tx_abort(isp, icmdp);
1871 1871 break;
1872 1872 case ISCSI_CMD_TYPE_RESET:
1873 1873 rval = iscsi_tx_reset(isp, icmdp);
1874 1874 break;
1875 1875 case ISCSI_CMD_TYPE_LOGOUT:
1876 1876 rval = iscsi_tx_logout(isp, icmdp);
1877 1877 break;
1878 1878 case ISCSI_CMD_TYPE_TEXT:
1879 1879 rval = iscsi_tx_text(isp, icmdp);
1880 1880 break;
1881 1881 default:
1882 1882 cmn_err(CE_WARN, "iscsi_tx_cmd: invalid cmdtype: %d",
1883 1883 icmdp->cmd_type);
1884 1884 ASSERT(FALSE);
1885 1885 }
1886 1886
1887 1887 ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1888 1888 return (rval);
1889 1889 }
1890 1890
1891 1891 /*
1892 1892 * a variable length cdb can be up to 16K, but we obviously don't want
1893 1893 * to put that on the stack; go with 200 bytes; if we get something
1894 1894 * bigger than that we will kmem_alloc a buffer
1895 1895 */
1896 1896 #define DEF_CDB_LEN 200
1897 1897
1898 1898 /*
1899 1899 * given the size of the cdb, return how many bytes the header takes,
1900 1900 * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
1901 1901 * stored in the basic header, minus sizeof (ahs_extscb)
1902 1902 */
1903 1903 #define ADDLHDRSZ(x) (sizeof (iscsi_addl_hdr_t) + (x) - \
1904 1904 16 - 4)
1905 1905
1906 1906 static void
1907 1907 iscsi_tx_init_hdr(iscsi_sess_t *isp, iscsi_conn_t *icp,
1908 1908 iscsi_text_hdr_t *ihp, int opcode, iscsi_cmd_t *icmdp)
1909 1909 {
1910 1910 ihp->opcode = opcode;
1911 1911 ihp->itt = icmdp->cmd_itt;
1912 1912 mutex_enter(&isp->sess_cmdsn_mutex);
1913 1913 icmdp->cmd_sn = isp->sess_cmdsn;
1914 1914 ihp->cmdsn = htonl(isp->sess_cmdsn);
1915 1915 isp->sess_cmdsn++;
1916 1916 mutex_exit(&isp->sess_cmdsn_mutex);
1917 1917 ihp->expstatsn = htonl(icp->conn_expstatsn);
1918 1918 icp->conn_laststatsn = icp->conn_expstatsn;
1919 1919 }
1920 1920
1921 1921
1922 1922 static void
1923 1923 iscsi_tx_scsi_data(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp,
1924 1924 iscsi_conn_t *icp, idm_pdu_t *pdu)
1925 1925 {
1926 1926 struct buf *bp = NULL;
1927 1927 size_t buflen = 0;
1928 1928 uint32_t first_burst_length = 0;
1929 1929 struct scsi_pkt *pkt;
1930 1930
1931 1931 pkt = icmdp->cmd_un.scsi.pkt;
1932 1932 bp = icmdp->cmd_un.scsi.bp;
1933 1933 if ((bp != NULL) && bp->b_bcount) {
1934 1934 buflen = bp->b_bcount;
1935 1935 first_burst_length =
1936 1936 icp->conn_params.first_burst_length;
1937 1937
1938 1938 if (bp->b_flags & B_READ) {
1939 1939 ihp->flags = ISCSI_FLAG_FINAL;
1940 1940 /*
1941 1941 * fix problem where OS sends bp (B_READ &
1942 1942 * b_bcount!=0) for a TUR or START_STOP.
1943 1943 * (comment came from cisco code.)
1944 1944 */
1945 1945 if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
1946 1946 (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
1947 1947 ihp->flags |= ISCSI_FLAG_CMD_READ;
1948 1948 ihp->data_length = htonl(buflen);
1949 1949 }
1950 1950 } else {
1951 1951 ihp->flags = ISCSI_FLAG_CMD_WRITE;
1952 1952 /*
1953 1953 * FinalBit on the the iSCSI PDU denotes this
1954 1954 * is the last PDU in the sequence.
1955 1955 *
1956 1956 * initial_r2t = true means R2T is required
1957 1957 * for additional PDU, so there will be no more
1958 1958 * unsolicited PDUs following
1959 1959 */
1960 1960 if (icp->conn_params.initial_r2t) {
1961 1961 ihp->flags |= ISCSI_FLAG_FINAL;
1962 1962 }
1963 1963
1964 1964 /* Check if we should send ImmediateData */
1965 1965 if (icp->conn_params.immediate_data) {
1966 1966 pdu->isp_data =
1967 1967 (uint8_t *)icmdp->
1968 1968 cmd_un.scsi.bp->b_un.b_addr;
1969 1969
1970 1970 pdu->isp_datalen = MIN(MIN(buflen,
1971 1971 first_burst_length),
1972 1972 icmdp->cmd_conn->conn_params.
1973 1973 max_xmit_data_seg_len);
1974 1974
1975 1975 /*
1976 1976 * if everything fits immediate, or
1977 1977 * we can send all burst data immediate
1978 1978 * (not unsol), set F
1979 1979 */
1980 1980 /*
1981 1981 * XXX This doesn't look right -- it's not
1982 1982 * clear how we can handle transmitting
1983 1983 * any unsolicited data. It looks like
1984 1984 * we only support immediate data. So what
1985 1985 * happens if we don't set ISCSI_FLAG_FINAL?
1986 1986 *
1987 1987 * Unless there's magic code somewhere that
1988 1988 * is sending the remaining PDU's we should
1989 1989 * simply set ISCSI_FLAG_FINAL and forget
1990 1990 * about sending unsolicited data. The big
1991 1991 * win is the immediate data anyway for small
1992 1992 * PDU's.
1993 1993 */
1994 1994 if ((pdu->isp_datalen == buflen) ||
1995 1995 (pdu->isp_datalen == first_burst_length)) {
1996 1996 ihp->flags |= ISCSI_FLAG_FINAL;
1997 1997 }
1998 1998
1999 1999 hton24(ihp->dlength, pdu->isp_datalen);
2000 2000 }
2001 2001 /* total data transfer length */
2002 2002 ihp->data_length = htonl(buflen);
2003 2003 }
2004 2004 } else {
2005 2005 ihp->flags = ISCSI_FLAG_FINAL;
2006 2006 }
2007 2007 icmdp->cmd_un.scsi.data_transferred += pdu->isp_datalen;
2008 2008 /* XXX How is this different from the code above? */
2009 2009 /* will idm send the next data command up to burst length? */
2010 2010 /* send the burstlen if we haven't sent immediate data */
2011 2011 /* CRM: should idm send difference min(buflen, first_burst) and imm? */
2012 2012 /* (MIN(first_burst_length, buflen) - imdata > 0) */
2013 2013 /* CRM_LATER: change this to generate unsolicited pdu */
2014 2014 if ((buflen > 0) &&
2015 2015 ((bp->b_flags & B_READ) == 0) &&
2016 2016 (icp->conn_params.initial_r2t == 0) &&
2017 2017 pdu->isp_datalen == 0) {
2018 2018
2019 2019 pdu->isp_datalen = MIN(first_burst_length, buflen);
2020 2020 if ((pdu->isp_datalen == buflen) ||
2021 2021 (pdu->isp_datalen == first_burst_length)) {
2022 2022 ihp->flags |= ISCSI_FLAG_FINAL;
2023 2023 }
2024 2024 pdu->isp_data = (uint8_t *)icmdp->cmd_un.scsi.bp->b_un.b_addr;
2025 2025 hton24(ihp->dlength, pdu->isp_datalen);
2026 2026 }
2027 2027 }
2028 2028
2029 2029 static void
2030 2030 iscsi_tx_scsi_init_pkt(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp)
2031 2031 {
2032 2032 struct scsi_pkt *pkt;
2033 2033
2034 2034 pkt = icmdp->cmd_un.scsi.pkt;
2035 2035 pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
2036 2036 pkt->pkt_reason = CMD_INCOMPLETE;
2037 2037
2038 2038 /* tagged queuing */
2039 2039 if (pkt->pkt_flags & FLAG_HTAG) {
2040 2040 ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
2041 2041 } else if (pkt->pkt_flags & FLAG_OTAG) {
2042 2042 ihp->flags |= ISCSI_ATTR_ORDERED;
2043 2043 } else if (pkt->pkt_flags & FLAG_STAG) {
2044 2044 ihp->flags |= ISCSI_ATTR_SIMPLE;
2045 2045 } else {
2046 2046 /* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
2047 2047 /* EMPTY */
2048 2048 }
2049 2049
2050 2050 /* iscsi states lun is based on spc.2 */
2051 2051 ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
2052 2052
2053 2053 if (icmdp->cmd_un.scsi.cmdlen <= 16) {
2054 2054 /* copy the SCSI Command Block into the PDU */
2055 2055 bcopy(pkt->pkt_cdbp, ihp->scb,
2056 2056 icmdp->cmd_un.scsi.cmdlen);
2057 2057 } else {
2058 2058 iscsi_addl_hdr_t *iahp;
2059 2059
2060 2060 iahp = (iscsi_addl_hdr_t *)ihp;
2061 2061
2062 2062 ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
2063 2063 sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
2064 2064 iahp->ahs_hlen_hi = 0;
2065 2065 iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
2066 2066 iahp->ahs_key = 0x01;
2067 2067 iahp->ahs_resv = 0;
2068 2068 bcopy(pkt->pkt_cdbp, ihp->scb, 16);
2069 2069 bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
2070 2070 icmdp->cmd_un.scsi.cmdlen);
2071 2071 }
2072 2072
2073 2073 /*
2074 2074 * Update all values before transfering.
2075 2075 * We should never touch the icmdp after
2076 2076 * transfering if there is no more data
2077 2077 * to send. The only case the idm_pdu_tx()
2078 2078 * will fail is a on a connection disconnect
2079 2079 * in that case the command will be flushed.
2080 2080 */
2081 2081 pkt->pkt_state |= STATE_SENT_CMD;
2082 2082 }
2083 2083
2084 2084 static void
2085 2085 iscsi_tx_scsi_init_task(iscsi_cmd_t *icmdp, iscsi_conn_t *icp,
2086 2086 iscsi_scsi_cmd_hdr_t *ihp)
2087 2087 {
2088 2088 idm_task_t *itp;
2089 2089 struct buf *bp = NULL;
2090 2090 uint32_t data_length;
2091 2091
2092 2092 bp = icmdp->cmd_un.scsi.bp;
2093 2093
2094 2094 itp = icmdp->cmd_itp;
2095 2095 ASSERT(itp != NULL);
2096 2096 data_length = ntohl(ihp->data_length);
2097 2097 ISCSI_IO_LOG(CE_NOTE,
2098 2098 "DEBUG: iscsi_tx_init_task: task_start: %p idt_tt: %x cmdsn: %x "
2099 2099 "sess_cmdsn: %x cmd: %p "
2100 2100 "cmdtype: %d datalen: %u",
2101 2101 (void *)itp, itp->idt_tt, ihp->cmdsn, icp->conn_sess->sess_cmdsn,
2102 2102 (void *)icmdp, icmdp->cmd_type, data_length);
2103 2103 if (data_length > 0) {
2104 2104 if (bp->b_flags & B_READ) {
2105 2105 icmdp->cmd_un.scsi.ibp_ibuf =
2106 2106 idm_buf_alloc(icp->conn_ic,
2107 2107 bp->b_un.b_addr, bp->b_bcount);
2108 2108 if (icmdp->cmd_un.scsi.ibp_ibuf)
2109 2109 idm_buf_bind_in(itp,
2110 2110 icmdp->cmd_un.scsi.ibp_ibuf);
2111 2111 } else {
2112 2112 icmdp->cmd_un.scsi.ibp_obuf =
2113 2113 idm_buf_alloc(icp->conn_ic,
2114 2114 bp->b_un.b_addr, bp->b_bcount);
2115 2115 if (icmdp->cmd_un.scsi.ibp_obuf)
2116 2116 idm_buf_bind_out(itp,
2117 2117 icmdp->cmd_un.scsi.ibp_obuf);
2118 2118 }
2119 2119 ISCSI_IO_LOG(CE_NOTE,
2120 2120 "DEBUG: pdu_tx: task_start(%s): %p ic: %p idt_tt: %x "
2121 2121 "cmdsn: %x sess_cmdsn: %x sess_expcmdsn: %x obuf: %p "
2122 2122 "cmdp: %p cmdtype: %d "
2123 2123 "buflen: %lu " "bpaddr: %p datalen: %u ",
2124 2124 bp->b_flags & B_READ ? "B_READ" : "B_WRITE",
2125 2125 (void *)itp, (void *)icp->conn_ic,
2126 2126 itp->idt_tt, ihp->cmdsn,
2127 2127 icp->conn_sess->sess_cmdsn,
2128 2128 icp->conn_sess->sess_expcmdsn,
2129 2129 (void *)icmdp->cmd_un.scsi.ibp_ibuf,
2130 2130 (void *)icmdp, icmdp->cmd_type, bp->b_bcount,
2131 2131 (void *)bp->b_un.b_addr,
2132 2132 data_length);
2133 2133 }
2134 2134
2135 2135 /*
2136 2136 * Task is now active
2137 2137 */
2138 2138 idm_task_start(itp, ISCSI_INI_TASK_TTT);
2139 2139 }
2140 2140
2141 2141 /*
2142 2142 * iscsi_tx_scsi -
2143 2143 *
2144 2144 */
2145 2145 static iscsi_status_t
2146 2146 iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2147 2147 {
2148 2148 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2149 2149 iscsi_conn_t *icp = NULL;
2150 2150 struct scsi_pkt *pkt = NULL;
2151 2151 iscsi_scsi_cmd_hdr_t *ihp = NULL;
2152 2152 int cdblen = 0;
2153 2153 idm_pdu_t *pdu;
2154 2154 int len;
2155 2155
2156 2156 ASSERT(isp != NULL);
2157 2157 ASSERT(icmdp != NULL);
2158 2158
2159 2159 pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2160 2160
2161 2161 pkt = icmdp->cmd_un.scsi.pkt;
2162 2162 ASSERT(pkt != NULL);
2163 2163 icp = icmdp->cmd_conn;
2164 2164 ASSERT(icp != NULL);
2165 2165
2166 2166 /* Reset counts in case we are on a retry */
2167 2167 icmdp->cmd_un.scsi.data_transferred = 0;
2168 2168
2169 2169 if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
2170 2170 cdblen = icmdp->cmd_un.scsi.cmdlen;
2171 2171 ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
2172 2172 len = ADDLHDRSZ(cdblen);
2173 2173 } else {
2174 2174 /*
2175 2175 * only bzero the basic header; the additional header
2176 2176 * will be set up correctly later, if needed
2177 2177 */
2178 2178 ihp = kmem_zalloc(sizeof (iscsi_scsi_cmd_hdr_t), KM_SLEEP);
2179 2179 len = sizeof (iscsi_scsi_cmd_hdr_t);
2180 2180 }
2181 2181
2182 2182 iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ihp,
2183 2183 ISCSI_OP_SCSI_CMD, icmdp);
2184 2184
2185 2185 idm_pdu_init(pdu, icp->conn_ic, (void *)icmdp, &iscsi_tx_done);
2186 2186 idm_pdu_init_hdr(pdu, (uint8_t *)ihp, len);
2187 2187 pdu->isp_data = NULL;
2188 2188 pdu->isp_datalen = 0;
2189 2189
2190 2190 /*
2191 2191 * Sestion 12.11 of the iSCSI specification has a good table
2192 2192 * describing when uncolicited data and/or immediate data
2193 2193 * should be sent.
2194 2194 */
2195 2195
2196 2196 iscsi_tx_scsi_data(icmdp, ihp, icp, pdu);
2197 2197
2198 2198 iscsi_tx_scsi_init_pkt(icmdp, ihp);
2199 2199
2200 2200 /* Calls idm_task_start */
2201 2201 iscsi_tx_scsi_init_task(icmdp, icp, ihp);
2202 2202
2203 2203 mutex_exit(&isp->sess_queue_pending.mutex);
2204 2204
2205 2205 idm_pdu_tx(pdu);
2206 2206
2207 2207 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2208 2208
2209 2209 return (rval);
2210 2210 }
2211 2211
2212 2212
2213 2213 /* ARGSUSED */
2214 2214 static void
2215 2215 iscsi_tx_done(idm_pdu_t *pdu, idm_status_t status)
2216 2216 {
2217 2217 kmem_free((iscsi_hdr_t *)pdu->isp_hdr, pdu->isp_hdrlen);
2218 2218 kmem_free(pdu, sizeof (idm_pdu_t));
2219 2219 }
2220 2220
2221 2221
2222 2222 static void
2223 2223 iscsi_tx_pdu(iscsi_conn_t *icp, int opcode, void *hdr, int hdrlen,
2224 2224 iscsi_cmd_t *icmdp)
2225 2225 {
2226 2226 idm_pdu_t *tx_pdu;
2227 2227 iscsi_hdr_t *ihp = (iscsi_hdr_t *)hdr;
2228 2228
2229 2229 tx_pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2230 2230 ASSERT(tx_pdu != NULL);
2231 2231
2232 2232 idm_pdu_init(tx_pdu, icp->conn_ic, icmdp, &iscsi_tx_done);
2233 2233 idm_pdu_init_hdr(tx_pdu, hdr, hdrlen);
2234 2234 if (opcode == ISCSI_OP_TEXT_CMD) {
2235 2235 idm_pdu_init_data(tx_pdu,
2236 2236 (uint8_t *)icmdp->cmd_un.text.buf,
2237 2237 ntoh24(ihp->dlength));
2238 2238 }
2239 2239
2240 2240 mutex_exit(&icp->conn_sess->sess_queue_pending.mutex);
2241 2241 idm_pdu_tx(tx_pdu);
2242 2242 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2243 2243 }
2244 2244
2245 2245
2246 2246 /*
2247 2247 * iscsi_tx_nop -
2248 2248 *
2249 2249 */
2250 2250 static iscsi_status_t
2251 2251 iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2252 2252 {
2253 2253 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2254 2254 iscsi_conn_t *icp = NULL;
2255 2255 iscsi_nop_out_hdr_t *inohp;
2256 2256
2257 2257 ASSERT(isp != NULL);
2258 2258 ASSERT(icmdp != NULL);
2259 2259 icp = icmdp->cmd_conn;
2260 2260 ASSERT(icp != NULL);
2261 2261
2262 2262 inohp = kmem_zalloc(sizeof (iscsi_nop_out_hdr_t), KM_SLEEP);
2263 2263 ASSERT(inohp != NULL);
2264 2264
2265 2265 inohp->opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
2266 2266 inohp->flags = ISCSI_FLAG_FINAL;
2267 2267 inohp->itt = icmdp->cmd_itt;
2268 2268 inohp->ttt = icmdp->cmd_ttt;
2269 2269 mutex_enter(&isp->sess_cmdsn_mutex);
2270 2270 icmdp->cmd_sn = isp->sess_cmdsn;
2271 2271 inohp->cmdsn = htonl(isp->sess_cmdsn);
2272 2272 mutex_exit(&isp->sess_cmdsn_mutex);
2273 2273 inohp->expstatsn = htonl(icp->conn_expstatsn);
2274 2274 icp->conn_laststatsn = icp->conn_expstatsn;
2275 2275 iscsi_tx_pdu(icp, ISCSI_OP_NOOP_OUT, inohp,
2276 2276 sizeof (iscsi_nop_out_hdr_t), icmdp);
2277 2277 return (rval);
2278 2278 }
2279 2279
2280 2280
2281 2281 /*
2282 2282 * iscsi_tx_abort -
2283 2283 *
2284 2284 */
2285 2285 static iscsi_status_t
2286 2286 iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2287 2287 {
2288 2288 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2289 2289 iscsi_conn_t *icp = NULL;
2290 2290 iscsi_scsi_task_mgt_hdr_t *istmh;
2291 2291
2292 2292 ASSERT(isp != NULL);
2293 2293 ASSERT(icmdp != NULL);
2294 2294 icp = icmdp->cmd_conn;
2295 2295 ASSERT(icp != NULL);
2296 2296
2297 2297 istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2298 2298 ASSERT(istmh != NULL);
2299 2299 mutex_enter(&isp->sess_cmdsn_mutex);
2300 2300 icmdp->cmd_sn = isp->sess_cmdsn;
2301 2301 istmh->cmdsn = htonl(isp->sess_cmdsn);
2302 2302 mutex_exit(&isp->sess_cmdsn_mutex);
2303 2303 istmh->expstatsn = htonl(icp->conn_expstatsn);
2304 2304 icp->conn_laststatsn = icp->conn_expstatsn;
2305 2305 istmh->itt = icmdp->cmd_itt;
2306 2306 istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2307 2307 istmh->function = ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
2308 2308 ISCSI_LUN_BYTE_COPY(istmh->lun,
2309 2309 icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
2310 2310 istmh->rtt = icmdp->cmd_un.abort.icmdp->cmd_itt;
2311 2311 iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2312 2312 sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2313 2313
2314 2314 return (rval);
2315 2315 }
2316 2316
2317 2317
2318 2318 /*
2319 2319 * iscsi_tx_reset -
2320 2320 *
2321 2321 */
2322 2322 static iscsi_status_t
2323 2323 iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2324 2324 {
2325 2325 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2326 2326 iscsi_conn_t *icp = NULL;
2327 2327 iscsi_scsi_task_mgt_hdr_t *istmh;
2328 2328
2329 2329 ASSERT(isp != NULL);
2330 2330 ASSERT(icmdp != NULL);
2331 2331 icp = icmdp->cmd_conn;
2332 2332 ASSERT(icp != NULL);
2333 2333
2334 2334 istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2335 2335 ASSERT(istmh != NULL);
2336 2336 istmh->opcode = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2337 2337 mutex_enter(&isp->sess_cmdsn_mutex);
2338 2338 icmdp->cmd_sn = isp->sess_cmdsn;
2339 2339 istmh->cmdsn = htonl(isp->sess_cmdsn);
2340 2340 mutex_exit(&isp->sess_cmdsn_mutex);
2341 2341 istmh->expstatsn = htonl(icp->conn_expstatsn);
2342 2342 istmh->itt = icmdp->cmd_itt;
2343 2343
2344 2344 switch (icmdp->cmd_un.reset.level) {
2345 2345 case RESET_LUN:
2346 2346 istmh->function = ISCSI_FLAG_FINAL |
2347 2347 ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
2348 2348 ISCSI_LUN_BYTE_COPY(istmh->lun, icmdp->cmd_lun->lun_num);
2349 2349 break;
2350 2350 case RESET_TARGET:
2351 2351 case RESET_BUS:
2352 2352 istmh->function = ISCSI_FLAG_FINAL |
2353 2353 ISCSI_TM_FUNC_TARGET_WARM_RESET;
2354 2354 break;
2355 2355 default:
2356 2356 /* unsupported / unknown level */
2357 2357 ASSERT(FALSE);
2358 2358 break;
2359 2359 }
2360 2360
2361 2361 iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2362 2362 sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2363 2363
2364 2364 return (rval);
2365 2365 }
2366 2366
2367 2367
2368 2368 /*
2369 2369 * iscsi_tx_logout -
2370 2370 *
2371 2371 */
2372 2372 static iscsi_status_t
2373 2373 iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2374 2374 {
2375 2375 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2376 2376 iscsi_conn_t *icp = NULL;
2377 2377 iscsi_logout_hdr_t *ilh;
2378 2378
2379 2379 ASSERT(isp != NULL);
2380 2380 ASSERT(icmdp != NULL);
2381 2381 icp = icmdp->cmd_conn;
2382 2382 ASSERT(icp != NULL);
2383 2383
2384 2384 ilh = kmem_zalloc(sizeof (iscsi_logout_hdr_t), KM_SLEEP);
2385 2385 ilh->opcode = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
2386 2386 ilh->flags = ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2387 2387 ilh->itt = icmdp->cmd_itt;
2388 2388 ilh->cid = icp->conn_cid;
2389 2389 mutex_enter(&isp->sess_cmdsn_mutex);
2390 2390 icmdp->cmd_sn = isp->sess_cmdsn;
2391 2391 ilh->cmdsn = htonl(isp->sess_cmdsn);
2392 2392 mutex_exit(&isp->sess_cmdsn_mutex);
2393 2393 ilh->expstatsn = htonl(icp->conn_expstatsn);
2394 2394 iscsi_tx_pdu(icp, ISCSI_OP_LOGOUT_CMD, ilh,
2395 2395 sizeof (iscsi_logout_hdr_t), icmdp);
2396 2396
2397 2397 return (rval);
2398 2398 }
2399 2399
2400 2400 /*
2401 2401 * iscsi_tx_text - setup iSCSI text request header and send PDU with
2402 2402 * data given in the buffer attached to the command. For a single
2403 2403 * text request, the target may need to send its response in multiple
2404 2404 * text response. In this case, empty text requests are sent after
2405 2405 * each received response to notify the target the initiator is ready
2406 2406 * for more response. For the initial request, the data_len field in
2407 2407 * the text specific portion of a command is set to the amount of data
2408 2408 * the initiator wants to send as part of the request. If additional
2409 2409 * empty text requests are required for long responses, the data_len
2410 2410 * field is set to 0 by the iscsi_handle_text function.
2411 2411 */
2412 2412 static iscsi_status_t
2413 2413 iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2414 2414 {
2415 2415 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2416 2416 iscsi_conn_t *icp = NULL;
2417 2417 iscsi_text_hdr_t *ith;
2418 2418
2419 2419 ASSERT(icmdp != NULL);
2420 2420 icp = icmdp->cmd_conn;
2421 2421 ASSERT(icp != NULL);
2422 2422
2423 2423 ith = kmem_zalloc(sizeof (iscsi_text_hdr_t), KM_SLEEP);
2424 2424 ASSERT(ith != NULL);
2425 2425 ith->flags = ISCSI_FLAG_FINAL;
2426 2426 hton24(ith->dlength, icmdp->cmd_un.text.data_len);
2427 2427 ith->ttt = icmdp->cmd_un.text.ttt;
2428 2428 iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ith,
2429 2429 ISCSI_OP_TEXT_CMD, icmdp);
2430 2430 bcopy(icmdp->cmd_un.text.lun, ith->rsvd4, sizeof (ith->rsvd4));
2431 2431
2432 2432 iscsi_tx_pdu(icp, ISCSI_OP_TEXT_CMD, ith, sizeof (iscsi_text_hdr_t),
2433 2433 icmdp);
2434 2434
2435 2435 return (rval);
2436 2436 }
2437 2437
2438 2438 /*
2439 2439 * +--------------------------------------------------------------------+
2440 2440 * | End of protocol send routines |
2441 2441 * +--------------------------------------------------------------------+
2442 2442 */
2443 2443
2444 2444 /*
2445 2445 * iscsi_handle_abort -
2446 2446 *
2447 2447 */
2448 2448 void
2449 2449 iscsi_handle_abort(void *arg)
2450 2450 {
2451 2451 iscsi_sess_t *isp = NULL;
2452 2452 iscsi_cmd_t *icmdp = (iscsi_cmd_t *)arg;
2453 2453 iscsi_cmd_t *new_icmdp;
2454 2454 iscsi_conn_t *icp;
2455 2455
2456 2456 ASSERT(icmdp != NULL);
2457 2457 icp = icmdp->cmd_conn;
2458 2458 ASSERT(icp != NULL);
2459 2459 isp = icp->conn_sess;
2460 2460 ASSERT(isp != NULL);
2461 2461
2462 2462 /* there should only be one abort */
2463 2463 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
2464 2464
2465 2465 new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2466 2466 new_icmdp->cmd_type = ISCSI_CMD_TYPE_ABORT;
2467 2467 new_icmdp->cmd_lun = icmdp->cmd_lun;
2468 2468 new_icmdp->cmd_un.abort.icmdp = icmdp;
2469 2469 new_icmdp->cmd_conn = icmdp->cmd_conn;
2470 2470 icmdp->cmd_un.scsi.abort_icmdp = new_icmdp;
2471 2471
2472 2472 /* pending queue mutex is already held by timeout_checks */
2473 2473 iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2474 2474 }
2475 2475
2476 2476 /*
2477 2477 * Callback from IDM indicating that the task has been suspended or aborted.
2478 2478 */
2479 2479 void
2480 2480 iscsi_task_aborted(idm_task_t *idt, idm_status_t status)
2481 2481 {
2482 2482 iscsi_cmd_t *icmdp = idt->idt_private;
2483 2483 iscsi_conn_t *icp = icmdp->cmd_conn;
2484 2484 iscsi_sess_t *isp = icp->conn_sess;
2485 2485
2486 2486 ASSERT(icmdp->cmd_conn != NULL);
2487 2487
2488 2488 switch (status) {
2489 2489 case IDM_STATUS_SUSPENDED:
2490 2490 /*
2491 2491 * If the task is suspended, it may be aborted later,
2492 2492 * so we can ignore this notification.
2493 2493 */
2494 2494 break;
2495 2495
2496 2496 case IDM_STATUS_ABORTED:
2497 2497 mutex_enter(&icp->conn_queue_active.mutex);
2498 2498 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E9, isp);
2499 2499 mutex_exit(&icp->conn_queue_active.mutex);
2500 2500 break;
2501 2501
2502 2502 default:
2503 2503 /*
2504 2504 * Unexpected status.
2505 2505 */
2506 2506 ASSERT(0);
2507 2507 }
2508 2508
2509 2509 }
2510 2510
2511 2511 /*
2512 2512 * iscsi_handle_nop -
2513 2513 *
2514 2514 */
2515 2515 static void
2516 2516 iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
2517 2517 {
2518 2518 iscsi_sess_t *isp = NULL;
2519 2519 iscsi_cmd_t *icmdp = NULL;
2520 2520
2521 2521 ASSERT(icp != NULL);
2522 2522 isp = icp->conn_sess;
2523 2523 ASSERT(isp != NULL);
2524 2524
2525 2525 icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
2526 2526 if (icmdp == NULL) {
2527 2527 return;
2528 2528 }
2529 2529
2530 2530 icmdp->cmd_type = ISCSI_CMD_TYPE_NOP;
2531 2531 icmdp->cmd_itt = itt;
2532 2532 icmdp->cmd_ttt = ttt;
2533 2533 icmdp->cmd_lun = NULL;
2534 2534 icp->conn_nop_lbolt = ddi_get_lbolt();
2535 2535
2536 2536 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2537 2537 }
2538 2538
2539 2539 /*
2540 2540 * iscsi_handle_reset - send reset request to the target
2541 2541 *
2542 2542 */
2543 2543 iscsi_status_t
2544 2544 iscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
2545 2545 {
2546 2546 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2547 2547 iscsi_conn_t *icp;
2548 2548 iscsi_cmd_t icmd;
2549 2549
2550 2550 ASSERT(isp != NULL);
2551 2551
2552 2552 if (level == RESET_LUN) {
2553 2553 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2554 2554 ASSERT(ilp != NULL);
2555 2555 if (ilp->lun_state & ISCSI_LUN_STATE_BUSY) {
2556 2556 rw_exit(&isp->sess_lun_list_rwlock);
2557 2557 return (ISCSI_STATUS_SUCCESS);
2558 2558 }
2559 2559 ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
2560 2560 rw_exit(&isp->sess_lun_list_rwlock);
2561 2561 } else {
2562 2562 mutex_enter(&isp->sess_reset_mutex);
2563 2563 if (isp->sess_reset_in_progress == B_TRUE) {
2564 2564 /*
2565 2565 * If the reset is in progress, it is unnecessary
2566 2566 * to send reset to the target redunantly.
2567 2567 */
2568 2568 mutex_exit(&isp->sess_reset_mutex);
2569 2569 return (ISCSI_STATUS_SUCCESS);
2570 2570 }
2571 2571 isp->sess_reset_in_progress = B_TRUE;
2572 2572 mutex_exit(&isp->sess_reset_mutex);
2573 2573 }
2574 2574
2575 2575 bzero(&icmd, sizeof (iscsi_cmd_t));
2576 2576 icmd.cmd_sig = ISCSI_SIG_CMD;
2577 2577 icmd.cmd_state = ISCSI_CMD_STATE_FREE;
2578 2578 icmd.cmd_type = ISCSI_CMD_TYPE_RESET;
2579 2579 icmd.cmd_lun = ilp;
2580 2580 icmd.cmd_un.reset.level = level;
2581 2581 icmd.cmd_result = ISCSI_STATUS_SUCCESS;
2582 2582 icmd.cmd_completed = B_FALSE;
2583 2583 icmd.cmd_un.reset.response = SCSI_TCP_TM_RESP_COMPLETE;
2584 2584
2585 2585 mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
2586 2586 cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
2587 2587 /*
2588 2588 * If we received an IO and we are not in the
2589 2589 * LOGGED_IN state we are in the process of
2590 2590 * failing. Just respond that we are BUSY.
2591 2591 */
2592 2592 rw_enter(&isp->sess_state_rwlock, RW_READER);
2593 2593 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2594 2594 /* We aren't connected to the target fake success */
2595 2595 rw_exit(&isp->sess_state_rwlock);
2596 2596
2597 2597 if (level == RESET_LUN) {
2598 2598 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2599 2599 ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2600 2600 rw_exit(&isp->sess_lun_list_rwlock);
2601 2601 } else {
2602 2602 mutex_enter(&isp->sess_reset_mutex);
2603 2603 isp->sess_reset_in_progress = B_FALSE;
2604 2604 mutex_exit(&isp->sess_reset_mutex);
2605 2605 }
2606 2606
2607 2607 return (ISCSI_STATUS_SUCCESS);
2608 2608 }
2609 2609
2610 2610 mutex_enter(&isp->sess_queue_pending.mutex);
2611 2611 iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
2612 2612 mutex_exit(&isp->sess_queue_pending.mutex);
2613 2613 rw_exit(&isp->sess_state_rwlock);
2614 2614
2615 2615 /* stall until completed */
2616 2616 mutex_enter(&icmd.cmd_mutex);
2617 2617 while (icmd.cmd_completed == B_FALSE) {
2618 2618 cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
2619 2619 }
2620 2620 mutex_exit(&icmd.cmd_mutex);
2621 2621
2622 2622 /* copy rval */
2623 2623 rval = icmd.cmd_result;
2624 2624
2625 2625 if (rval == ISCSI_STATUS_SUCCESS) {
2626 2626 /*
2627 2627 * Reset was successful. We need to flush
2628 2628 * all active IOs.
2629 2629 */
2630 2630 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2631 2631 icp = isp->sess_conn_list;
2632 2632 while (icp != NULL) {
2633 2633 iscsi_cmd_t *t_icmdp = NULL;
2634 2634 iscsi_cmd_t *next_icmdp = NULL;
2635 2635
2636 2636 mutex_enter(&icp->conn_queue_active.mutex);
2637 2637 t_icmdp = icp->conn_queue_active.head;
2638 2638 while (t_icmdp != NULL) {
2639 2639 next_icmdp = t_icmdp->cmd_next;
2640 2640 mutex_enter(&t_icmdp->cmd_mutex);
2641 2641 if (!(t_icmdp->cmd_misc_flags &
2642 2642 ISCSI_CMD_MISCFLAG_SENT)) {
2643 2643 /*
2644 2644 * Although this command is in the
2645 2645 * active queue, it has not been sent.
2646 2646 * Skip it.
2647 2647 */
2648 2648 mutex_exit(&t_icmdp->cmd_mutex);
2649 2649 t_icmdp = next_icmdp;
2650 2650 continue;
2651 2651 }
2652 2652 if (level == RESET_LUN) {
2653 2653 if (icmd.cmd_lun == NULL ||
2654 2654 t_icmdp->cmd_lun == NULL ||
2655 2655 (icmd.cmd_lun->lun_num !=
2656 2656 t_icmdp->cmd_lun->lun_num)) {
2657 2657 mutex_exit(&t_icmdp->cmd_mutex);
2658 2658 t_icmdp = next_icmdp;
2659 2659 continue;
2660 2660 }
2661 2661 }
2662 2662
2663 2663 if (icmd.cmd_sn == t_icmdp->cmd_sn) {
2664 2664 /*
2665 2665 * This command may be replied with
2666 2666 * UA sense key later. So currently
2667 2667 * it is not a suitable time to flush
2668 2668 * it. Mark its flag with FLUSH. There
2669 2669 * is no harm to keep it for a while.
2670 2670 */
2671 2671 t_icmdp->cmd_misc_flags |=
2672 2672 ISCSI_CMD_MISCFLAG_FLUSH;
2673 2673 if (t_icmdp->cmd_type ==
2674 2674 ISCSI_CMD_TYPE_SCSI) {
2675 2675 t_icmdp->cmd_un.scsi.pkt_stat |=
2676 2676 STAT_BUS_RESET;
2677 2677 }
2678 2678 mutex_exit(&t_icmdp->cmd_mutex);
2679 2679 } else if ((icmd.cmd_sn > t_icmdp->cmd_sn) ||
2680 2680 ((t_icmdp->cmd_sn - icmd.cmd_sn) >
2681 2681 ISCSI_CMD_SN_WRAP)) {
2682 2682 /*
2683 2683 * This reset request must act on all
2684 2684 * the commnds from the same session
2685 2685 * having a CmdSN lower than the task
2686 2686 * mangement CmdSN. So flush these
2687 2687 * commands here.
2688 2688 */
2689 2689 if (t_icmdp->cmd_type ==
2690 2690 ISCSI_CMD_TYPE_SCSI) {
2691 2691 t_icmdp->cmd_un.scsi.pkt_stat |=
2692 2692 STAT_BUS_RESET;
2693 2693 }
2694 2694 mutex_exit(&t_icmdp->cmd_mutex);
2695 2695 iscsi_cmd_state_machine(t_icmdp,
2696 2696 ISCSI_CMD_EVENT_E7, isp);
2697 2697 } else {
2698 2698 mutex_exit(&t_icmdp->cmd_mutex);
2699 2699 }
2700 2700
2701 2701 t_icmdp = next_icmdp;
2702 2702 }
2703 2703
2704 2704 mutex_exit(&icp->conn_queue_active.mutex);
2705 2705 icp = icp->conn_next;
2706 2706 }
2707 2707 rw_exit(&isp->sess_conn_list_rwlock);
2708 2708 }
2709 2709
2710 2710 /* clean up */
2711 2711 cv_destroy(&icmd.cmd_completion);
2712 2712 mutex_destroy(&icmd.cmd_mutex);
2713 2713
2714 2714 if (level == RESET_LUN) {
2715 2715 rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2716 2716 ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2717 2717 rw_exit(&isp->sess_lun_list_rwlock);
2718 2718 } else {
2719 2719 mutex_enter(&isp->sess_reset_mutex);
2720 2720 isp->sess_reset_in_progress = B_FALSE;
2721 2721 mutex_exit(&isp->sess_reset_mutex);
2722 2722 }
2723 2723
2724 2724 return (rval);
2725 2725 }
2726 2726
2727 2727 /*
2728 2728 * iscsi_logout_start - task handler for deferred logout
2729 2729 * Acquire a hold before call, released in iscsi_handle_logout
2730 2730 */
2731 2731 static void
2732 2732 iscsi_logout_start(void *arg)
2733 2733 {
2734 2734 iscsi_task_t *itp = (iscsi_task_t *)arg;
2735 2735 iscsi_conn_t *icp;
2736 2736
2737 2737 icp = (iscsi_conn_t *)itp->t_arg;
2738 2738
2739 2739 mutex_enter(&icp->conn_state_mutex);
2740 2740 (void) iscsi_handle_logout(icp);
2741 2741 mutex_exit(&icp->conn_state_mutex);
2742 2742 }
2743 2743
2744 2744 /*
2745 2745 * iscsi_handle_logout - This function will issue a logout for
2746 2746 * the session from a specific connection.
2747 2747 * Acquire idm_conn_hold before call. Released internally.
2748 2748 */
2749 2749 iscsi_status_t
2750 2750 iscsi_handle_logout(iscsi_conn_t *icp)
2751 2751 {
2752 2752 iscsi_sess_t *isp;
2753 2753 idm_conn_t *ic;
2754 2754 iscsi_cmd_t *icmdp;
2755 2755 int rval;
2756 2756
2757 2757 ASSERT(icp != NULL);
2758 2758 isp = icp->conn_sess;
2759 2759 ic = icp->conn_ic;
2760 2760 ASSERT(isp != NULL);
2761 2761 ASSERT(isp->sess_hba != NULL);
2762 2762 ASSERT(mutex_owned(&icp->conn_state_mutex));
2763 2763
2764 2764 /*
2765 2765 * If the connection has already gone down (e.g. if the transport
2766 2766 * failed between when this LOGOUT was generated and now) then we
2767 2767 * can and must skip sending the LOGOUT. Check the same condition
2768 2768 * we use below to determine that connection has "settled".
2769 2769 */
2770 2770 if ((icp->conn_state == ISCSI_CONN_STATE_FREE) ||
2771 2771 (icp->conn_state == ISCSI_CONN_STATE_FAILED) ||
2772 2772 (icp->conn_state == ISCSI_CONN_STATE_POLLING)) {
2773 2773 idm_conn_rele(ic);
2774 2774 return (0);
2775 2775 }
2776 2776
2777 2777 icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2778 2778 ASSERT(icmdp != NULL);
2779 2779 icmdp->cmd_type = ISCSI_CMD_TYPE_LOGOUT;
2780 2780 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
2781 2781 icmdp->cmd_completed = B_FALSE;
2782 2782
2783 2783 mutex_enter(&isp->sess_queue_pending.mutex);
2784 2784 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2785 2785 mutex_exit(&isp->sess_queue_pending.mutex);
2786 2786
2787 2787 /*
2788 2788 * release connection state mutex to avoid a deadlock. This
2789 2789 * function is called from within the connection state
2790 2790 * machine with the lock held. When the logout response is
2791 2791 * received another call to the connection state machine
2792 2792 * occurs which causes the deadlock
2793 2793 */
2794 2794 mutex_exit(&icp->conn_state_mutex);
2795 2795
2796 2796 /* stall until completed */
2797 2797 mutex_enter(&icmdp->cmd_mutex);
2798 2798 while (icmdp->cmd_completed == B_FALSE) {
2799 2799 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2800 2800 }
2801 2801 mutex_exit(&icmdp->cmd_mutex);
2802 2802 mutex_enter(&icp->conn_state_mutex);
2803 2803
2804 2804 /* copy rval */
2805 2805 rval = icmdp->cmd_result;
2806 2806
2807 2807 /* clean up */
2808 2808 iscsi_cmd_free(icmdp);
2809 2809
2810 2810 if (rval != 0) {
2811 2811 /* If the logout failed then drop the connection */
2812 2812 idm_ini_conn_disconnect(icp->conn_ic);
2813 2813 }
2814 2814
2815 2815 /* stall until connection settles */
2816 2816 while ((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
2817 2817 (icp->conn_state != ISCSI_CONN_STATE_FAILED) &&
2818 2818 (icp->conn_state != ISCSI_CONN_STATE_POLLING)) {
2819 2819 /* wait for transition */
2820 2820 cv_wait(&icp->conn_state_change, &icp->conn_state_mutex);
2821 2821 }
2822 2822
2823 2823 idm_conn_rele(ic);
2824 2824
2825 2825 /*
2826 2826 * Return value reflects whether the logout command completed --
2827 2827 * regardless of the return value the connection is closed and
2828 2828 * ready for reconnection.
2829 2829 */
2830 2830 return (rval);
2831 2831 }
2832 2832
2833 2833
2834 2834 /*
2835 2835 * iscsi_handle_text - main control function for iSCSI text requests. This
2836 2836 * function handles allocating the command, sending initial text request, and
2837 2837 * handling long response sequence.
2838 2838 * If a data overflow condition occurs, iscsi_handle_text continues to
2839 2839 * receive responses until the all data has been recieved. This allows
2840 2840 * the full data length to be returned to the caller.
2841 2841 */
2842 2842 iscsi_status_t
2843 2843 iscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
2844 2844 uint32_t data_len, uint32_t *rx_data_len)
2845 2845 {
2846 2846 iscsi_sess_t *isp;
2847 2847 iscsi_cmd_t *icmdp;
2848 2848 iscsi_status_t rval = ISCSI_STATUS_SUCCESS;
2849 2849
2850 2850 ASSERT(icp != NULL);
2851 2851 ASSERT(buf != NULL);
2852 2852 ASSERT(rx_data_len != NULL);
2853 2853
2854 2854 isp = icp->conn_sess;
2855 2855 ASSERT(isp != NULL);
2856 2856
2857 2857 /*
2858 2858 * Ensure data for text request command is not greater
2859 2859 * than the negotiated maximum receive data seqment length.
2860 2860 *
2861 2861 * Although iSCSI allows for long text requests (multiple
2862 2862 * pdus), this function places a restriction on text
2863 2863 * requests to ensure it is handled by a single PDU.
2864 2864 */
2865 2865 if (data_len > icp->conn_params.max_xmit_data_seg_len) {
2866 2866 return (ISCSI_STATUS_CMD_FAILED);
2867 2867 }
2868 2868
2869 2869 icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2870 2870 ASSERT(icmdp != NULL);
2871 2871
2872 2872 icmdp->cmd_type = ISCSI_CMD_TYPE_TEXT;
2873 2873 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
2874 2874 icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
2875 2875 icmdp->cmd_completed = B_FALSE;
2876 2876
2877 2877 icmdp->cmd_un.text.buf = buf;
2878 2878 icmdp->cmd_un.text.buf_len = buf_len;
2879 2879 icmdp->cmd_un.text.offset = 0;
2880 2880 icmdp->cmd_un.text.data_len = data_len;
2881 2881 icmdp->cmd_un.text.total_rx_len = 0;
2882 2882 icmdp->cmd_un.text.ttt = ISCSI_RSVD_TASK_TAG;
2883 2883 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_INITIAL_REQ;
2884 2884
2885 2885 long_text_response:
2886 2886 rw_enter(&isp->sess_state_rwlock, RW_READER);
2887 2887 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2888 2888 iscsi_cmd_free(icmdp);
2889 2889 rw_exit(&isp->sess_state_rwlock);
2890 2890 return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
2891 2891 }
2892 2892
2893 2893 mutex_enter(&isp->sess_queue_pending.mutex);
2894 2894 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2895 2895 mutex_exit(&isp->sess_queue_pending.mutex);
2896 2896 rw_exit(&isp->sess_state_rwlock);
2897 2897
2898 2898 /* stall until completed */
2899 2899 mutex_enter(&icmdp->cmd_mutex);
2900 2900 while (icmdp->cmd_completed == B_FALSE) {
2901 2901 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2902 2902 }
2903 2903 mutex_exit(&icmdp->cmd_mutex);
2904 2904
2905 2905 /*
2906 2906 * check if error occured. If data overflow occured, continue on
2907 2907 * to ensure we get all data so that the full data length can be
2908 2908 * returned to the user
2909 2909 */
2910 2910 if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
2911 2911 (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
2912 2912 cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
2913 2913 icmdp->cmd_result);
2914 2914 rval = icmdp->cmd_result;
2915 2915 iscsi_cmd_free(icmdp);
2916 2916 return (rval);
2917 2917 }
2918 2918
2919 2919 /* check if this was a partial text PDU */
2920 2920 if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
2921 2921 /*
2922 2922 * If a paritial text rexponse received, send an empty
2923 2923 * text request. This follows the behaviour specified
2924 2924 * in RFC3720 regarding long text responses.
2925 2925 */
2926 2926 icmdp->cmd_misc_flags &= ~ISCSI_CMD_MISCFLAG_FREE;
2927 2927 icmdp->cmd_completed = B_FALSE;
2928 2928 icmdp->cmd_un.text.data_len = 0;
2929 2929 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
2930 2930 goto long_text_response;
2931 2931 }
2932 2932
2933 2933 /*
2934 2934 * set total received data length. If data overflow this would be
2935 2935 * amount of data that would have been received if buffer large
2936 2936 * enough.
2937 2937 */
2938 2938 *rx_data_len = icmdp->cmd_un.text.total_rx_len;
2939 2939
2940 2940 /* copy rval */
2941 2941 rval = icmdp->cmd_result;
2942 2942
2943 2943 /* clean up */
2944 2944 iscsi_cmd_free(icmdp);
2945 2945
2946 2946 return (rval);
2947 2947 }
2948 2948
2949 2949 /*
2950 2950 * iscsi_handle_passthru - This function is used to send a uscsi_cmd
2951 2951 * to a specific target lun. This routine is used for internal purposes
2952 2952 * during enumeration and via the ISCSI_USCSICMD IOCTL. We restrict
2953 2953 * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
2954 2954 * and READ_CAPACITY for security purposes.
2955 2955 *
2956 2956 * The logic here is broken into three phases.
2957 2957 * 1) Allocate and initialize a pkt/icmdp
2958 2958 * 2) Send the pkt/icmdp
2959 2959 * 3) cv_wait for completion
2960 2960 */
2961 2961 iscsi_status_t
2962 2962 iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
2963 2963 {
2964 2964 iscsi_status_t rval;
2965 2965 iscsi_cmd_t *icmdp;
2966 2966 struct scsi_pkt *pkt;
2967 2967 struct buf *bp;
2968 2968 struct scsi_arq_status *arqstat;
2969 2969 int statuslen;
2970 2970
2971 2971 ASSERT(isp != NULL);
2972 2972 ASSERT(ucmdp != NULL);
2973 2973
2974 2974 if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
2975 2975 /*
2976 2976 * The caller provided sense buffer large enough for additional
2977 2977 * sense bytes. We need to allocate pkt_scbp to fit them there
2978 2978 * too.
2979 2979 */
2980 2980 statuslen = ucmdp->uscsi_rqlen + ISCSI_ARQ_STATUS_NOSENSE_LEN;
2981 2981 } else {
2982 2982 /* The default size of pkt_scbp */
2983 2983 statuslen = sizeof (struct scsi_arq_status);
2984 2984 }
2985 2985
2986 2986 /*
2987 2987 * Step 1. Setup structs - KM_SLEEP will always succeed
2988 2988 */
2989 2989 bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
2990 2990 ASSERT(bp != NULL);
2991 2991 pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
2992 2992 ASSERT(pkt != NULL);
2993 2993 icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
2994 2994 ASSERT(icmdp != NULL);
2995 2995
2996 2996 /* setup bp structure */
2997 2997 bp->b_flags = B_READ;
2998 2998 bp->b_bcount = ucmdp->uscsi_buflen;
2999 2999 bp->b_un.b_addr = ucmdp->uscsi_bufaddr;
3000 3000
3001 3001 /* setup scsi_pkt structure */
3002 3002 pkt->pkt_ha_private = icmdp;
3003 3003 pkt->pkt_scbp = kmem_zalloc(statuslen, KM_SLEEP);
3004 3004 pkt->pkt_cdbp = kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
3005 3005 /* callback routine for passthru, will wake cv_wait */
3006 3006 pkt->pkt_comp = iscsi_handle_passthru_callback;
3007 3007 pkt->pkt_time = ucmdp->uscsi_timeout;
3008 3008
3009 3009 /* setup iscsi_cmd structure */
3010 3010 icmdp->cmd_lun = NULL;
3011 3011 icmdp->cmd_type = ISCSI_CMD_TYPE_SCSI;
3012 3012 icmdp->cmd_un.scsi.lun = lun;
3013 3013 icmdp->cmd_un.scsi.pkt = pkt;
3014 3014 icmdp->cmd_un.scsi.bp = bp;
3015 3015 bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3016 3016 icmdp->cmd_un.scsi.cmdlen = ucmdp->uscsi_cdblen;
3017 3017 icmdp->cmd_un.scsi.statuslen = statuslen;
3018 3018 icmdp->cmd_crc_error_seen = B_FALSE;
3019 3019 icmdp->cmd_completed = B_FALSE;
3020 3020 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
3021 3021
3022 3022 /*
3023 3023 * Step 2. Push IO onto pending queue. If we aren't in
3024 3024 * FULL_FEATURE we need to fail the IO.
3025 3025 */
3026 3026 rw_enter(&isp->sess_state_rwlock, RW_READER);
3027 3027 if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
3028 3028 rw_exit(&isp->sess_state_rwlock);
3029 3029
3030 3030 iscsi_cmd_free(icmdp);
3031 3031 kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3032 3032 kmem_free(pkt->pkt_scbp, statuslen);
3033 3033 kmem_free(pkt, sizeof (struct scsi_pkt));
3034 3034 kmem_free(bp, sizeof (struct buf));
3035 3035
3036 3036 return (ISCSI_STATUS_CMD_FAILED);
3037 3037 }
3038 3038
3039 3039 mutex_enter(&isp->sess_queue_pending.mutex);
3040 3040 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
3041 3041 mutex_exit(&isp->sess_queue_pending.mutex);
3042 3042 rw_exit(&isp->sess_state_rwlock);
3043 3043
3044 3044 /*
3045 3045 * Step 3. Wait on cv_wait for completion routine
3046 3046 */
3047 3047 mutex_enter(&icmdp->cmd_mutex);
3048 3048 while (icmdp->cmd_completed == B_FALSE) {
3049 3049 cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
3050 3050 }
3051 3051 mutex_exit(&icmdp->cmd_mutex);
3052 3052
3053 3053 /* copy rval */
3054 3054 rval = icmdp->cmd_result;
3055 3055
3056 3056 ucmdp->uscsi_resid = pkt->pkt_resid;
3057 3057
3058 3058 /* update scsi status */
3059 3059 arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
3060 3060 ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
3061 3061
3062 3062 /* copy request sense buffers if caller gave space */
3063 3063 if ((ucmdp->uscsi_rqlen > 0) &&
3064 3064 (ucmdp->uscsi_rqbuf != NULL)) {
3065 3065 ASSERT(ucmdp->uscsi_rqlen >= arqstat->sts_rqpkt_resid);
3066 3066 ucmdp->uscsi_rqresid = arqstat->sts_rqpkt_resid;
3067 3067 bcopy(&arqstat->sts_sensedata, ucmdp->uscsi_rqbuf,
3068 3068 ucmdp->uscsi_rqlen - arqstat->sts_rqpkt_resid);
3069 3069 }
3070 3070
3071 3071 if ((ucmdp->uscsi_status == STATUS_CHECK) &&
3072 3072 ((icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL)) == B_TRUE) {
3073 3073 /*
3074 3074 * Internal SCSI commands received status
3075 3075 */
3076 3076 (void) iscsi_decode_sense(
3077 3077 (uint8_t *)&arqstat->sts_sensedata, icmdp);
3078 3078 }
3079 3079
3080 3080 /* clean up */
3081 3081 iscsi_cmd_free(icmdp);
3082 3082 kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3083 3083 kmem_free(pkt->pkt_scbp, statuslen);
3084 3084 kmem_free(pkt, sizeof (struct scsi_pkt));
3085 3085 kmem_free(bp, sizeof (struct buf));
3086 3086
3087 3087 return (rval);
3088 3088 }
3089 3089
3090 3090
3091 3091 /*
3092 3092 * iscsi_handle_passthru_callback -
3093 3093 *
3094 3094 */
3095 3095 static void
3096 3096 iscsi_handle_passthru_callback(struct scsi_pkt *pkt)
3097 3097 {
3098 3098 iscsi_cmd_t *icmdp = NULL;
3099 3099
3100 3100 ASSERT(pkt != NULL);
3101 3101 icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
3102 3102 ASSERT(icmdp != NULL);
3103 3103
3104 3104 mutex_enter(&icmdp->cmd_mutex);
3105 3105 icmdp->cmd_completed = B_TRUE;
3106 3106 icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
3107 3107 cv_broadcast(&icmdp->cmd_completion);
3108 3108 mutex_exit(&icmdp->cmd_mutex);
3109 3109
3110 3110 }
3111 3111
3112 3112 /*
3113 3113 * IDM callbacks
3114 3114 */
3115 3115 void
3116 3116 iscsi_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
3117 3117 {
3118 3118 iscsi_cmd_t *icmdp = idm_task->idt_private;
3119 3119 iscsi_conn_t *icp = icmdp->cmd_conn;
3120 3120 iscsi_data_hdr_t *ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
3121 3121
3122 3122 mutex_enter(&icmdp->cmd_mutex);
3123 3123 if (opcode == ISCSI_OP_SCSI_DATA) {
3124 3124 uint32_t data_sn;
3125 3125 uint32_t lun;
3126 3126 icmdp = idm_task->idt_private;
3127 3127 icp = icmdp->cmd_conn;
3128 3128 ihp->opcode = opcode;
3129 3129 ihp->itt = icmdp->cmd_itt;
3130 3130 ihp->ttt = idm_task->idt_r2t_ttt;
3131 3131 ihp->expstatsn = htonl(icp->conn_expstatsn);
3132 3132 icp->conn_laststatsn = icp->conn_expstatsn;
3133 3133 data_sn = ntohl(ihp->datasn);
3134 3134 data_sn++;
3135 3135 lun = icmdp->cmd_un.scsi.lun;
3136 3136 ISCSI_LUN_BYTE_COPY(ihp->lun, lun);
3137 3137 /* CRM: upate_flow_control */
3138 3138 ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_build_hdr"
3139 3139 "(ISCSI_OP_SCSI_DATA): task: %p icp: %p ic: %p itt: %x "
3140 3140 "exp: %d data_sn: %d", (void *)idm_task, (void *)icp,
3141 3141 (void *)icp->conn_ic, ihp->itt, icp->conn_expstatsn,
3142 3142 data_sn);
3143 3143 } else {
3144 3144 cmn_err(CE_WARN, "iscsi_build_hdr: unprocessed build "
3145 3145 "header opcode: %x", opcode);
3146 3146 }
3147 3147 mutex_exit(&icmdp->cmd_mutex);
3148 3148 }
3149 3149
3150 3150 static void
3151 3151 iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
3152 3152 idm_status_t status)
3153 3153 {
3154 3154 switch (status) {
3155 3155 case IDM_STATUS_SUCCESS:
3156 3156 if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
3157 3157 (icp->conn_queue_active.count == 0)) {
3158 3158 iscsi_drop_conn_cleanup(icp);
3159 3159 }
3160 3160 break;
3161 3161 case IDM_STATUS_PROTOCOL_ERROR:
3162 3162 KSTAT_INC_CONN_ERR_PROTOCOL(icp);
3163 3163 iscsi_drop_conn_cleanup(icp);
3164 3164 break;
3165 3165 default:
3166 3166 break;
3167 3167 }
3168 3168 }
3169 3169
3170 3170 static void
3171 3171 iscsi_drop_conn_cleanup(iscsi_conn_t *icp) {
3172 3172 mutex_enter(&icp->conn_state_mutex);
3173 3173 idm_ini_conn_disconnect(icp->conn_ic);
3174 3174 mutex_exit(&icp->conn_state_mutex);
3175 3175 }
3176 3176
3177 3177 void
3178 3178 iscsi_rx_error_pdu(idm_conn_t *ic, idm_pdu_t *pdu, idm_status_t status)
3179 3179 {
3180 3180 iscsi_conn_t *icp = (iscsi_conn_t *)ic->ic_handle;
3181 3181 iscsi_sess_t *isp;
3182 3182
3183 3183 ASSERT(icp != NULL);
3184 3184 isp = icp->conn_sess;
3185 3185 ASSERT(isp != NULL);
3186 3186 iscsi_process_rsp_status(isp, icp, status);
3187 3187 idm_pdu_complete(pdu, status);
3188 3188 }
3189 3189
3190 3190 void
3191 3191 iscsi_rx_misc_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
3192 3192 {
3193 3193 iscsi_conn_t *icp;
3194 3194 iscsi_hdr_t *ihp = (iscsi_hdr_t *)pdu->isp_hdr;
3195 3195 iscsi_sess_t *isp;
3196 3196 idm_status_t status;
3197 3197
3198 3198 icp = ic->ic_handle;
3199 3199 isp = icp->conn_sess;
3200 3200 isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
3201 3201 switch (ihp->opcode & ISCSI_OPCODE_MASK) {
3202 3202 case ISCSI_OP_LOGIN_RSP:
3203 3203 status = iscsi_rx_process_login_pdu(ic, pdu);
3204 3204 idm_pdu_complete(pdu, status);
3205 3205 break;
3206 3206 case ISCSI_OP_LOGOUT_RSP:
3207 3207 status = iscsi_rx_process_logout_rsp(ic, pdu);
3208 3208 idm_pdu_complete(pdu, status);
3209 3209 break;
3210 3210 case ISCSI_OP_REJECT_MSG:
3211 3211 status = iscsi_rx_process_reject_rsp(ic, pdu);
3212 3212 break;
3213 3213 case ISCSI_OP_SCSI_TASK_MGT_RSP:
3214 3214 status = iscsi_rx_process_task_mgt_rsp(ic, pdu);
3215 3215 idm_pdu_complete(pdu, status);
3216 3216 break;
3217 3217 case ISCSI_OP_NOOP_IN:
3218 3218 status = iscsi_rx_process_nop(ic, pdu);
3219 3219 idm_pdu_complete(pdu, status);
3220 3220 break;
3221 3221 case ISCSI_OP_ASYNC_EVENT:
3222 3222 status = iscsi_rx_process_async_rsp(ic, pdu);
3223 3223 break;
3224 3224 case ISCSI_OP_TEXT_RSP:
3225 3225 status = iscsi_rx_process_text_rsp(ic, pdu);
3226 3226 idm_pdu_complete(pdu, status);
3227 3227 break;
3228 3228 default:
3229 3229 cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
3230 3230 "- received misc unsupported opcode 0x%02x",
3231 3231 icp->conn_oid, ihp->opcode);
3232 3232 status = IDM_STATUS_PROTOCOL_ERROR;
3233 3233 break;
3234 3234 }
3235 3235 iscsi_process_rsp_status(isp, icp, status);
3236 3236 }
3237 3237
3238 3238 /*
3239 3239 * +--------------------------------------------------------------------+
3240 3240 * | Beginning of completion routines |
3241 3241 * +--------------------------------------------------------------------+
3242 3242 */
3243 3243
3244 3244 /*
3245 3245 * iscsi_ic_thread -
3246 3246 */
3247 3247 void
3248 3248 iscsi_ic_thread(iscsi_thread_t *thread, void *arg)
3249 3249 {
3250 3250 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
3251 3251 int ret;
3252 3252 iscsi_queue_t q;
3253 3253 iscsi_cmd_t *icmdp;
3254 3254 iscsi_cmd_t *next_icmdp;
3255 3255
3256 3256 ASSERT(isp != NULL);
3257 3257 ASSERT(thread != NULL);
3258 3258 ASSERT(thread->signature == SIG_ISCSI_THREAD);
3259 3259
3260 3260 for (;;) {
3261 3261
3262 3262 /*
3263 3263 * We wait till iodone or somebody else wakes us up.
3264 3264 */
3265 3265 ret = iscsi_thread_wait(thread, -1);
3266 3266
3267 3267 /*
3268 3268 * The value should never be negative since we never timeout.
3269 3269 */
3270 3270 ASSERT(ret >= 0);
3271 3271
3272 3272 q.count = 0;
3273 3273 q.head = NULL;
3274 3274 q.tail = NULL;
3275 3275 mutex_enter(&isp->sess_queue_completion.mutex);
3276 3276 icmdp = isp->sess_queue_completion.head;
3277 3277 while (icmdp != NULL) {
3278 3278 next_icmdp = icmdp->cmd_next;
3279 3279 mutex_enter(&icmdp->cmd_mutex);
3280 3280 /*
3281 3281 * check if the associated r2t/abort has finished
3282 3282 * yet. If not, don't complete the command.
3283 3283 */
3284 3284 if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
3285 3285 (icmdp->cmd_un.scsi.abort_icmdp == NULL)) {
3286 3286 mutex_exit(&icmdp->cmd_mutex);
3287 3287 (void) iscsi_dequeue_cmd(&isp->
3288 3288 sess_queue_completion.head,
3289 3289 &isp->sess_queue_completion.tail,
3290 3290 icmdp);
3291 3291 --isp->sess_queue_completion.count;
3292 3292 iscsi_enqueue_cmd_head(&q.head,
3293 3293 &q.tail, icmdp);
3294 3294 } else {
3295 3295 mutex_exit(&icmdp->cmd_mutex);
3296 3296 }
3297 3297 icmdp = next_icmdp;
3298 3298 }
3299 3299 mutex_exit(&isp->sess_queue_completion.mutex);
3300 3300 icmdp = q.head;
3301 3301 while (icmdp != NULL) {
3302 3302 next_icmdp = icmdp->cmd_next;
3303 3303 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
3304 3304 icmdp = next_icmdp;
3305 3305 }
3306 3306
3307 3307 if (ret > 0)
3308 3308 /* Somebody woke us up to work */
3309 3309 continue;
3310 3310 else
3311 3311 /*
3312 3312 * Somebody woke us up to kill ourselves. We will
3313 3313 * make sure, however that the completion queue is
3314 3314 * empty before leaving. After we've done that it
3315 3315 * is the originator of the signal that has to make
3316 3316 * sure no other SCSI command is posted.
3317 3317 */
3318 3318 break;
3319 3319 }
3320 3320
3321 3321 }
3322 3322
3323 3323 /*
3324 3324 * iscsi_iodone -
3325 3325 *
3326 3326 */
3327 3327 void
3328 3328 iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
3329 3329 {
3330 3330 struct scsi_pkt *pkt = NULL;
3331 3331 struct buf *bp = icmdp->cmd_un.scsi.bp;
3332 3332
3333 3333 ASSERT(isp != NULL);
3334 3334 ASSERT(icmdp != NULL);
3335 3335 pkt = icmdp->cmd_un.scsi.pkt;
3336 3336 ASSERT(pkt != NULL);
3337 3337
3338 3338 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
3339 3339 ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
3340 3340 if (pkt->pkt_reason == CMD_CMPLT) {
3341 3341 if (bp) {
3342 3342 if (bp->b_flags & B_READ) {
3343 3343 KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
3344 3344 } else {
3345 3345 KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
3346 3346 }
3347 3347 }
3348 3348 }
3349 3349
3350 3350 if (pkt->pkt_flags & FLAG_NOINTR) {
3351 3351 cv_broadcast(&icmdp->cmd_completion);
3352 3352 mutex_exit(&icmdp->cmd_mutex);
3353 3353 } else {
3354 3354 /*
3355 3355 * Release mutex. As soon as callback is
3356 3356 * issued the caller may destroy the command.
3357 3357 */
3358 3358 mutex_exit(&icmdp->cmd_mutex);
3359 3359 /*
3360 3360 * We can't just directly call the pk_comp routine. In
3361 3361 * many error cases the target driver will use the calling
3362 3362 * thread to re-drive error handling (reset, retries...)
3363 3363 * back into the hba driver (iscsi). If the target redrives
3364 3364 * a reset back into the iscsi driver off this thead we have
3365 3365 * a chance of deadlocking. So instead use the io completion
3366 3366 * thread.
3367 3367 */
3368 3368 (*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
3369 3369 }
3370 3370 }
3371 3371
3372 3372 /*
3373 3373 * +--------------------------------------------------------------------+
3374 3374 * | End of completion routines |
3375 3375 * +--------------------------------------------------------------------+
3376 3376 */
3377 3377
3378 3378 /*
3379 3379 * +--------------------------------------------------------------------+
3380 3380 * | Beginning of watchdog routines |
3381 3381 * +--------------------------------------------------------------------+
3382 3382 */
3383 3383
3384 3384 /*
3385 3385 * iscsi_watchdog_thread -
3386 3386 *
3387 3387 */
3388 3388 void
3389 3389 iscsi_wd_thread(iscsi_thread_t *thread, void *arg)
3390 3390 {
3391 3391 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
3392 3392 int rc = 1;
3393 3393
3394 3394 ASSERT(isp != NULL);
3395 3395
3396 3396 while (rc != NULL) {
3397 3397
3398 3398 iscsi_timeout_checks(isp);
3399 3399 iscsi_nop_checks(isp);
3400 3400
3401 3401 rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
3402 3402 }
3403 3403 }
3404 3404
3405 3405 /*
3406 3406 * iscsi_timeout_checks -
3407 3407 *
3408 3408 */
3409 3409 static void
3410 3410 iscsi_timeout_checks(iscsi_sess_t *isp)
3411 3411 {
3412 3412 clock_t now = ddi_get_lbolt();
3413 3413 iscsi_conn_t *icp;
3414 3414 iscsi_cmd_t *icmdp, *nicmdp;
3415 3415
3416 3416 ASSERT(isp != NULL);
3417 3417
3418 3418 /* PENDING */
3419 3419 rw_enter(&isp->sess_state_rwlock, RW_READER);
3420 3420 mutex_enter(&isp->sess_queue_pending.mutex);
3421 3421 for (icmdp = isp->sess_queue_pending.head;
3422 3422 icmdp; icmdp = nicmdp) {
3423 3423 nicmdp = icmdp->cmd_next;
3424 3424
3425 3425 /* Skip entries with no timeout */
3426 3426 if (icmdp->cmd_lbolt_timeout == 0)
3427 3427 continue;
3428 3428
3429 3429 /*
3430 3430 * Skip pending queue entries for cmd_type values that depend
3431 3431 * on having an open cmdsn window for successfull transition
3432 3432 * from pending to the active (i.e. ones that depend on
3433 3433 * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
3434 3434 * when they are successfully moved to the active queue by
3435 3435 * iscsi_cmd_state_pending() code.
3436 3436 */
3437 3437 /*
3438 3438 * If the cmd is stuck, at least give it a chance
3439 3439 * to timeout
3440 3440 */
3441 3441 if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
3442 3442 (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
3443 3443 !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
3444 3444 continue;
3445 3445
3446 3446 /* Skip if timeout still in the future */
3447 3447 if (now <= icmdp->cmd_lbolt_timeout)
3448 3448 continue;
3449 3449
3450 3450 /* timeout */
3451 3451 iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3452 3452 }
3453 3453 mutex_exit(&isp->sess_queue_pending.mutex);
3454 3454 rw_exit(&isp->sess_state_rwlock);
3455 3455
3456 3456 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3457 3457 icp = isp->sess_conn_list;
3458 3458 while (icp != NULL) {
3459 3459
3460 3460 icp->conn_timeout = B_FALSE;
3461 3461 /* ACTIVE */
3462 3462 mutex_enter(&icp->conn_state_mutex);
3463 3463 mutex_enter(&isp->sess_queue_pending.mutex);
3464 3464 mutex_enter(&icp->conn_queue_active.mutex);
3465 3465 for (icmdp = icp->conn_queue_active.head;
3466 3466 icmdp; icmdp = nicmdp) {
3467 3467 nicmdp = icmdp->cmd_next;
3468 3468
3469 3469 if (iscsi_nop_timeout_checks(icmdp) == B_TRUE) {
3470 3470 icp->conn_timeout = B_TRUE;
3471 3471 }
3472 3472
3473 3473 /* Skip entries with no timeout */
3474 3474 if (icmdp->cmd_lbolt_timeout == 0)
3475 3475 continue;
3476 3476
3477 3477 /*
3478 3478 * Skip if command is not active or not needed
3479 3479 * to flush.
3480 3480 */
3481 3481 if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE &&
3482 3482 !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH))
3483 3483 continue;
3484 3484
3485 3485 /* Skip if timeout still in the future */
3486 3486 if (now <= icmdp->cmd_lbolt_timeout)
3487 3487 continue;
3488 3488
3489 3489 if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH) {
3490 3490 /*
3491 3491 * This command is left during target reset,
3492 3492 * we can flush it now.
3493 3493 */
3494 3494 iscsi_cmd_state_machine(icmdp,
3495 3495 ISCSI_CMD_EVENT_E7, isp);
3496 3496 } else if (icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE) {
3497 3497 /* timeout */
3498 3498 iscsi_cmd_state_machine(icmdp,
3499 3499 ISCSI_CMD_EVENT_E6, isp);
3500 3500 }
3501 3501
3502 3502 }
3503 3503 mutex_exit(&icp->conn_queue_active.mutex);
3504 3504 mutex_exit(&isp->sess_queue_pending.mutex);
3505 3505 mutex_exit(&icp->conn_state_mutex);
3506 3506
3507 3507 icp = icp->conn_next;
3508 3508 }
3509 3509
3510 3510 icp = isp->sess_conn_list;
3511 3511 while (icp != NULL) {
3512 3512 if (icp->conn_timeout == B_TRUE) {
3513 3513 /* timeout on this connect detected */
3514 3514 idm_ini_conn_disconnect(icp->conn_ic);
3515 3515 icp->conn_timeout = B_FALSE;
3516 3516 }
3517 3517 icp = icp->conn_next;
3518 3518 }
3519 3519 rw_exit(&isp->sess_conn_list_rwlock);
3520 3520 }
3521 3521
3522 3522 /*
3523 3523 * iscsi_nop_checks - sends a NOP on idle connections
3524 3524 *
3525 3525 * This function walks the connections on a session and
3526 3526 * issues NOPs on those connections that are in FULL
3527 3527 * FEATURE mode and have not received data for the
3528 3528 * time period specified by iscsi_nop_delay (global).
3529 3529 */
3530 3530 static void
3531 3531 iscsi_nop_checks(iscsi_sess_t *isp)
3532 3532 {
3533 3533 iscsi_conn_t *icp;
3534 3534
3535 3535 ASSERT(isp != NULL);
3536 3536
3537 3537 if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
3538 3538 return;
3539 3539 }
3540 3540
3541 3541 rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3542 3542 icp = isp->sess_conn_act;
3543 3543 if (icp != NULL) {
3544 3544
3545 3545 mutex_enter(&icp->conn_state_mutex);
3546 3546 if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
3547 3547 (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
3548 3548 SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
3549 3549 isp->sess_conn_act->conn_nop_lbolt +
3550 3550 SEC_TO_TICK(iscsi_nop_delay))) {
3551 3551
3552 3552 /*
3553 3553 * We haven't received anything from the
3554 3554 * target is a defined period of time,
3555 3555 * send NOP to see if the target is alive.
3556 3556 */
3557 3557 mutex_enter(&isp->sess_queue_pending.mutex);
3558 3558 iscsi_handle_nop(isp->sess_conn_act,
3559 3559 0, ISCSI_RSVD_TASK_TAG);
3560 3560 mutex_exit(&isp->sess_queue_pending.mutex);
3561 3561 }
3562 3562 mutex_exit(&icp->conn_state_mutex);
3563 3563
3564 3564 icp = icp->conn_next;
3565 3565 }
3566 3566 rw_exit(&isp->sess_conn_list_rwlock);
3567 3567 }
3568 3568
3569 3569 static boolean_t
3570 3570 iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp)
3571 3571 {
3572 3572 if (icmdp->cmd_type == ISCSI_CMD_TYPE_NOP) {
3573 3573 if ((ddi_get_lbolt() - icmdp->cmd_lbolt_active) >
3574 3574 SEC_TO_TICK(ISCSI_CONN_TIEMOUT_DETECT)) {
3575 3575 return (B_TRUE);
3576 3576 } else {
3577 3577 return (B_FALSE);
3578 3578 }
3579 3579 }
3580 3580 return (B_FALSE);
3581 3581 }
3582 3582 /*
3583 3583 * +--------------------------------------------------------------------+
3584 3584 * | End of wd routines |
3585 3585 * +--------------------------------------------------------------------+
3586 3586 */
3587 3587
3588 3588 /*
3589 3589 * iscsi_flush_cmd_after_reset - flush commands after reset
3590 3590 *
3591 3591 * Here we will flush all the commands for a specified LUN whose cmdsn is less
3592 3592 * than the one received with the Unit Attention.
3593 3593 */
3594 3594 static void
3595 3595 iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
3596 3596 iscsi_conn_t *icp)
3597 3597 {
3598 3598 iscsi_cmd_t *t_icmdp = NULL;
3599 3599 iscsi_cmd_t *next_icmdp = NULL;
3600 3600
3601 3601 ASSERT(icp != NULL);
3602 3602
3603 3603 t_icmdp = icp->conn_queue_active.head;
3604 3604 while (t_icmdp != NULL) {
3605 3605 next_icmdp = t_icmdp->cmd_next;
3606 3606 mutex_enter(&t_icmdp->cmd_mutex);
3607 3607 /*
3608 3608 * We will flush the commands whose cmdsn is less than the one
3609 3609 * got Unit Attention.
3610 3610 * Here we will check for wrap by subtracting and compare to
3611 3611 * 1/2 of a 32 bit number, if greater then we wrapped.
3612 3612 */
3613 3613 if ((t_icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_SENT) &&
3614 3614 ((cmd_sn > t_icmdp->cmd_sn) ||
3615 3615 ((t_icmdp->cmd_sn - cmd_sn) >
3616 3616 ISCSI_CMD_SN_WRAP))) {
3617 3617 /*
3618 3618 * Internally generated SCSI commands do not have
3619 3619 * t_icmdp->cmd_lun set, but the LUN can be retrieved
3620 3620 * from t_icmdp->cmd_un.scsi.lun.
3621 3621 */
3622 3622 if ((t_icmdp->cmd_lun != NULL &&
3623 3623 t_icmdp->cmd_lun->lun_num == lun_num) ||
3624 3624 (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI &&
3625 3625 (t_icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK) ==
3626 3626 lun_num)) {
3627 3627 t_icmdp->cmd_misc_flags |=
3628 3628 ISCSI_CMD_MISCFLAG_FLUSH;
3629 3629 if (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
3630 3630 t_icmdp->cmd_un.scsi.pkt_stat |=
3631 3631 STAT_BUS_RESET;
3632 3632 }
3633 3633 }
3634 3634 }
3635 3635 mutex_exit(&t_icmdp->cmd_mutex);
3636 3636 t_icmdp = next_icmdp;
3637 3637 }
3638 3638 }
3639 3639
3640 3640 /*
3641 3641 * iscsi_decode_sense - decode the sense data in the cmd response
3642 3642 * and take proper actions
3643 3643 */
3644 3644 static boolean_t
3645 3645 iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp)
3646 3646 {
3647 3647 uint8_t sense_key = 0;
3648 3648 uint8_t asc = 0;
3649 3649 uint8_t ascq = 0;
3650 3650 boolean_t flush_io = B_FALSE;
3651 3651 boolean_t reconfig_lun = B_FALSE;
3652 3652 iscsi_sess_t *isp = NULL;
3653 3653
3654 3654 ASSERT(sense_data != NULL);
3655 3655
3656 3656 isp = icmdp->cmd_conn->conn_sess;
3657 3657
3658 3658 sense_key = scsi_sense_key(sense_data);
3659 3659 switch (sense_key) {
3660 3660 case KEY_UNIT_ATTENTION:
3661 3661 asc = scsi_sense_asc(sense_data);
3662 3662 switch (asc) {
3663 3663 case ISCSI_SCSI_RESET_SENSE_CODE:
3664 3664 /*
3665 3665 * POWER ON, RESET, OR BUS_DEVICE RESET
3666 3666 * OCCURRED
3667 3667 */
3668 3668 flush_io = B_TRUE;
3669 3669 break;
3670 3670 case ISCSI_SCSI_LUNCHANGED_CODE:
3671 3671 ascq = scsi_sense_ascq(sense_data);
3672 3672 if (ascq == ISCSI_SCSI_LUNCHANGED_ASCQ)
3673 3673 reconfig_lun = B_TRUE;
3674 3674 default:
3675 3675 break;
3676 3676 }
3677 3677 break;
3678 3678 default:
3679 3679 /*
3680 3680 * Currently we don't care
3681 3681 * about other sense key.
3682 3682 */
3683 3683 break;
3684 3684 }
3685 3685
3686 3686 if (reconfig_lun == B_TRUE) {
3687 3687 rw_enter(&isp->sess_state_rwlock, RW_READER);
3688 3688 if ((isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) &&
3689 3689 (iscsi_sess_enum_request(isp, B_FALSE,
3690 3690 isp->sess_state_event_count) !=
3691 3691 ISCSI_SESS_ENUM_SUBMITTED)) {
3692 3692 cmn_err(CE_WARN, "Unable to commit re-enumeration for"
3693 3693 " session(%u) %s", isp->sess_oid, isp->sess_name);
3694 3694 }
3695 3695 rw_exit(&isp->sess_state_rwlock);
3696 3696 }
3697 3697
3698 3698 return (flush_io);
3699 3699 }
|
↓ open down ↓ |
2504 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX