Print this page
NEX-9981 Deadman timer panic from idm_refcnt_wait_ref thread while offlining iSCSI targets
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_cmd.c
+++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_cmd.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.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 26 * iSCSI command interfaces
26 27 */
27 28
28 29 #include "iscsi.h"
29 30
30 31 /* internal interfaces */
31 32 static void iscsi_cmd_state_free(iscsi_cmd_t *icmdp,
32 33 iscsi_cmd_event_t event, void *arg);
33 34 static void iscsi_cmd_state_pending(iscsi_cmd_t *icmdp,
34 35 iscsi_cmd_event_t event, void *arg);
35 36 static void iscsi_cmd_state_active(iscsi_cmd_t *icmdp,
36 37 iscsi_cmd_event_t event, void *arg);
37 38 static void iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp,
38 39 iscsi_cmd_event_t event, void *arg);
39 40 static void iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp,
40 41 iscsi_cmd_event_t event, void *arg);
41 42 static void iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
42 43 iscsi_cmd_event_t event, void *arg);
43 44 static char *iscsi_cmd_state_str(iscsi_cmd_state_t state);
44 45 static char *iscsi_cmd_event_str(iscsi_cmd_event_t event);
45 46 /* LINTED E_STATIC_UNUSED */
46 47 static char *iscsi_cmd_type_str(iscsi_cmd_type_t type);
47 48
48 49 #define ISCSI_INTERNAL_CMD_TIMEOUT 60
49 50
50 51 #define ISCSI_CMD_ISSUE_CALLBACK(icmdp, status) \
51 52 icmdp->cmd_completed = B_TRUE; \
52 53 icmdp->cmd_result = status; \
53 54 cv_broadcast(&icmdp->cmd_completion);
54 55
55 56 #define ISCSI_CMD_SET_REASON_STAT(icmdp, reason, stat) \
56 57 icmdp->cmd_un.scsi.pkt->pkt_reason = reason; \
57 58 icmdp->cmd_un.scsi.pkt->pkt_statistics = stat;
58 59
59 60 /*
60 61 * The following private tunable, settable via
61 62 * set iscsi:iscsi_cmd_timeout_factor = 2
62 63 * in /etc/system, provides customer relief for configurations experiencing
63 64 * SCSI command timeouts due to high-latency/high-loss network connections
64 65 * or slow target response (possibly due to backing store issues). If frequent
65 66 * use of this tunable is necessary, a beter mechanism must be provided.
66 67 */
67 68 int iscsi_cmd_timeout_factor = 1;
68 69
69 70 /*
70 71 * +--------------------------------------------------------------------+
71 72 * | External Command Interfaces |
72 73 * +--------------------------------------------------------------------+
73 74 */
74 75
75 76 /*
76 77 * iscsi_cmd_state_machine - This function is used to drive the
77 78 * state machine of the internal iscsi commands. It takes in a command
78 79 * and the associated event affecting the command.
79 80 *
80 81 * 7.1.3 Command State Diagram for an Initiator
81 82 * Symbolic Names for States:
82 83 * C1: FREE - State on instantiation, or after successful
83 84 * completion.
84 85 * C2: PENDING - Command is in the session's pending queue awaiting
85 86 * its turn to be sent on the wire.
86 87 * C3: ACTIVE - Command has been sent on the wire and is
87 88 * awaiting completion.
88 89 * C4: ABORTING - Command which was sent on the wire has not timed
89 90 * out or been requested to abort by an upper layer
90 91 * driver. At this point there is a task management
91 92 * command in the active queue trying to abort the task.
92 93 * C4': IDM ABORTING - SCSI command is owned by IDM and idm_task_abort
93 94 * has been called for this command.
94 95 * C5: COMPLETED - Command which is ready to complete via pkt callback.
95 96 *
96 97 * The state diagram is as follows:
97 98 * -------
98 99 * / C1 \
99 100 * I-------->\ /<------------
100 101 * N| ---+--- |
101 102 * T| |E1 |
102 103 * E| V |
103 104 * R| ------- |
104 105 * N+--------/ C2 \ |
105 106 * A| E4/6/7\ /-------- |
106 107 * L| ---+--- E4/6/7| |
107 108 * | |E2 E10 | |
108 109 * C| V | S |
109 110 * M| _______ | C |
110 111 * D+--------/ C3 \ | S |
111 112 * S E3/4/6/7\ /-------+ I |
112 113 * /---+---E3/4/6/7| |
113 114 * / | E9/10| |
114 115 * ------/ E4/6| | C |
115 116 * | V | M |
116 117 * E7| ------- | D |
117 118 * SCSI| - >/ C4 \ | S |
118 119 * | / \ /-------+ |
119 120 * | | ---+---E3/6/7/9| |
120 121 * | | E4| | V /E8
121 122 * | ------ | -------
122 123 * +-\ / / C5 \
123 124 * V \-------/ /---->\ /
124 125 * ------- E7 / ---+---
125 126 * / C4' \ /
126 127 * \ /------/ E9
127 128 * -------
128 129 *
129 130 * The state transition table is as follows:
130 131 *
131 132 * +---------+---+---+-----+----+--------------+
132 133 * |C1 |C2 |C3 |C4 |C4' |C5 |
133 134 * ---+---------+---+---+-----+----+--------------+
134 135 * C1| - |E1 | - | - | - | |
135 136 * ---+---------+---+---+-----+----+--------------+
136 137 * C2|E4/6/7 |- |E2 | - | - |E4/6/7/10 |
137 138 * ---+---------+---+---+-----+----+--------------+
138 139 * C3|E3/4/6/7 |- |- |E4/6 |E7 |E3/4/6/7/9/10 |
139 140 * ---+---------+---+---+-----+----+--------------+
140 141 * C4| |- |- |E4 |E7 |E3/6/7/9 |
141 142 * ---+---------+---+---+-----+----+--------------+
142 143 * C4'| |- |- |- |- |E9 |
143 144 * ---+---------+---+---+-----+----+--------------+
144 145 * C5|E8 | | | | | |
145 146 * ---+---------+---+---+-----+----+--------------+
146 147 *
147 148 * Event definitions:
148 149 *
149 150 * -E1: Command was requested to be sent on wire
150 151 * -E2: Command was submitted and now active on wire
151 152 * -E3: Command was successfully completed
152 153 * - SCSI command is move to completion queue
153 154 * - ABORT/RESET/etc are completed.
154 155 * -E4: Command has been requested to abort
155 156 * - SCSI command in pending queue will be returned
156 157 * to caller with aborted status.
157 158 * - SCSI command state updated and iscsi_handle_abort()
158 159 * will be called.
159 160 * - SCSI command with ABORTING state has already
160 161 * been requested to abort ignore request.
161 162 * - ABORT/RESET commands will be destroyed and the
162 163 * caller will be notify of the failure.
163 164 * - All other commands will just be destroyed.
164 165 * -E6: Command has timed out
165 166 * - SCSI commands in pending queue will be returned up the
166 167 * stack with TIMEOUT errors.
167 168 * - SCSI commands in the active queue and timed out
168 169 * will be moved to the aborting queue.
169 170 * - SCSI commands in ABORTING state will be returned up
170 171 * up the stack with TIMEOUT errors.
171 172 * - ABORT/RESET commands will be destroyed and the caller
172 173 * notified of the failure.
173 174 * - All other commands will just be detroyed.
174 175 * -E7: Connection has encountered a problem
175 176 * -E8: Command has completed
176 177 * - Only SCSI cmds should receive these events
177 178 * and reach the command state.
178 179 * -E9: Callback received for previous idm_task_abort request
179 180 * -E10: The command this abort was associated with has terminated on its own
180 181 */
181 182 void
182 183 iscsi_cmd_state_machine(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
183 184 {
184 185 boolean_t release_lock = B_TRUE;
185 186
186 187 ASSERT(icmdp != NULL);
187 188 ASSERT(arg != NULL);
188 189
189 190 DTRACE_PROBE3(event, iscsi_cmd_t *, icmdp, char *,
190 191 iscsi_cmd_state_str(icmdp->cmd_state),
191 192 char *, iscsi_cmd_event_str(event));
192 193
193 194 mutex_enter(&icmdp->cmd_mutex);
194 195
195 196 /* Audit event */
196 197 idm_sm_audit_event(&icmdp->cmd_state_audit,
197 198 SAS_ISCSI_CMD, icmdp->cmd_state, event, (uintptr_t)arg);
198 199
199 200 icmdp->cmd_prev_state = icmdp->cmd_state;
200 201 switch (icmdp->cmd_state) {
201 202 case ISCSI_CMD_STATE_FREE:
202 203 iscsi_cmd_state_free(icmdp, event, arg);
203 204 break;
204 205
205 206 case ISCSI_CMD_STATE_PENDING:
206 207 iscsi_cmd_state_pending(icmdp, event, arg);
207 208 break;
208 209
209 210 case ISCSI_CMD_STATE_ACTIVE:
210 211 iscsi_cmd_state_active(icmdp, event, arg);
211 212 break;
212 213
213 214 case ISCSI_CMD_STATE_ABORTING:
214 215 iscsi_cmd_state_aborting(icmdp, event, arg);
215 216 break;
216 217
217 218 case ISCSI_CMD_STATE_IDM_ABORTING:
218 219 iscsi_cmd_state_idm_aborting(icmdp, event, arg);
219 220 break;
220 221
221 222 case ISCSI_CMD_STATE_COMPLETED:
222 223 iscsi_cmd_state_completed(icmdp, event, arg);
223 224
224 225 /*
225 226 * Once completed event is processed we DO NOT
226 227 * want to touch it again because the caller
227 228 * (sd, st, etc) may have freed the command.
228 229 */
229 230 release_lock = B_FALSE;
230 231 break;
231 232
232 233 default:
233 234 ASSERT(FALSE);
234 235 }
235 236
236 237 if (release_lock == B_TRUE) {
237 238 /* Audit state if not completed */
238 239 idm_sm_audit_state_change(&icmdp->cmd_state_audit,
239 240 SAS_ISCSI_CMD, icmdp->cmd_prev_state, icmdp->cmd_state);
240 241
241 242 if (!(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FREE) ||
242 243 !(icmdp->cmd_misc_flags &
243 244 ISCSI_CMD_MISCFLAG_INTERNAL)) {
244 245 mutex_exit(&icmdp->cmd_mutex);
245 246 return;
246 247 }
247 248 mutex_exit(&icmdp->cmd_mutex);
248 249 iscsi_cmd_free(icmdp);
249 250 }
250 251 }
251 252
252 253 /*
253 254 * iscsi_cmd_alloc -
254 255 *
255 256 */
256 257 iscsi_cmd_t *
257 258 iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags)
258 259 {
259 260 iscsi_cmd_t *icmdp;
260 261
261 262 icmdp = kmem_zalloc(sizeof (iscsi_cmd_t), km_flags);
262 263 if (icmdp) {
263 264 icmdp->cmd_sig = ISCSI_SIG_CMD;
264 265 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
265 266 icmdp->cmd_conn = icp;
266 267 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_INTERNAL;
267 268 idm_sm_audit_init(&icmdp->cmd_state_audit);
268 269 mutex_init(&icmdp->cmd_mutex, NULL, MUTEX_DRIVER, NULL);
269 270 cv_init(&icmdp->cmd_completion, NULL, CV_DRIVER, NULL);
270 271 }
271 272 return (icmdp);
272 273 }
273 274
274 275 /*
275 276 * iscsi_cmd_free -
276 277 *
277 278 */
278 279 void
279 280 iscsi_cmd_free(iscsi_cmd_t *icmdp)
280 281 {
281 282 ASSERT(icmdp != NULL);
282 283 ASSERT(icmdp->cmd_sig == ISCSI_SIG_CMD);
283 284 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
284 285 ASSERT(icmdp->cmd_next == NULL);
285 286 ASSERT(icmdp->cmd_prev == NULL);
286 287 ASSERT(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL);
287 288 if (icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT)
288 289 ASSERT(icmdp->cmd_un.abort.icmdp == NULL);
289 290 else if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
290 291 ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
291 292 ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
292 293 }
293 294 mutex_destroy(&icmdp->cmd_mutex);
294 295 cv_destroy(&icmdp->cmd_completion);
295 296 kmem_free(icmdp, sizeof (iscsi_cmd_t));
296 297 }
297 298
298 299 /*
299 300 * +--------------------------------------------------------------------+
300 301 * | Internal Command Interfaces |
301 302 * +--------------------------------------------------------------------+
302 303 */
303 304 /*
304 305 * iscsi_cmd_state_free -
305 306 *
306 307 */
307 308 static void
308 309 iscsi_cmd_state_free(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
309 310 {
310 311 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
311 312
312 313 ASSERT(icmdp != NULL);
313 314 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_FREE);
314 315 ASSERT(isp != NULL);
315 316
316 317 /* switch on event change */
317 318 switch (event) {
318 319 /* -E1: Command was requested to be sent on wire */
319 320 case ISCSI_CMD_EVENT_E1:
320 321
321 322 /* setup timestamps and timeouts for this command */
322 323 icmdp->cmd_lbolt_pending = ddi_get_lbolt();
323 324 if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
324 325 /*
325 326 * Establish absolute time when command should timeout.
326 327 * For commands that depend on cmdsn window to go
327 328 * active, the timeout will be ignored while on
328 329 * the pending queue and a new timeout will be
329 330 * established when the command goes active.
330 331 */
331 332 if (icmdp->cmd_un.scsi.pkt &&
332 333 icmdp->cmd_un.scsi.pkt->pkt_time)
333 334 icmdp->cmd_lbolt_timeout =
334 335 icmdp->cmd_lbolt_pending + SEC_TO_TICK(
335 336 icmdp->cmd_un.scsi.pkt->pkt_time *
336 337 iscsi_cmd_timeout_factor);
337 338 else
338 339 icmdp->cmd_lbolt_timeout = 0;
339 340
340 341 icmdp->cmd_un.scsi.pkt_stat &=
341 342 ISCSI_CMD_PKT_STAT_INIT;
342 343 } else {
343 344 icmdp->cmd_lbolt_timeout = icmdp->cmd_lbolt_pending +
344 345 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
345 346 iscsi_cmd_timeout_factor);
346 347 }
347 348
348 349 /* place into pending queue */
349 350 iscsi_enqueue_pending_cmd(isp, icmdp);
350 351
351 352 break;
352 353
353 354 /* All other events are invalid for this state */
354 355 default:
355 356 ASSERT(FALSE);
356 357 }
357 358 }
358 359
359 360 /*
360 361 * iscsi_cmd_state_pending -
361 362 *
362 363 */
363 364 static void
364 365 iscsi_cmd_state_pending(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
365 366 {
366 367 iscsi_status_t status;
367 368 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
368 369 boolean_t free_icmdp = B_FALSE;
369 370 int rval;
370 371
371 372 ASSERT(icmdp != NULL);
372 373 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_PENDING);
373 374 ASSERT(isp != NULL);
374 375
375 376 /* switch on event change */
376 377 switch (event) {
377 378 /* -E2: Command was submitted and now active on wire */
378 379 case ISCSI_CMD_EVENT_E2:
379 380
380 381 /* A connection should have already been assigned */
381 382 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
382 383 ASSERT(icmdp->cmd_conn != NULL);
383 384
384 385 /*
385 386 * RESERVE RESOURSES
386 387 */
387 388 switch (icmdp->cmd_type) {
388 389 case ISCSI_CMD_TYPE_SCSI:
389 390 /* check cmdsn window */
390 391 mutex_enter(&isp->sess_cmdsn_mutex);
391 392 if (!iscsi_sna_lte(isp->sess_cmdsn,
392 393 isp->sess_maxcmdsn)) {
393 394 /* cmdsn window closed */
394 395 mutex_exit(&isp->sess_cmdsn_mutex);
395 396 mutex_exit(&isp->sess_queue_pending.mutex);
396 397 isp->sess_window_open = B_FALSE;
397 398 icmdp->cmd_misc_flags |=
398 399 ISCSI_CMD_MISCFLAG_STUCK;
399 400 return;
400 401 }
401 402
402 403 /* assign itt */
403 404 status = iscsi_sess_reserve_scsi_itt(icmdp);
404 405 if (!ISCSI_SUCCESS(status)) {
405 406 /* no available itt slots */
406 407 mutex_exit(&isp->sess_cmdsn_mutex);
407 408 mutex_exit(&isp->sess_queue_pending.mutex);
408 409 isp->sess_window_open = B_FALSE;
409 410 icmdp->cmd_misc_flags |=
410 411 ISCSI_CMD_MISCFLAG_STUCK;
411 412 return;
412 413 }
413 414 mutex_exit(&isp->sess_cmdsn_mutex);
414 415 break;
415 416
416 417 case ISCSI_CMD_TYPE_ABORT:
417 418 /*
418 419 * Verify ABORT's parent SCSI command is still
419 420 * there. If parent SCSI command is completed
420 421 * then there is no longer any reason to abort
421 422 * the parent command. This could occur due
422 423 * to a connection or target reset.
423 424 */
424 425 ASSERT(icmdp->cmd_un.abort.icmdp != NULL);
425 426 if (icmdp->cmd_un.abort.icmdp->cmd_state ==
426 427 ISCSI_CMD_STATE_COMPLETED) {
427 428 iscsi_dequeue_pending_cmd(isp, icmdp);
428 429 mutex_exit(&isp->sess_queue_pending.mutex);
429 430
430 431 mutex_enter(&icmdp->cmd_un.abort.icmdp->
431 432 cmd_mutex);
432 433 icmdp->cmd_un.abort.icmdp->
433 434 cmd_un.scsi.abort_icmdp = NULL;
434 435 cv_broadcast(&icmdp->cmd_un.abort.icmdp->
435 436 cmd_completion);
436 437 mutex_exit(&icmdp->cmd_un.abort.icmdp->
437 438 cmd_mutex);
438 439 icmdp->cmd_un.abort.icmdp = NULL;
439 440
440 441 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
441 442 icmdp->cmd_misc_flags |=
442 443 ISCSI_CMD_MISCFLAG_FREE;
443 444 return;
444 445 }
445 446 /* FALLTHRU */
446 447 case ISCSI_CMD_TYPE_RESET:
447 448 /* FALLTHRU */
448 449 case ISCSI_CMD_TYPE_LOGOUT:
449 450 mutex_enter(&isp->sess_cmdsn_mutex);
450 451 /* assign itt */
451 452 status = iscsi_sess_reserve_itt(isp, icmdp);
452 453 if (!ISCSI_SUCCESS(status)) {
453 454 /* no available itt slots */
454 455 mutex_exit(&isp->sess_cmdsn_mutex);
455 456 mutex_exit(&isp->sess_queue_pending.mutex);
456 457 isp->sess_window_open = B_FALSE;
457 458 return;
458 459 }
459 460 mutex_exit(&isp->sess_cmdsn_mutex);
460 461 break;
461 462 case ISCSI_CMD_TYPE_NOP:
462 463 /* assign itt, if needed */
463 464 if (icmdp->cmd_itt == ISCSI_RSVD_TASK_TAG) {
464 465 /* not expecting a response */
465 466 free_icmdp = B_TRUE;
466 467 } else {
467 468 /* expecting response, assign an itt */
468 469 mutex_enter(&isp->sess_cmdsn_mutex);
469 470 /* assign itt */
470 471 status = iscsi_sess_reserve_itt(isp, icmdp);
471 472 if (!ISCSI_SUCCESS(status)) {
472 473 /* no available itt slots */
473 474 mutex_exit(&isp->sess_cmdsn_mutex);
474 475 mutex_exit(&isp->sess_queue_pending.
475 476 mutex);
476 477 isp->sess_window_open = B_FALSE;
477 478 return;
478 479 }
479 480 mutex_exit(&isp->sess_cmdsn_mutex);
480 481 }
481 482 break;
482 483
483 484 case ISCSI_CMD_TYPE_TEXT:
484 485 mutex_enter(&isp->sess_cmdsn_mutex);
485 486 /* check cmdsn window */
486 487 if (!iscsi_sna_lte(isp->sess_cmdsn,
487 488 isp->sess_maxcmdsn)) {
488 489 /* cmdsn window closed */
489 490 isp->sess_window_open = B_FALSE;
490 491 mutex_exit(&isp->sess_cmdsn_mutex);
491 492 mutex_exit(&isp->sess_queue_pending.mutex);
492 493 icmdp->cmd_misc_flags |=
493 494 ISCSI_CMD_MISCFLAG_STUCK;
494 495 return;
495 496 }
496 497 if (icmdp->cmd_un.text.stage ==
497 498 ISCSI_CMD_TEXT_INITIAL_REQ) {
498 499 /* assign itt */
499 500 status = iscsi_sess_reserve_itt(isp, icmdp);
500 501 if (!ISCSI_SUCCESS(status)) {
501 502 /* no available itt slots */
502 503 mutex_exit(&isp->sess_cmdsn_mutex);
503 504 mutex_exit(&isp->sess_queue_pending.
504 505 mutex);
505 506 isp->sess_window_open = B_FALSE;
506 507 icmdp->cmd_misc_flags |=
507 508 ISCSI_CMD_MISCFLAG_STUCK;
508 509 return;
509 510 }
510 511 }
511 512 mutex_exit(&isp->sess_cmdsn_mutex);
512 513 break;
513 514
514 515 default:
515 516 ASSERT(FALSE);
516 517 }
517 518
518 519 /*
519 520 * RESOURCES RESERVED
520 521 *
521 522 * Now that we have the resources reserved, establish timeout
522 523 * for cmd_type values that depend on having an open cmdsn
523 524 * window (i.e. cmd_type that called iscsi_sna_lte() above).
524 525 */
525 526 if (icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
526 527 if (icmdp->cmd_un.scsi.pkt &&
527 528 icmdp->cmd_un.scsi.pkt->pkt_time)
528 529 icmdp->cmd_lbolt_timeout =
529 530 ddi_get_lbolt() + SEC_TO_TICK(
530 531 icmdp->cmd_un.scsi.pkt->pkt_time *
531 532 iscsi_cmd_timeout_factor);
532 533 else
533 534 icmdp->cmd_lbolt_timeout = 0;
534 535 } else if (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT) {
535 536 icmdp->cmd_lbolt_timeout = ddi_get_lbolt() +
536 537 SEC_TO_TICK(ISCSI_INTERNAL_CMD_TIMEOUT *
537 538 iscsi_cmd_timeout_factor);
538 539 }
539 540
540 541 /* remove command from pending queue */
541 542 iscsi_dequeue_pending_cmd(isp, icmdp);
542 543 /* check if expecting a response */
543 544 if (free_icmdp == B_FALSE) {
544 545 /* response expected, move to active queue */
545 546 mutex_enter(&icmdp->cmd_conn->conn_queue_active.mutex);
546 547 iscsi_enqueue_active_cmd(icmdp->cmd_conn, icmdp);
547 548 mutex_exit(&icmdp->cmd_conn->conn_queue_active.mutex);
548 549 }
549 550
550 551 /*
551 552 * TRANSFER COMMAND
552 553 */
553 554 rval = iscsi_tx_cmd(isp, icmdp);
554 555
555 556 ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
556 557
557 558 /*
558 559 * CHECK SUCCESS/FAILURE
559 560 */
560 561 if (!ISCSI_SUCCESS(rval)) {
561 562 /*
562 563 * iscsi_tx_cmd failed. No cleanup is required
563 564 * of commands that were put in the active queue.
564 565 * If the tx failed then rx will also fail and cleanup
565 566 * all items in the active/aborted queue in a common.
566 567 */
567 568
568 569 /* EMPTY */
569 570 }
570 571
571 572 /* free temporary commands */
572 573 if (free_icmdp == B_TRUE) {
573 574 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
574 575 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
575 576 }
576 577 break;
577 578
578 579 /* -E10: Abort is no longer required for this command */
579 580 case ISCSI_CMD_EVENT_E10:
580 581 /*
581 582 * Acquiring the sess_queue_pending lock while the
582 583 * conn_queue_active lock is held conflicts with the
583 584 * locking order in iscsi_cmd_state_pending where
584 585 * conn_queue_active is acquired while sess_queue_pending
585 586 * is held. Normally this would be a dangerous lock
586 587 * order conflict, except that we know that if we are
587 588 * seeing ISCSI_CMD_EVENT_E10 then the command being
588 589 * aborted is in "aborting" state and by extension
589 590 * is not in "pending" state. Therefore the code
590 591 * path with that alternate lock order will not execute.
591 592 * That's good because we can't drop the lock here without
592 593 * risking a deadlock.
593 594 */
594 595 ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
595 596 mutex_enter(&isp->sess_queue_pending.mutex);
596 597
597 598 icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
598 599
599 600 iscsi_dequeue_pending_cmd(isp, icmdp);
600 601
601 602 icmdp->cmd_un.abort.icmdp->cmd_un.scsi.abort_icmdp = NULL;
602 603 icmdp->cmd_un.abort.icmdp = NULL;
603 604 icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_FREE;
604 605 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
605 606
606 607 mutex_exit(&isp->sess_queue_pending.mutex);
607 608 break;
608 609
609 610 /* -E4: Command has been requested to abort */
610 611 case ISCSI_CMD_EVENT_E4:
611 612 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
612 613
613 614 icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
614 615 ISCSI_CMD_SET_REASON_STAT(icmdp,
615 616 CMD_ABORTED, STAT_ABORTED);
616 617
617 618 iscsi_dequeue_pending_cmd(isp, icmdp);
618 619 iscsi_enqueue_completed_cmd(isp, icmdp);
619 620
620 621 icmdp->cmd_lbolt_aborting = ddi_get_lbolt();
621 622
622 623 break;
623 624
624 625 /* -E7: Command has been reset */
625 626 case ISCSI_CMD_EVENT_E7:
626 627
627 628 /* FALLTHRU */
628 629
629 630 /* -E6: Command has timed out */
630 631 case ISCSI_CMD_EVENT_E6:
631 632 ASSERT(mutex_owned(&isp->sess_queue_pending.mutex));
632 633 iscsi_dequeue_pending_cmd(isp, icmdp);
633 634
634 635 switch (icmdp->cmd_type) {
635 636 case ISCSI_CMD_TYPE_SCSI:
636 637 /* Complete to caller as TIMEOUT */
637 638 if (event == ISCSI_CMD_EVENT_E6) {
638 639 ISCSI_CMD_SET_REASON_STAT(icmdp,
639 640 CMD_TIMEOUT, STAT_TIMEOUT);
640 641 } else {
641 642 ISCSI_CMD_SET_REASON_STAT(icmdp,
642 643 CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
643 644 }
644 645 iscsi_enqueue_completed_cmd(isp, icmdp);
645 646 break;
646 647
647 648 case ISCSI_CMD_TYPE_NOP:
648 649 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
649 650 /*
650 651 * Timeout occured. Just free NOP. Another
651 652 * NOP request will be spawned to replace
652 653 * this one.
653 654 */
654 655 icmdp->cmd_misc_flags |=
655 656 ISCSI_CMD_MISCFLAG_FREE;
656 657
657 658 break;
658 659
659 660 case ISCSI_CMD_TYPE_ABORT:
660 661 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
661 662 icmdp->cmd_un.abort.icmdp->
662 663 cmd_un.scsi.abort_icmdp = NULL;
663 664 cv_broadcast(&icmdp->cmd_un.abort.icmdp->
664 665 cmd_completion);
665 666 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
666 667 icmdp->cmd_un.abort.icmdp = NULL;
667 668
668 669 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
669 670 icmdp->cmd_misc_flags |=
670 671 ISCSI_CMD_MISCFLAG_FREE;
671 672 break;
672 673
673 674 case ISCSI_CMD_TYPE_RESET:
674 675 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
675 676 /*
676 677 * If we are failing a RESET we need
677 678 * to notify the tran_reset caller.
678 679 * with the cmd and notify caller.
679 680 */
680 681 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
681 682 ISCSI_STATUS_CMD_FAILED);
682 683 break;
683 684
684 685 case ISCSI_CMD_TYPE_LOGOUT:
685 686 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
686 687 /* notify requester of failure */
687 688 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
688 689 ISCSI_STATUS_CMD_FAILED);
689 690 break;
690 691
691 692 case ISCSI_CMD_TYPE_TEXT:
692 693 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
693 694 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
694 695 /*
695 696 * If a TEXT command fails, notify the owner.
696 697 */
697 698 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
698 699 ISCSI_STATUS_CMD_FAILED);
699 700 break;
700 701
701 702 default:
702 703 ASSERT(FALSE);
703 704 break;
704 705 }
705 706 break;
706 707
707 708 /* All other events are invalid for this state */
708 709 default:
709 710 ASSERT(FALSE);
710 711 }
711 712 }
712 713
713 714
714 715 /*
715 716 * iscsi_cmd_state_active -
716 717 *
717 718 */
718 719 static void
719 720 iscsi_cmd_state_active(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
720 721 {
721 722 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
722 723 iscsi_hba_t *ihp;
723 724 iscsi_cmd_t *t_icmdp = NULL;
724 725 iscsi_conn_t *icp = NULL;
725 726
726 727 ASSERT(icmdp != NULL);
727 728 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE);
728 729 ASSERT(isp != NULL);
729 730
730 731 ihp = isp->sess_hba;
731 732 ASSERT(ihp != NULL);
732 733
733 734 icp = icmdp->cmd_conn;
734 735 ASSERT(icp != NULL);
735 736 ASSERT(mutex_owned(&icp->conn_queue_active.mutex));
736 737
737 738 /* switch on event change */
738 739 switch (event) {
739 740 /* -E3: Command was successfully completed */
740 741 case ISCSI_CMD_EVENT_E3:
741 742 /*
742 743 * Remove command from the active list. We need to protect
743 744 * someone from looking up this command ITT until it's
744 745 * freed of the command is moved to a new queue location.
745 746 */
746 747 mutex_enter(&isp->sess_cmdsn_mutex);
747 748 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
748 749
749 750 switch (icmdp->cmd_type) {
750 751 case ISCSI_CMD_TYPE_SCSI:
751 752 iscsi_sess_release_scsi_itt(icmdp);
752 753 mutex_exit(&isp->sess_cmdsn_mutex);
753 754 iscsi_enqueue_completed_cmd(isp, icmdp);
754 755 break;
755 756
756 757 case ISCSI_CMD_TYPE_NOP:
757 758 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
758 759 iscsi_sess_release_itt(isp, icmdp);
759 760 mutex_exit(&isp->sess_cmdsn_mutex);
760 761
761 762 /* free alloc */
762 763 icmdp->cmd_misc_flags |=
763 764 ISCSI_CMD_MISCFLAG_FREE;
764 765
765 766 break;
766 767
767 768 case ISCSI_CMD_TYPE_ABORT:
768 769 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
769 770 iscsi_sess_release_itt(isp, icmdp);
770 771 mutex_exit(&isp->sess_cmdsn_mutex);
771 772
772 773 /*
773 774 * Abort was completed successfully. We should
774 775 * complete the parent scsi command if it still
775 776 * exists as timed out, and the state is not
776 777 * COMPLETED
777 778 */
778 779 t_icmdp = icmdp->cmd_un.abort.icmdp;
779 780 ASSERT(t_icmdp != NULL);
780 781 mutex_enter(&t_icmdp->cmd_mutex);
781 782 t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
782 783 if (t_icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED) {
783 784 iscsi_dequeue_active_cmd(
784 785 t_icmdp->cmd_conn, t_icmdp);
785 786 mutex_enter(
786 787 &icp->conn_queue_idm_aborting.mutex);
787 788 iscsi_enqueue_idm_aborting_cmd(
788 789 t_icmdp->cmd_conn,
|
↓ open down ↓ |
754 lines elided |
↑ open up ↑ |
789 790 t_icmdp);
790 791 mutex_exit(&icp->conn_queue_idm_aborting.mutex);
791 792
792 793 /*
793 794 * Complete abort processing after IDM
794 795 * calls us back. Set the status to use
795 796 * when we complete the command.
796 797 */
797 798 ISCSI_CMD_SET_REASON_STAT(
798 799 t_icmdp, CMD_TIMEOUT, STAT_ABORTED);
799 - idm_task_abort(icp->conn_ic, t_icmdp->cmd_itp,
800 - AT_TASK_MGMT_ABORT);
800 + (void) idm_task_abort(icp->conn_ic,
801 + t_icmdp->cmd_itp, AT_TASK_MGMT_ABORT);
801 802 } else {
802 803 cv_broadcast(&t_icmdp->cmd_completion);
803 804 }
804 805 mutex_exit(&t_icmdp->cmd_mutex);
805 806 icmdp->cmd_un.abort.icmdp = NULL;
806 807
807 808 icmdp->cmd_misc_flags |=
808 809 ISCSI_CMD_MISCFLAG_FREE;
809 810
810 811 break;
811 812 case ISCSI_CMD_TYPE_RESET:
812 813 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
813 814 iscsi_sess_release_itt(isp, icmdp);
814 815 mutex_exit(&isp->sess_cmdsn_mutex);
815 816
816 817 /*
817 818 * Complete the abort/reset command.
818 819 */
819 820 if (icmdp->cmd_un.reset.response !=
820 821 SCSI_TCP_TM_RESP_COMPLETE) {
821 822 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
822 823 ISCSI_STATUS_CMD_FAILED);
823 824 } else {
824 825 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
825 826 ISCSI_STATUS_SUCCESS);
826 827 }
827 828
828 829 break;
829 830
830 831 case ISCSI_CMD_TYPE_LOGOUT:
831 832 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
832 833 iscsi_sess_release_itt(isp, icmdp);
833 834 mutex_exit(&isp->sess_cmdsn_mutex);
834 835
835 836 /*
836 837 * Complete the logout successfully.
837 838 */
838 839 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
839 840 break;
840 841
841 842 case ISCSI_CMD_TYPE_TEXT:
842 843 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
843 844 if (icmdp->cmd_un.text.stage ==
844 845 ISCSI_CMD_TEXT_FINAL_RSP) {
845 846 iscsi_sess_release_itt(isp, icmdp);
846 847 }
847 848 mutex_exit(&isp->sess_cmdsn_mutex);
848 849
849 850 /*
850 851 * Complete the text command successfully.
851 852 */
852 853 ISCSI_CMD_ISSUE_CALLBACK(icmdp, icmdp->cmd_result);
853 854 break;
854 855
855 856 default:
856 857 mutex_exit(&isp->sess_cmdsn_mutex);
857 858 ASSERT(FALSE);
858 859 }
859 860
860 861 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
861 862 break;
862 863
863 864 /* -E10,E4: Command has been requested to abort */
864 865 case ISCSI_CMD_EVENT_E10:
865 866 /* FALLTHRU */
866 867 case ISCSI_CMD_EVENT_E4:
867 868
868 869 /* E4 is only for resets and aborts */
869 870 ASSERT((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) ||
870 871 (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET));
871 872 /* FALLTHRU */
872 873
873 874 /* -E6: Command has timed out */
874 875 case ISCSI_CMD_EVENT_E6:
875 876
876 877 switch (icmdp->cmd_type) {
877 878 case ISCSI_CMD_TYPE_SCSI:
878 879 icmdp->cmd_state = ISCSI_CMD_STATE_ABORTING;
879 880 iscsi_handle_abort(icmdp);
880 881 break;
881 882
882 883 case ISCSI_CMD_TYPE_NOP:
883 884 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
884 885
885 886 mutex_enter(&isp->sess_cmdsn_mutex);
886 887 iscsi_sess_release_itt(isp, icmdp);
887 888 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
888 889 mutex_exit(&isp->sess_cmdsn_mutex);
889 890
890 891 icmdp->cmd_misc_flags |=
891 892 ISCSI_CMD_MISCFLAG_FREE;
892 893
893 894 break;
894 895
895 896 case ISCSI_CMD_TYPE_ABORT:
896 897 icmdp->cmd_state =
897 898 ISCSI_CMD_STATE_FREE;
898 899
899 900 mutex_enter(&isp->sess_cmdsn_mutex);
900 901 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
901 902 iscsi_sess_release_itt(isp, icmdp);
902 903 mutex_exit(&isp->sess_cmdsn_mutex);
903 904
904 905 /*
905 906 * If this is an E4 then we may need to deal with
906 907 * the abort's associated SCSI command. If this
907 908 * is an E10 then IDM is already cleaning up the
908 909 * SCSI command and all we need to do is break the
909 910 * linkage between them and free the abort command.
910 911 */
911 912 t_icmdp = icmdp->cmd_un.abort.icmdp;
912 913 ASSERT(t_icmdp != NULL);
913 914 if (event != ISCSI_CMD_EVENT_E10) {
914 915
915 916 mutex_enter(&t_icmdp->cmd_mutex);
916 917 t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
917 918 /*
918 919 * If abort command is aborted then we should
919 920 * not act on the parent scsi command. If the
920 921 * abort command timed out then we need to
921 922 * complete the parent command if it still
922 923 * exists with a timeout failure.
923 924 */
924 925 if ((event == ISCSI_CMD_EVENT_E6) &&
925 926 (t_icmdp->cmd_state !=
926 927 ISCSI_CMD_STATE_IDM_ABORTING) &&
927 928 (t_icmdp->cmd_state !=
928 929 ISCSI_CMD_STATE_COMPLETED)) {
929 930
930 931 iscsi_dequeue_active_cmd(
931 932 t_icmdp->cmd_conn, t_icmdp);
932 933 mutex_enter(&icp->
933 934 conn_queue_idm_aborting.mutex);
934 935 iscsi_enqueue_idm_aborting_cmd(
|
↓ open down ↓ |
124 lines elided |
↑ open up ↑ |
935 936 t_icmdp->cmd_conn, t_icmdp);
936 937 mutex_exit(&icp->
937 938 conn_queue_idm_aborting.mutex);
938 939 /*
939 940 * Complete abort processing after IDM
940 941 * calls us back. Set the status to use
941 942 * when we complete the command.
942 943 */
943 944 ISCSI_CMD_SET_REASON_STAT(t_icmdp,
944 945 CMD_TIMEOUT, STAT_TIMEOUT);
945 - idm_task_abort(icp->conn_ic,
946 + (void) idm_task_abort(icp->conn_ic,
946 947 t_icmdp->cmd_itp,
947 948 AT_TASK_MGMT_ABORT);
948 949 } else {
949 950 cv_broadcast(&t_icmdp->cmd_completion);
950 951 }
951 952 mutex_exit(&t_icmdp->cmd_mutex);
952 953 } else {
953 954 t_icmdp->cmd_un.scsi.abort_icmdp = NULL;
954 955 }
955 956 icmdp->cmd_un.abort.icmdp = NULL;
956 957 icmdp->cmd_misc_flags |=
957 958 ISCSI_CMD_MISCFLAG_FREE;
958 959 break;
959 960
960 961 case ISCSI_CMD_TYPE_RESET:
961 962 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
962 963
963 964 mutex_enter(&isp->sess_cmdsn_mutex);
964 965 iscsi_sess_release_itt(isp, icmdp);
965 966 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
966 967 mutex_exit(&isp->sess_cmdsn_mutex);
967 968
968 969 /*
969 970 * If we are failing a RESET we need
970 971 * to notify the tran_reset caller.
971 972 * It will free the memory associated
972 973 * with the cmd and notify caller.
973 974 */
974 975
975 976 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
976 977 ISCSI_STATUS_CMD_FAILED);
977 978 break;
978 979
979 980 case ISCSI_CMD_TYPE_LOGOUT:
980 981 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
981 982
982 983 mutex_enter(&isp->sess_cmdsn_mutex);
983 984 iscsi_sess_release_itt(isp, icmdp);
984 985 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
985 986 mutex_exit(&isp->sess_cmdsn_mutex);
986 987
987 988 /*
988 989 * Notify caller of failure.
989 990 */
990 991 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
991 992 ISCSI_STATUS_CMD_FAILED);
992 993 break;
993 994
994 995 case ISCSI_CMD_TYPE_TEXT:
995 996 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
996 997 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
997 998 mutex_enter(&isp->sess_cmdsn_mutex);
998 999 iscsi_sess_release_itt(isp, icmdp);
999 1000 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1000 1001 mutex_exit(&isp->sess_cmdsn_mutex);
1001 1002
1002 1003 /*
1003 1004 * If a TEXT command fails, notify caller so
1004 1005 * it can free assocated command
1005 1006 */
1006 1007 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1007 1008 ISCSI_STATUS_CMD_FAILED);
1008 1009 break;
1009 1010
1010 1011 default:
1011 1012 ASSERT(FALSE);
1012 1013 }
1013 1014
1014 1015 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
1015 1016 break;
1016 1017
1017 1018 /* -E7: Connection has encountered a problem */
1018 1019 case ISCSI_CMD_EVENT_E7:
1019 1020 mutex_enter(&isp->sess_cmdsn_mutex);
|
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
1020 1021 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1021 1022
1022 1023 switch (icmdp->cmd_type) {
1023 1024 case ISCSI_CMD_TYPE_SCSI:
1024 1025 mutex_exit(&isp->sess_cmdsn_mutex);
1025 1026 mutex_enter(&icp->conn_queue_idm_aborting.mutex);
1026 1027 iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
1027 1028 mutex_exit(&icp->conn_queue_idm_aborting.mutex);
1028 1029 ISCSI_CMD_SET_REASON_STAT(icmdp,
1029 1030 CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
1030 - idm_task_abort(icp->conn_ic, icmdp->cmd_itp,
1031 + (void) idm_task_abort(icp->conn_ic, icmdp->cmd_itp,
1031 1032 AT_TASK_MGMT_ABORT);
1032 1033 break;
1033 1034
1034 1035 case ISCSI_CMD_TYPE_NOP:
1035 1036 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1036 1037 iscsi_sess_release_itt(isp, icmdp);
1037 1038 mutex_exit(&isp->sess_cmdsn_mutex);
1038 1039
1039 1040 icmdp->cmd_misc_flags |=
1040 1041 ISCSI_CMD_MISCFLAG_FREE;
1041 1042 break;
1042 1043
1043 1044 case ISCSI_CMD_TYPE_ABORT:
1044 1045 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1045 1046 iscsi_sess_release_itt(isp, icmdp);
1046 1047 mutex_exit(&isp->sess_cmdsn_mutex);
1047 1048
1048 1049 mutex_enter(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
1049 1050 icmdp->cmd_un.abort.icmdp->
1050 1051 cmd_un.scsi.abort_icmdp = NULL;
1051 1052 cv_broadcast(&icmdp->cmd_un.abort.icmdp->
1052 1053 cmd_completion);
1053 1054 mutex_exit(&icmdp->cmd_un.abort.icmdp->cmd_mutex);
1054 1055 /*
1055 1056 * Nullify the abort command's pointer to its
1056 1057 * parent command. It does not have to complete its
1057 1058 * parent command because the parent command will
1058 1059 * also get an E7.
1059 1060 */
1060 1061 icmdp->cmd_un.abort.icmdp = NULL;
1061 1062
1062 1063 icmdp->cmd_misc_flags |=
1063 1064 ISCSI_CMD_MISCFLAG_FREE;
1064 1065 break;
1065 1066
1066 1067 case ISCSI_CMD_TYPE_RESET:
1067 1068 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1068 1069 iscsi_sess_release_itt(isp, icmdp);
1069 1070 mutex_exit(&isp->sess_cmdsn_mutex);
1070 1071 /*
1071 1072 * If we are failing a ABORT we need
1072 1073 * to notify the tran_abort caller.
1073 1074 * It will free the memory associated
1074 1075 * with the cmd and notify caller.
1075 1076 */
1076 1077
1077 1078 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1078 1079 ISCSI_STATUS_CMD_FAILED);
1079 1080 break;
1080 1081
1081 1082 case ISCSI_CMD_TYPE_LOGOUT:
1082 1083 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1083 1084 /*
1084 1085 * A connection problem and we attempted to
1085 1086 * logout? I guess we can just free the
1086 1087 * request. Someone has already pushed the
1087 1088 * connection state.
1088 1089 */
1089 1090 iscsi_sess_release_itt(isp, icmdp);
1090 1091 mutex_exit(&isp->sess_cmdsn_mutex);
1091 1092
1092 1093 ISCSI_CMD_ISSUE_CALLBACK(icmdp, ISCSI_STATUS_SUCCESS);
1093 1094 break;
1094 1095
1095 1096 case ISCSI_CMD_TYPE_TEXT:
1096 1097 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1097 1098 icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1098 1099 iscsi_sess_release_itt(isp, icmdp);
1099 1100 mutex_exit(&isp->sess_cmdsn_mutex);
1100 1101
1101 1102 /*
1102 1103 * If a TEXT command fails, notify caller so
1103 1104 * it can free assocated command
1104 1105 */
1105 1106 ISCSI_CMD_ISSUE_CALLBACK(icmdp,
1106 1107 ISCSI_STATUS_CMD_FAILED);
1107 1108 break;
1108 1109
1109 1110 default:
1110 1111 mutex_exit(&isp->sess_cmdsn_mutex);
1111 1112 ASSERT(FALSE);
1112 1113 break;
1113 1114 }
1114 1115
1115 1116 ASSERT(!mutex_owned(&isp->sess_cmdsn_mutex));
1116 1117 break;
1117 1118
1118 1119 /* -E9: IDM is no longer processing this command */
1119 1120 case ISCSI_CMD_EVENT_E9:
1120 1121 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1121 1122
1122 1123 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
1123 1124 iscsi_sess_release_scsi_itt(icmdp);
1124 1125
1125 1126 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
1126 1127 icmdp->cmd_un.scsi.pkt_stat);
1127 1128 iscsi_enqueue_completed_cmd(isp, icmdp);
1128 1129 break;
1129 1130
1130 1131 /* All other events are invalid for this state */
1131 1132 default:
1132 1133 ASSERT(FALSE);
1133 1134 }
1134 1135 }
1135 1136
1136 1137
1137 1138 /*
1138 1139 * iscsi_cmd_state_aborting -
1139 1140 *
1140 1141 */
1141 1142 static void
1142 1143 iscsi_cmd_state_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event, void *arg)
1143 1144 {
1144 1145 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
1145 1146 iscsi_cmd_t *a_icmdp;
1146 1147
1147 1148 ASSERT(icmdp != NULL);
1148 1149 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
1149 1150 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_ABORTING);
1150 1151 ASSERT(isp != NULL);
1151 1152 ASSERT(mutex_owned(&icmdp->cmd_conn->conn_queue_active.mutex));
1152 1153
1153 1154 /* switch on event change */
1154 1155 switch (event) {
1155 1156 /* -E3: Command was successfully completed */
1156 1157 case ISCSI_CMD_EVENT_E3:
1157 1158 /*
1158 1159 * Remove command from the aborting list
1159 1160 */
1160 1161 mutex_enter(&isp->sess_cmdsn_mutex);
1161 1162 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1162 1163 iscsi_sess_release_scsi_itt(icmdp);
1163 1164 mutex_exit(&isp->sess_cmdsn_mutex);
1164 1165
1165 1166 iscsi_enqueue_completed_cmd(isp, icmdp);
1166 1167 break;
1167 1168
1168 1169 /* -E4: Command has been requested to abort */
1169 1170 case ISCSI_CMD_EVENT_E4:
1170 1171 /*
1171 1172 * An upper level driver might attempt to
1172 1173 * abort a command that we are already
1173 1174 * aborting due to a nop. Since we are
1174 1175 * already in the process of aborting
1175 1176 * ignore the request.
1176 1177 */
1177 1178 break;
1178 1179
1179 1180 /* -E6: Command has timed out */
1180 1181 case ISCSI_CMD_EVENT_E6:
1181 1182 ASSERT(FALSE);
1182 1183 /*
1183 1184 * Timeouts should not occur on command in abort queue
1184 1185 * they are already be processed due to a timeout.
1185 1186 */
1186 1187 break;
1187 1188
1188 1189 /* -E7: Connection has encountered a problem */
1189 1190 case ISCSI_CMD_EVENT_E7:
1190 1191 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1191 1192 mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
1192 1193 iscsi_enqueue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
1193 1194 mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
1194 1195
1195 1196 /*
1196 1197 * Since we are in "aborting" state there is another command
1197 1198 * representing the abort of this command. This command
1198 1199 * will cleanup at some indeterminate time after the call
1199 1200 * to idm_task_abort so we can't leave the abort request
1200 1201 * active. An E10 event to the abort command will cause
|
↓ open down ↓ |
160 lines elided |
↑ open up ↑ |
1201 1202 * it to complete immediately.
1202 1203 */
1203 1204 if ((a_icmdp = icmdp->cmd_un.scsi.abort_icmdp) != NULL) {
1204 1205 iscsi_cmd_state_machine(a_icmdp,
1205 1206 ISCSI_CMD_EVENT_E10, arg);
1206 1207 }
1207 1208
1208 1209 ISCSI_CMD_SET_REASON_STAT(icmdp,
1209 1210 CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
1210 1211
1211 - idm_task_abort(icmdp->cmd_conn->conn_ic, icmdp->cmd_itp,
1212 + (void) idm_task_abort(icmdp->cmd_conn->conn_ic, icmdp->cmd_itp,
1212 1213 AT_TASK_MGMT_ABORT);
1213 1214 break;
1214 1215
1215 1216 /* -E9: IDM is no longer processing this command */
1216 1217 case ISCSI_CMD_EVENT_E9:
1217 1218 iscsi_dequeue_active_cmd(icmdp->cmd_conn, icmdp);
1218 1219
1219 1220 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
1220 1221 iscsi_sess_release_scsi_itt(icmdp);
1221 1222
1222 1223 ISCSI_CMD_SET_REASON_STAT(icmdp, CMD_TRAN_ERR,
1223 1224 icmdp->cmd_un.scsi.pkt_stat);
1224 1225 iscsi_enqueue_completed_cmd(isp, icmdp);
1225 1226 break;
1226 1227
1227 1228 /* All other events are invalid for this state */
1228 1229 default:
1229 1230 ASSERT(FALSE);
1230 1231 }
1231 1232 }
1232 1233
1233 1234 static void
1234 1235 iscsi_cmd_state_idm_aborting(iscsi_cmd_t *icmdp, iscsi_cmd_event_t event,
1235 1236 void *arg)
1236 1237 {
1237 1238 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
1238 1239
1239 1240 ASSERT(icmdp != NULL);
1240 1241 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
1241 1242 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING);
1242 1243 ASSERT(isp != NULL);
1243 1244
1244 1245 /* switch on event change */
1245 1246 switch (event) {
1246 1247 /* -E3: Command was successfully completed */
1247 1248 case ISCSI_CMD_EVENT_E3:
1248 1249 /*
1249 1250 * iscsi_rx_process_cmd_rsp() and iscsi_rx_process_data_rsp()
1250 1251 * are supposed to confirm the cmd state is appropriate before
1251 1252 * generating an E3 event. E3 is not allowed in this state.
1252 1253 */
1253 1254 ASSERT(0);
1254 1255 break;
1255 1256
1256 1257 /* -E4: Command has been requested to abort */
1257 1258 case ISCSI_CMD_EVENT_E4:
1258 1259 /*
1259 1260 * An upper level driver might attempt to
1260 1261 * abort a command that we are already
1261 1262 * aborting due to a nop. Since we are
1262 1263 * already in the process of aborting
1263 1264 * ignore the request.
1264 1265 */
1265 1266 break;
1266 1267
1267 1268 /* -E6: Command has timed out */
1268 1269 case ISCSI_CMD_EVENT_E6:
1269 1270 ASSERT(FALSE);
1270 1271 /*
1271 1272 * Timeouts should not occur on aborting commands
1272 1273 */
1273 1274 break;
1274 1275
1275 1276 /* -E7: Connection has encountered a problem */
1276 1277 case ISCSI_CMD_EVENT_E7:
1277 1278 /*
1278 1279 * We have already requested IDM to stop processing this
1279 1280 * command so just update the pkt_statistics.
1280 1281 */
1281 1282 ISCSI_CMD_SET_REASON_STAT(icmdp,
1282 1283 CMD_TRAN_ERR, icmdp->cmd_un.scsi.pkt_stat);
1283 1284 break;
1284 1285
1285 1286 /* -E9: IDM is no longer processing this command */
1286 1287 case ISCSI_CMD_EVENT_E9:
1287 1288 mutex_enter(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
1288 1289 iscsi_dequeue_idm_aborting_cmd(icmdp->cmd_conn, icmdp);
1289 1290 mutex_exit(&icmdp->cmd_conn->conn_queue_idm_aborting.mutex);
1290 1291
1291 1292 /* This is always an error so make sure an error has been set */
1292 1293 ASSERT(icmdp->cmd_un.scsi.pkt->pkt_reason != CMD_CMPLT);
1293 1294 iscsi_task_cleanup(ISCSI_OP_SCSI_RSP, icmdp);
1294 1295 iscsi_sess_release_scsi_itt(icmdp);
1295 1296
1296 1297 /*
1297 1298 * Whoever called idm_task_abort should have set the completion
1298 1299 * status beforehand.
1299 1300 */
1300 1301 iscsi_enqueue_completed_cmd(isp, icmdp);
1301 1302 cv_broadcast(&icmdp->cmd_completion);
1302 1303 break;
1303 1304
1304 1305 /* All other events are invalid for this state */
1305 1306 default:
1306 1307 ASSERT(FALSE);
1307 1308 }
1308 1309 }
1309 1310
1310 1311
1311 1312 /*
1312 1313 * iscsi_cmd_state_completed -
1313 1314 *
1314 1315 */
1315 1316 static void
1316 1317 iscsi_cmd_state_completed(iscsi_cmd_t *icmdp,
1317 1318 iscsi_cmd_event_t event, void *arg)
1318 1319 {
1319 1320 iscsi_sess_t *isp = (iscsi_sess_t *)arg;
1320 1321
1321 1322 ASSERT(icmdp != NULL);
1322 1323 ASSERT(icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI);
1323 1324 ASSERT(icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED);
1324 1325 ASSERT(isp != NULL);
1325 1326
1326 1327 /* switch on event change */
1327 1328 switch (event) {
1328 1329 /* -E8: */
1329 1330 case ISCSI_CMD_EVENT_E8:
1330 1331 icmdp->cmd_state = ISCSI_CMD_STATE_FREE;
1331 1332
1332 1333 /* the caller has already remove cmd from queue */
1333 1334
1334 1335 icmdp->cmd_next = NULL;
1335 1336 icmdp->cmd_prev = NULL;
1336 1337 iscsi_iodone(isp, icmdp);
1337 1338 break;
1338 1339 /* All other events are invalid for this state */
1339 1340 default:
1340 1341 ASSERT(FALSE);
1341 1342 }
1342 1343 }
1343 1344
1344 1345
1345 1346 /*
1346 1347 * iscsi_cmd_state_str -
1347 1348 *
1348 1349 */
1349 1350 static char *
1350 1351 iscsi_cmd_state_str(iscsi_cmd_state_t state)
1351 1352 {
1352 1353 switch (state) {
1353 1354 case ISCSI_CMD_STATE_FREE:
1354 1355 return ("free");
1355 1356 case ISCSI_CMD_STATE_PENDING:
1356 1357 return ("pending");
1357 1358 case ISCSI_CMD_STATE_ACTIVE:
1358 1359 return ("active");
1359 1360 case ISCSI_CMD_STATE_ABORTING:
1360 1361 return ("aborting");
1361 1362 case ISCSI_CMD_STATE_IDM_ABORTING:
1362 1363 return ("idm-aborting");
1363 1364 case ISCSI_CMD_STATE_COMPLETED:
1364 1365 return ("completed");
1365 1366 default:
1366 1367 return ("unknown");
1367 1368 }
1368 1369 }
1369 1370
1370 1371
1371 1372 /*
1372 1373 * iscsi_cmd_event_str -
1373 1374 *
1374 1375 */
1375 1376 static char *
1376 1377 iscsi_cmd_event_str(iscsi_cmd_event_t event)
1377 1378 {
1378 1379 switch (event) {
1379 1380 case ISCSI_CMD_EVENT_E1:
1380 1381 return ("E1");
1381 1382 case ISCSI_CMD_EVENT_E2:
1382 1383 return ("E2");
1383 1384 case ISCSI_CMD_EVENT_E3:
1384 1385 return ("E3");
1385 1386 case ISCSI_CMD_EVENT_E4:
1386 1387 return ("E4");
1387 1388 case ISCSI_CMD_EVENT_E6:
1388 1389 return ("E6");
1389 1390 case ISCSI_CMD_EVENT_E7:
1390 1391 return ("E7");
1391 1392 case ISCSI_CMD_EVENT_E8:
1392 1393 return ("E8");
1393 1394 case ISCSI_CMD_EVENT_E9:
1394 1395 return ("E9");
1395 1396 case ISCSI_CMD_EVENT_E10:
1396 1397 return ("E10");
1397 1398 default:
1398 1399 return ("unknown");
1399 1400 }
1400 1401 }
1401 1402
1402 1403
1403 1404 /*
1404 1405 * iscsi_cmd_event_str -
1405 1406 *
1406 1407 */
1407 1408 static char *
1408 1409 iscsi_cmd_type_str(iscsi_cmd_type_t type)
1409 1410 {
1410 1411 switch (type) {
1411 1412 case ISCSI_CMD_TYPE_SCSI:
1412 1413 return ("scsi");
1413 1414 case ISCSI_CMD_TYPE_NOP:
1414 1415 return ("nop");
1415 1416 case ISCSI_CMD_TYPE_ABORT:
1416 1417 return ("abort");
1417 1418 case ISCSI_CMD_TYPE_RESET:
1418 1419 return ("reset");
1419 1420 case ISCSI_CMD_TYPE_LOGOUT:
1420 1421 return ("logout");
1421 1422 default:
1422 1423 return ("unknown");
1423 1424 }
1424 1425 }
|
↓ open down ↓ |
203 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX