diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 623 |
1 files changed, 347 insertions, 276 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index e72b4ad47d35..716cc344c5df 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -38,15 +38,30 @@ | |||
38 | #include <scsi/scsi_transport_iscsi.h> | 38 | #include <scsi/scsi_transport_iscsi.h> |
39 | #include <scsi/libiscsi.h> | 39 | #include <scsi/libiscsi.h> |
40 | 40 | ||
41 | static int iscsi_dbg_lib; | 41 | static int iscsi_dbg_lib_conn; |
42 | module_param_named(debug_libiscsi, iscsi_dbg_lib, int, S_IRUGO | S_IWUSR); | 42 | module_param_named(debug_libiscsi_conn, iscsi_dbg_lib_conn, int, |
43 | MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. " | 43 | S_IRUGO | S_IWUSR); |
44 | "Set to 1 to turn on, and zero to turn off. Default " | 44 | MODULE_PARM_DESC(debug_libiscsi_conn, |
45 | "is off."); | 45 | "Turn on debugging for connections in libiscsi module. " |
46 | "Set to 1 to turn on, and zero to turn off. Default is off."); | ||
47 | |||
48 | static int iscsi_dbg_lib_session; | ||
49 | module_param_named(debug_libiscsi_session, iscsi_dbg_lib_session, int, | ||
50 | S_IRUGO | S_IWUSR); | ||
51 | MODULE_PARM_DESC(debug_libiscsi_session, | ||
52 | "Turn on debugging for sessions in libiscsi module. " | ||
53 | "Set to 1 to turn on, and zero to turn off. Default is off."); | ||
54 | |||
55 | static int iscsi_dbg_lib_eh; | ||
56 | module_param_named(debug_libiscsi_eh, iscsi_dbg_lib_eh, int, | ||
57 | S_IRUGO | S_IWUSR); | ||
58 | MODULE_PARM_DESC(debug_libiscsi_eh, | ||
59 | "Turn on debugging for error handling in libiscsi module. " | ||
60 | "Set to 1 to turn on, and zero to turn off. Default is off."); | ||
46 | 61 | ||
47 | #define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \ | 62 | #define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \ |
48 | do { \ | 63 | do { \ |
49 | if (iscsi_dbg_lib) \ | 64 | if (iscsi_dbg_lib_conn) \ |
50 | iscsi_conn_printk(KERN_INFO, _conn, \ | 65 | iscsi_conn_printk(KERN_INFO, _conn, \ |
51 | "%s " dbg_fmt, \ | 66 | "%s " dbg_fmt, \ |
52 | __func__, ##arg); \ | 67 | __func__, ##arg); \ |
@@ -54,7 +69,15 @@ MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. " | |||
54 | 69 | ||
55 | #define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \ | 70 | #define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \ |
56 | do { \ | 71 | do { \ |
57 | if (iscsi_dbg_lib) \ | 72 | if (iscsi_dbg_lib_session) \ |
73 | iscsi_session_printk(KERN_INFO, _session, \ | ||
74 | "%s " dbg_fmt, \ | ||
75 | __func__, ##arg); \ | ||
76 | } while (0); | ||
77 | |||
78 | #define ISCSI_DBG_EH(_session, dbg_fmt, arg...) \ | ||
79 | do { \ | ||
80 | if (iscsi_dbg_lib_eh) \ | ||
58 | iscsi_session_printk(KERN_INFO, _session, \ | 81 | iscsi_session_printk(KERN_INFO, _session, \ |
59 | "%s " dbg_fmt, \ | 82 | "%s " dbg_fmt, \ |
60 | __func__, ##arg); \ | 83 | __func__, ##arg); \ |
@@ -81,7 +104,8 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn) | |||
81 | struct Scsi_Host *shost = conn->session->host; | 104 | struct Scsi_Host *shost = conn->session->host; |
82 | struct iscsi_host *ihost = shost_priv(shost); | 105 | struct iscsi_host *ihost = shost_priv(shost); |
83 | 106 | ||
84 | queue_work(ihost->workq, &conn->xmitwork); | 107 | if (ihost->workq) |
108 | queue_work(ihost->workq, &conn->xmitwork); | ||
85 | } | 109 | } |
86 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); | 110 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); |
87 | 111 | ||
@@ -109,11 +133,9 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
109 | * if the window closed with IO queued, then kick the | 133 | * if the window closed with IO queued, then kick the |
110 | * xmit thread | 134 | * xmit thread |
111 | */ | 135 | */ |
112 | if (!list_empty(&session->leadconn->xmitqueue) || | 136 | if (!list_empty(&session->leadconn->cmdqueue) || |
113 | !list_empty(&session->leadconn->mgmtqueue)) { | 137 | !list_empty(&session->leadconn->mgmtqueue)) |
114 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 138 | iscsi_conn_queue_work(session->leadconn); |
115 | iscsi_conn_queue_work(session->leadconn); | ||
116 | } | ||
117 | } | 139 | } |
118 | } | 140 | } |
119 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 141 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
@@ -257,9 +279,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
257 | itt_t itt; | 279 | itt_t itt; |
258 | int rc; | 280 | int rc; |
259 | 281 | ||
260 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); | 282 | if (conn->session->tt->alloc_pdu) { |
261 | if (rc) | 283 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); |
262 | return rc; | 284 | if (rc) |
285 | return rc; | ||
286 | } | ||
263 | hdr = (struct iscsi_cmd *) task->hdr; | 287 | hdr = (struct iscsi_cmd *) task->hdr; |
264 | itt = hdr->itt; | 288 | itt = hdr->itt; |
265 | memset(hdr, 0, sizeof(*hdr)); | 289 | memset(hdr, 0, sizeof(*hdr)); |
@@ -364,7 +388,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
364 | return -EIO; | 388 | return -EIO; |
365 | 389 | ||
366 | task->state = ISCSI_TASK_RUNNING; | 390 | task->state = ISCSI_TASK_RUNNING; |
367 | list_move_tail(&task->running, &conn->run_list); | ||
368 | 391 | ||
369 | conn->scsicmd_pdus_cnt++; | 392 | conn->scsicmd_pdus_cnt++; |
370 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " | 393 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " |
@@ -380,26 +403,25 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
380 | } | 403 | } |
381 | 404 | ||
382 | /** | 405 | /** |
383 | * iscsi_complete_command - finish a task | 406 | * iscsi_free_task - free a task |
384 | * @task: iscsi cmd task | 407 | * @task: iscsi cmd task |
385 | * | 408 | * |
386 | * Must be called with session lock. | 409 | * Must be called with session lock. |
387 | * This function returns the scsi command to scsi-ml or cleans | 410 | * This function returns the scsi command to scsi-ml or cleans |
388 | * up mgmt tasks then returns the task to the pool. | 411 | * up mgmt tasks then returns the task to the pool. |
389 | */ | 412 | */ |
390 | static void iscsi_complete_command(struct iscsi_task *task) | 413 | static void iscsi_free_task(struct iscsi_task *task) |
391 | { | 414 | { |
392 | struct iscsi_conn *conn = task->conn; | 415 | struct iscsi_conn *conn = task->conn; |
393 | struct iscsi_session *session = conn->session; | 416 | struct iscsi_session *session = conn->session; |
394 | struct scsi_cmnd *sc = task->sc; | 417 | struct scsi_cmnd *sc = task->sc; |
395 | 418 | ||
419 | ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n", | ||
420 | task->itt, task->state, task->sc); | ||
421 | |||
396 | session->tt->cleanup_task(task); | 422 | session->tt->cleanup_task(task); |
397 | list_del_init(&task->running); | 423 | task->state = ISCSI_TASK_FREE; |
398 | task->state = ISCSI_TASK_COMPLETED; | ||
399 | task->sc = NULL; | 424 | task->sc = NULL; |
400 | |||
401 | if (conn->task == task) | ||
402 | conn->task = NULL; | ||
403 | /* | 425 | /* |
404 | * login task is preallocated so do not free | 426 | * login task is preallocated so do not free |
405 | */ | 427 | */ |
@@ -408,9 +430,6 @@ static void iscsi_complete_command(struct iscsi_task *task) | |||
408 | 430 | ||
409 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); | 431 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); |
410 | 432 | ||
411 | if (conn->ping_task == task) | ||
412 | conn->ping_task = NULL; | ||
413 | |||
414 | if (sc) { | 433 | if (sc) { |
415 | task->sc = NULL; | 434 | task->sc = NULL; |
416 | /* SCSI eh reuses commands to verify us */ | 435 | /* SCSI eh reuses commands to verify us */ |
@@ -433,7 +452,7 @@ EXPORT_SYMBOL_GPL(__iscsi_get_task); | |||
433 | static void __iscsi_put_task(struct iscsi_task *task) | 452 | static void __iscsi_put_task(struct iscsi_task *task) |
434 | { | 453 | { |
435 | if (atomic_dec_and_test(&task->refcount)) | 454 | if (atomic_dec_and_test(&task->refcount)) |
436 | iscsi_complete_command(task); | 455 | iscsi_free_task(task); |
437 | } | 456 | } |
438 | 457 | ||
439 | void iscsi_put_task(struct iscsi_task *task) | 458 | void iscsi_put_task(struct iscsi_task *task) |
@@ -446,26 +465,74 @@ void iscsi_put_task(struct iscsi_task *task) | |||
446 | } | 465 | } |
447 | EXPORT_SYMBOL_GPL(iscsi_put_task); | 466 | EXPORT_SYMBOL_GPL(iscsi_put_task); |
448 | 467 | ||
468 | /** | ||
469 | * iscsi_complete_task - finish a task | ||
470 | * @task: iscsi cmd task | ||
471 | * @state: state to complete task with | ||
472 | * | ||
473 | * Must be called with session lock. | ||
474 | */ | ||
475 | static void iscsi_complete_task(struct iscsi_task *task, int state) | ||
476 | { | ||
477 | struct iscsi_conn *conn = task->conn; | ||
478 | |||
479 | ISCSI_DBG_SESSION(conn->session, | ||
480 | "complete task itt 0x%x state %d sc %p\n", | ||
481 | task->itt, task->state, task->sc); | ||
482 | if (task->state == ISCSI_TASK_COMPLETED || | ||
483 | task->state == ISCSI_TASK_ABRT_TMF || | ||
484 | task->state == ISCSI_TASK_ABRT_SESS_RECOV) | ||
485 | return; | ||
486 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); | ||
487 | task->state = state; | ||
488 | |||
489 | if (!list_empty(&task->running)) | ||
490 | list_del_init(&task->running); | ||
491 | |||
492 | if (conn->task == task) | ||
493 | conn->task = NULL; | ||
494 | |||
495 | if (conn->ping_task == task) | ||
496 | conn->ping_task = NULL; | ||
497 | |||
498 | /* release get from queueing */ | ||
499 | __iscsi_put_task(task); | ||
500 | } | ||
501 | |||
449 | /* | 502 | /* |
450 | * session lock must be held | 503 | * session lock must be held and if not called for a task that is |
504 | * still pending or from the xmit thread, then xmit thread must | ||
505 | * be suspended. | ||
451 | */ | 506 | */ |
452 | static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | 507 | static void fail_scsi_task(struct iscsi_task *task, int err) |
453 | int err) | ||
454 | { | 508 | { |
509 | struct iscsi_conn *conn = task->conn; | ||
455 | struct scsi_cmnd *sc; | 510 | struct scsi_cmnd *sc; |
511 | int state; | ||
456 | 512 | ||
513 | /* | ||
514 | * if a command completes and we get a successful tmf response | ||
515 | * we will hit this because the scsi eh abort code does not take | ||
516 | * a ref to the task. | ||
517 | */ | ||
457 | sc = task->sc; | 518 | sc = task->sc; |
458 | if (!sc) | 519 | if (!sc) |
459 | return; | 520 | return; |
460 | 521 | ||
461 | if (task->state == ISCSI_TASK_PENDING) | 522 | if (task->state == ISCSI_TASK_PENDING) { |
462 | /* | 523 | /* |
463 | * cmd never made it to the xmit thread, so we should not count | 524 | * cmd never made it to the xmit thread, so we should not count |
464 | * the cmd in the sequencing | 525 | * the cmd in the sequencing |
465 | */ | 526 | */ |
466 | conn->session->queued_cmdsn--; | 527 | conn->session->queued_cmdsn--; |
528 | /* it was never sent so just complete like normal */ | ||
529 | state = ISCSI_TASK_COMPLETED; | ||
530 | } else if (err == DID_TRANSPORT_DISRUPTED) | ||
531 | state = ISCSI_TASK_ABRT_SESS_RECOV; | ||
532 | else | ||
533 | state = ISCSI_TASK_ABRT_TMF; | ||
467 | 534 | ||
468 | sc->result = err; | 535 | sc->result = err << 16; |
469 | if (!scsi_bidi_cmnd(sc)) | 536 | if (!scsi_bidi_cmnd(sc)) |
470 | scsi_set_resid(sc, scsi_bufflen(sc)); | 537 | scsi_set_resid(sc, scsi_bufflen(sc)); |
471 | else { | 538 | else { |
@@ -473,10 +540,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | |||
473 | scsi_in(sc)->resid = scsi_in(sc)->length; | 540 | scsi_in(sc)->resid = scsi_in(sc)->length; |
474 | } | 541 | } |
475 | 542 | ||
476 | if (conn->task == task) | 543 | iscsi_complete_task(task, state); |
477 | conn->task = NULL; | ||
478 | /* release ref from queuecommand */ | ||
479 | __iscsi_put_task(task); | ||
480 | } | 544 | } |
481 | 545 | ||
482 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | 546 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
@@ -516,7 +580,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
516 | session->state = ISCSI_STATE_LOGGING_OUT; | 580 | session->state = ISCSI_STATE_LOGGING_OUT; |
517 | 581 | ||
518 | task->state = ISCSI_TASK_RUNNING; | 582 | task->state = ISCSI_TASK_RUNNING; |
519 | list_move_tail(&task->running, &conn->mgmt_run_list); | ||
520 | ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " | 583 | ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " |
521 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, | 584 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, |
522 | hdr->itt, task->data_count); | 585 | hdr->itt, task->data_count); |
@@ -528,6 +591,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
528 | char *data, uint32_t data_size) | 591 | char *data, uint32_t data_size) |
529 | { | 592 | { |
530 | struct iscsi_session *session = conn->session; | 593 | struct iscsi_session *session = conn->session; |
594 | struct iscsi_host *ihost = shost_priv(session->host); | ||
531 | struct iscsi_task *task; | 595 | struct iscsi_task *task; |
532 | itt_t itt; | 596 | itt_t itt; |
533 | 597 | ||
@@ -544,6 +608,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
544 | */ | 608 | */ |
545 | task = conn->login_task; | 609 | task = conn->login_task; |
546 | else { | 610 | else { |
611 | if (session->state != ISCSI_STATE_LOGGED_IN) | ||
612 | return NULL; | ||
613 | |||
547 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); | 614 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); |
548 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); | 615 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
549 | 616 | ||
@@ -559,6 +626,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
559 | atomic_set(&task->refcount, 1); | 626 | atomic_set(&task->refcount, 1); |
560 | task->conn = conn; | 627 | task->conn = conn; |
561 | task->sc = NULL; | 628 | task->sc = NULL; |
629 | INIT_LIST_HEAD(&task->running); | ||
630 | task->state = ISCSI_TASK_PENDING; | ||
562 | 631 | ||
563 | if (data_size) { | 632 | if (data_size) { |
564 | memcpy(task->data, data, data_size); | 633 | memcpy(task->data, data, data_size); |
@@ -566,11 +635,14 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
566 | } else | 635 | } else |
567 | task->data_count = 0; | 636 | task->data_count = 0; |
568 | 637 | ||
569 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { | 638 | if (conn->session->tt->alloc_pdu) { |
570 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " | 639 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { |
571 | "pdu for mgmt task.\n"); | 640 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " |
572 | goto requeue_task; | 641 | "pdu for mgmt task.\n"); |
642 | goto free_task; | ||
643 | } | ||
573 | } | 644 | } |
645 | |||
574 | itt = task->hdr->itt; | 646 | itt = task->hdr->itt; |
575 | task->hdr_len = sizeof(struct iscsi_hdr); | 647 | task->hdr_len = sizeof(struct iscsi_hdr); |
576 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | 648 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
@@ -583,30 +655,22 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
583 | task->conn->session->age); | 655 | task->conn->session->age); |
584 | } | 656 | } |
585 | 657 | ||
586 | INIT_LIST_HEAD(&task->running); | 658 | if (!ihost->workq) { |
587 | list_add_tail(&task->running, &conn->mgmtqueue); | ||
588 | |||
589 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | ||
590 | if (iscsi_prep_mgmt_task(conn, task)) | 659 | if (iscsi_prep_mgmt_task(conn, task)) |
591 | goto free_task; | 660 | goto free_task; |
592 | 661 | ||
593 | if (session->tt->xmit_task(task)) | 662 | if (session->tt->xmit_task(task)) |
594 | goto free_task; | 663 | goto free_task; |
595 | 664 | } else { | |
596 | } else | 665 | list_add_tail(&task->running, &conn->mgmtqueue); |
597 | iscsi_conn_queue_work(conn); | 666 | iscsi_conn_queue_work(conn); |
667 | } | ||
598 | 668 | ||
599 | return task; | 669 | return task; |
600 | 670 | ||
601 | free_task: | 671 | free_task: |
602 | __iscsi_put_task(task); | 672 | __iscsi_put_task(task); |
603 | return NULL; | 673 | return NULL; |
604 | |||
605 | requeue_task: | ||
606 | if (task != conn->login_task) | ||
607 | __kfifo_put(session->cmdpool.queue, (void*)&task, | ||
608 | sizeof(void*)); | ||
609 | return NULL; | ||
610 | } | 674 | } |
611 | 675 | ||
612 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 676 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -701,11 +765,10 @@ invalid_datalen: | |||
701 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 765 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
702 | } | 766 | } |
703 | out: | 767 | out: |
704 | ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n", | 768 | ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n", |
705 | sc, sc->result, task->itt); | 769 | sc, sc->result, task->itt); |
706 | conn->scsirsp_pdus_cnt++; | 770 | conn->scsirsp_pdus_cnt++; |
707 | 771 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | |
708 | __iscsi_put_task(task); | ||
709 | } | 772 | } |
710 | 773 | ||
711 | /** | 774 | /** |
@@ -724,6 +787,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
724 | if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS)) | 787 | if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS)) |
725 | return; | 788 | return; |
726 | 789 | ||
790 | iscsi_update_cmdsn(conn->session, (struct iscsi_nopin *)hdr); | ||
727 | sc->result = (DID_OK << 16) | rhdr->cmd_status; | 791 | sc->result = (DID_OK << 16) | rhdr->cmd_status; |
728 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; | 792 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; |
729 | if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW | | 793 | if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW | |
@@ -738,8 +802,11 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
738 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 802 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
739 | } | 803 | } |
740 | 804 | ||
805 | ISCSI_DBG_SESSION(conn->session, "data in with status done " | ||
806 | "[sc %p res %d itt 0x%x]\n", | ||
807 | sc, sc->result, task->itt); | ||
741 | conn->scsirsp_pdus_cnt++; | 808 | conn->scsirsp_pdus_cnt++; |
742 | __iscsi_put_task(task); | 809 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
743 | } | 810 | } |
744 | 811 | ||
745 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 812 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) |
@@ -823,7 +890,7 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
823 | * | 890 | * |
824 | * The session lock must be held. | 891 | * The session lock must be held. |
825 | */ | 892 | */ |
826 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | 893 | struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
827 | { | 894 | { |
828 | struct iscsi_session *session = conn->session; | 895 | struct iscsi_session *session = conn->session; |
829 | int i; | 896 | int i; |
@@ -840,6 +907,7 @@ static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | |||
840 | 907 | ||
841 | return session->cmds[i]; | 908 | return session->cmds[i]; |
842 | } | 909 | } |
910 | EXPORT_SYMBOL_GPL(iscsi_itt_to_task); | ||
843 | 911 | ||
844 | /** | 912 | /** |
845 | * __iscsi_complete_pdu - complete pdu | 913 | * __iscsi_complete_pdu - complete pdu |
@@ -909,6 +977,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
909 | task = iscsi_itt_to_ctask(conn, hdr->itt); | 977 | task = iscsi_itt_to_ctask(conn, hdr->itt); |
910 | if (!task) | 978 | if (!task) |
911 | return ISCSI_ERR_BAD_ITT; | 979 | return ISCSI_ERR_BAD_ITT; |
980 | task->last_xfer = jiffies; | ||
912 | break; | 981 | break; |
913 | case ISCSI_OP_R2T: | 982 | case ISCSI_OP_R2T: |
914 | /* | 983 | /* |
@@ -959,7 +1028,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
959 | } | 1028 | } |
960 | 1029 | ||
961 | iscsi_tmf_rsp(conn, hdr); | 1030 | iscsi_tmf_rsp(conn, hdr); |
962 | __iscsi_put_task(task); | 1031 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
963 | break; | 1032 | break; |
964 | case ISCSI_OP_NOOP_IN: | 1033 | case ISCSI_OP_NOOP_IN: |
965 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 1034 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
@@ -977,7 +1046,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
977 | goto recv_pdu; | 1046 | goto recv_pdu; |
978 | 1047 | ||
979 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | 1048 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); |
980 | __iscsi_put_task(task); | 1049 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
981 | break; | 1050 | break; |
982 | default: | 1051 | default: |
983 | rc = ISCSI_ERR_BAD_OPCODE; | 1052 | rc = ISCSI_ERR_BAD_OPCODE; |
@@ -989,7 +1058,7 @@ out: | |||
989 | recv_pdu: | 1058 | recv_pdu: |
990 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | 1059 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
991 | rc = ISCSI_ERR_CONN_FAILED; | 1060 | rc = ISCSI_ERR_CONN_FAILED; |
992 | __iscsi_put_task(task); | 1061 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
993 | return rc; | 1062 | return rc; |
994 | } | 1063 | } |
995 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); | 1064 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); |
@@ -1147,10 +1216,12 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) | |||
1147 | spin_unlock_bh(&conn->session->lock); | 1216 | spin_unlock_bh(&conn->session->lock); |
1148 | rc = conn->session->tt->xmit_task(task); | 1217 | rc = conn->session->tt->xmit_task(task); |
1149 | spin_lock_bh(&conn->session->lock); | 1218 | spin_lock_bh(&conn->session->lock); |
1150 | __iscsi_put_task(task); | 1219 | if (!rc) { |
1151 | if (!rc) | ||
1152 | /* done with this task */ | 1220 | /* done with this task */ |
1221 | task->last_xfer = jiffies; | ||
1153 | conn->task = NULL; | 1222 | conn->task = NULL; |
1223 | } | ||
1224 | __iscsi_put_task(task); | ||
1154 | return rc; | 1225 | return rc; |
1155 | } | 1226 | } |
1156 | 1227 | ||
@@ -1166,7 +1237,12 @@ void iscsi_requeue_task(struct iscsi_task *task) | |||
1166 | { | 1237 | { |
1167 | struct iscsi_conn *conn = task->conn; | 1238 | struct iscsi_conn *conn = task->conn; |
1168 | 1239 | ||
1169 | list_move_tail(&task->running, &conn->requeue); | 1240 | /* |
1241 | * this may be on the requeue list already if the xmit_task callout | ||
1242 | * is handling the r2ts while we are adding new ones | ||
1243 | */ | ||
1244 | if (list_empty(&task->running)) | ||
1245 | list_add_tail(&task->running, &conn->requeue); | ||
1170 | iscsi_conn_queue_work(conn); | 1246 | iscsi_conn_queue_work(conn); |
1171 | } | 1247 | } |
1172 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); | 1248 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
@@ -1206,6 +1282,7 @@ check_mgmt: | |||
1206 | while (!list_empty(&conn->mgmtqueue)) { | 1282 | while (!list_empty(&conn->mgmtqueue)) { |
1207 | conn->task = list_entry(conn->mgmtqueue.next, | 1283 | conn->task = list_entry(conn->mgmtqueue.next, |
1208 | struct iscsi_task, running); | 1284 | struct iscsi_task, running); |
1285 | list_del_init(&conn->task->running); | ||
1209 | if (iscsi_prep_mgmt_task(conn, conn->task)) { | 1286 | if (iscsi_prep_mgmt_task(conn, conn->task)) { |
1210 | __iscsi_put_task(conn->task); | 1287 | __iscsi_put_task(conn->task); |
1211 | conn->task = NULL; | 1288 | conn->task = NULL; |
@@ -1217,23 +1294,26 @@ check_mgmt: | |||
1217 | } | 1294 | } |
1218 | 1295 | ||
1219 | /* process pending command queue */ | 1296 | /* process pending command queue */ |
1220 | while (!list_empty(&conn->xmitqueue)) { | 1297 | while (!list_empty(&conn->cmdqueue)) { |
1221 | if (conn->tmf_state == TMF_QUEUED) | 1298 | if (conn->tmf_state == TMF_QUEUED) |
1222 | break; | 1299 | break; |
1223 | 1300 | ||
1224 | conn->task = list_entry(conn->xmitqueue.next, | 1301 | conn->task = list_entry(conn->cmdqueue.next, |
1225 | struct iscsi_task, running); | 1302 | struct iscsi_task, running); |
1303 | list_del_init(&conn->task->running); | ||
1226 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1304 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1227 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); | 1305 | fail_scsi_task(conn->task, DID_IMM_RETRY); |
1228 | continue; | 1306 | continue; |
1229 | } | 1307 | } |
1230 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); | 1308 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1231 | if (rc) { | 1309 | if (rc) { |
1232 | if (rc == -ENOMEM) { | 1310 | if (rc == -ENOMEM) { |
1311 | list_add_tail(&conn->task->running, | ||
1312 | &conn->cmdqueue); | ||
1233 | conn->task = NULL; | 1313 | conn->task = NULL; |
1234 | goto again; | 1314 | goto again; |
1235 | } else | 1315 | } else |
1236 | fail_command(conn, conn->task, DID_ABORT << 16); | 1316 | fail_scsi_task(conn->task, DID_ABORT); |
1237 | continue; | 1317 | continue; |
1238 | } | 1318 | } |
1239 | rc = iscsi_xmit_task(conn); | 1319 | rc = iscsi_xmit_task(conn); |
@@ -1260,8 +1340,8 @@ check_mgmt: | |||
1260 | 1340 | ||
1261 | conn->task = list_entry(conn->requeue.next, | 1341 | conn->task = list_entry(conn->requeue.next, |
1262 | struct iscsi_task, running); | 1342 | struct iscsi_task, running); |
1343 | list_del_init(&conn->task->running); | ||
1263 | conn->task->state = ISCSI_TASK_RUNNING; | 1344 | conn->task->state = ISCSI_TASK_RUNNING; |
1264 | list_move_tail(conn->requeue.next, &conn->run_list); | ||
1265 | rc = iscsi_xmit_task(conn); | 1345 | rc = iscsi_xmit_task(conn); |
1266 | if (rc) | 1346 | if (rc) |
1267 | goto again; | 1347 | goto again; |
@@ -1307,6 +1387,9 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, | |||
1307 | task->state = ISCSI_TASK_PENDING; | 1387 | task->state = ISCSI_TASK_PENDING; |
1308 | task->conn = conn; | 1388 | task->conn = conn; |
1309 | task->sc = sc; | 1389 | task->sc = sc; |
1390 | task->have_checked_conn = false; | ||
1391 | task->last_timeout = jiffies; | ||
1392 | task->last_xfer = jiffies; | ||
1310 | INIT_LIST_HEAD(&task->running); | 1393 | INIT_LIST_HEAD(&task->running); |
1311 | return task; | 1394 | return task; |
1312 | } | 1395 | } |
@@ -1328,6 +1411,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1328 | { | 1411 | { |
1329 | struct iscsi_cls_session *cls_session; | 1412 | struct iscsi_cls_session *cls_session; |
1330 | struct Scsi_Host *host; | 1413 | struct Scsi_Host *host; |
1414 | struct iscsi_host *ihost; | ||
1331 | int reason = 0; | 1415 | int reason = 0; |
1332 | struct iscsi_session *session; | 1416 | struct iscsi_session *session; |
1333 | struct iscsi_conn *conn; | 1417 | struct iscsi_conn *conn; |
@@ -1338,6 +1422,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1338 | sc->SCp.ptr = NULL; | 1422 | sc->SCp.ptr = NULL; |
1339 | 1423 | ||
1340 | host = sc->device->host; | 1424 | host = sc->device->host; |
1425 | ihost = shost_priv(host); | ||
1341 | spin_unlock(host->host_lock); | 1426 | spin_unlock(host->host_lock); |
1342 | 1427 | ||
1343 | cls_session = starget_to_session(scsi_target(sc->device)); | 1428 | cls_session = starget_to_session(scsi_target(sc->device)); |
@@ -1350,13 +1435,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1350 | goto fault; | 1435 | goto fault; |
1351 | } | 1436 | } |
1352 | 1437 | ||
1353 | /* | 1438 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
1354 | * ISCSI_STATE_FAILED is a temp. state. The recovery | ||
1355 | * code will decide what is best to do with command queued | ||
1356 | * during this time | ||
1357 | */ | ||
1358 | if (session->state != ISCSI_STATE_LOGGED_IN && | ||
1359 | session->state != ISCSI_STATE_FAILED) { | ||
1360 | /* | 1439 | /* |
1361 | * to handle the race between when we set the recovery state | 1440 | * to handle the race between when we set the recovery state |
1362 | * and block the session we requeue here (commands could | 1441 | * and block the session we requeue here (commands could |
@@ -1364,12 +1443,15 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1364 | * up because the block code is not locked) | 1443 | * up because the block code is not locked) |
1365 | */ | 1444 | */ |
1366 | switch (session->state) { | 1445 | switch (session->state) { |
1446 | case ISCSI_STATE_FAILED: | ||
1367 | case ISCSI_STATE_IN_RECOVERY: | 1447 | case ISCSI_STATE_IN_RECOVERY: |
1368 | reason = FAILURE_SESSION_IN_RECOVERY; | 1448 | reason = FAILURE_SESSION_IN_RECOVERY; |
1369 | goto reject; | 1449 | sc->result = DID_IMM_RETRY << 16; |
1450 | break; | ||
1370 | case ISCSI_STATE_LOGGING_OUT: | 1451 | case ISCSI_STATE_LOGGING_OUT: |
1371 | reason = FAILURE_SESSION_LOGGING_OUT; | 1452 | reason = FAILURE_SESSION_LOGGING_OUT; |
1372 | goto reject; | 1453 | sc->result = DID_IMM_RETRY << 16; |
1454 | break; | ||
1373 | case ISCSI_STATE_RECOVERY_FAILED: | 1455 | case ISCSI_STATE_RECOVERY_FAILED: |
1374 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; | 1456 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; |
1375 | sc->result = DID_TRANSPORT_FAILFAST << 16; | 1457 | sc->result = DID_TRANSPORT_FAILFAST << 16; |
@@ -1402,9 +1484,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1402 | reason = FAILURE_OOM; | 1484 | reason = FAILURE_OOM; |
1403 | goto reject; | 1485 | goto reject; |
1404 | } | 1486 | } |
1405 | list_add_tail(&task->running, &conn->xmitqueue); | ||
1406 | 1487 | ||
1407 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 1488 | if (!ihost->workq) { |
1408 | reason = iscsi_prep_scsi_cmd_pdu(task); | 1489 | reason = iscsi_prep_scsi_cmd_pdu(task); |
1409 | if (reason) { | 1490 | if (reason) { |
1410 | if (reason == -ENOMEM) { | 1491 | if (reason == -ENOMEM) { |
@@ -1419,8 +1500,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1419 | reason = FAILURE_SESSION_NOT_READY; | 1500 | reason = FAILURE_SESSION_NOT_READY; |
1420 | goto prepd_reject; | 1501 | goto prepd_reject; |
1421 | } | 1502 | } |
1422 | } else | 1503 | } else { |
1504 | list_add_tail(&task->running, &conn->cmdqueue); | ||
1423 | iscsi_conn_queue_work(conn); | 1505 | iscsi_conn_queue_work(conn); |
1506 | } | ||
1424 | 1507 | ||
1425 | session->queued_cmdsn++; | 1508 | session->queued_cmdsn++; |
1426 | spin_unlock(&session->lock); | 1509 | spin_unlock(&session->lock); |
@@ -1429,7 +1512,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1429 | 1512 | ||
1430 | prepd_reject: | 1513 | prepd_reject: |
1431 | sc->scsi_done = NULL; | 1514 | sc->scsi_done = NULL; |
1432 | iscsi_complete_command(task); | 1515 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
1433 | reject: | 1516 | reject: |
1434 | spin_unlock(&session->lock); | 1517 | spin_unlock(&session->lock); |
1435 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", | 1518 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", |
@@ -1439,7 +1522,7 @@ reject: | |||
1439 | 1522 | ||
1440 | prepd_fault: | 1523 | prepd_fault: |
1441 | sc->scsi_done = NULL; | 1524 | sc->scsi_done = NULL; |
1442 | iscsi_complete_command(task); | 1525 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
1443 | fault: | 1526 | fault: |
1444 | spin_unlock(&session->lock); | 1527 | spin_unlock(&session->lock); |
1445 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", | 1528 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", |
@@ -1501,10 +1584,10 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) | |||
1501 | spin_lock_bh(&session->lock); | 1584 | spin_lock_bh(&session->lock); |
1502 | if (session->state == ISCSI_STATE_TERMINATE) { | 1585 | if (session->state == ISCSI_STATE_TERMINATE) { |
1503 | failed: | 1586 | failed: |
1504 | iscsi_session_printk(KERN_INFO, session, | 1587 | ISCSI_DBG_EH(session, |
1505 | "failing target reset: Could not log " | 1588 | "failing target reset: Could not log back into " |
1506 | "back into target [age %d]\n", | 1589 | "target [age %d]\n", |
1507 | session->age); | 1590 | session->age); |
1508 | spin_unlock_bh(&session->lock); | 1591 | spin_unlock_bh(&session->lock); |
1509 | mutex_unlock(&session->eh_mutex); | 1592 | mutex_unlock(&session->eh_mutex); |
1510 | return FAILED; | 1593 | return FAILED; |
@@ -1518,7 +1601,7 @@ failed: | |||
1518 | */ | 1601 | */ |
1519 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1602 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1520 | 1603 | ||
1521 | ISCSI_DBG_SESSION(session, "wait for relogin\n"); | 1604 | ISCSI_DBG_EH(session, "wait for relogin\n"); |
1522 | wait_event_interruptible(conn->ehwait, | 1605 | wait_event_interruptible(conn->ehwait, |
1523 | session->state == ISCSI_STATE_TERMINATE || | 1606 | session->state == ISCSI_STATE_TERMINATE || |
1524 | session->state == ISCSI_STATE_LOGGED_IN || | 1607 | session->state == ISCSI_STATE_LOGGED_IN || |
@@ -1528,10 +1611,10 @@ failed: | |||
1528 | 1611 | ||
1529 | mutex_lock(&session->eh_mutex); | 1612 | mutex_lock(&session->eh_mutex); |
1530 | spin_lock_bh(&session->lock); | 1613 | spin_lock_bh(&session->lock); |
1531 | if (session->state == ISCSI_STATE_LOGGED_IN) | 1614 | if (session->state == ISCSI_STATE_LOGGED_IN) { |
1532 | iscsi_session_printk(KERN_INFO, session, | 1615 | ISCSI_DBG_EH(session, |
1533 | "target reset succeeded\n"); | 1616 | "target reset succeeded\n"); |
1534 | else | 1617 | } else |
1535 | goto failed; | 1618 | goto failed; |
1536 | spin_unlock_bh(&session->lock); | 1619 | spin_unlock_bh(&session->lock); |
1537 | mutex_unlock(&session->eh_mutex); | 1620 | mutex_unlock(&session->eh_mutex); |
@@ -1547,7 +1630,7 @@ static void iscsi_tmf_timedout(unsigned long data) | |||
1547 | spin_lock(&session->lock); | 1630 | spin_lock(&session->lock); |
1548 | if (conn->tmf_state == TMF_QUEUED) { | 1631 | if (conn->tmf_state == TMF_QUEUED) { |
1549 | conn->tmf_state = TMF_TIMEDOUT; | 1632 | conn->tmf_state = TMF_TIMEDOUT; |
1550 | ISCSI_DBG_SESSION(session, "tmf timedout\n"); | 1633 | ISCSI_DBG_EH(session, "tmf timedout\n"); |
1551 | /* unblock eh_abort() */ | 1634 | /* unblock eh_abort() */ |
1552 | wake_up(&conn->ehwait); | 1635 | wake_up(&conn->ehwait); |
1553 | } | 1636 | } |
@@ -1567,7 +1650,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1567 | spin_unlock_bh(&session->lock); | 1650 | spin_unlock_bh(&session->lock); |
1568 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1651 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1569 | spin_lock_bh(&session->lock); | 1652 | spin_lock_bh(&session->lock); |
1570 | ISCSI_DBG_SESSION(session, "tmf exec failure\n"); | 1653 | ISCSI_DBG_EH(session, "tmf exec failure\n"); |
1571 | return -EPERM; | 1654 | return -EPERM; |
1572 | } | 1655 | } |
1573 | conn->tmfcmd_pdus_cnt++; | 1656 | conn->tmfcmd_pdus_cnt++; |
@@ -1575,7 +1658,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1575 | conn->tmf_timer.function = iscsi_tmf_timedout; | 1658 | conn->tmf_timer.function = iscsi_tmf_timedout; |
1576 | conn->tmf_timer.data = (unsigned long)conn; | 1659 | conn->tmf_timer.data = (unsigned long)conn; |
1577 | add_timer(&conn->tmf_timer); | 1660 | add_timer(&conn->tmf_timer); |
1578 | ISCSI_DBG_SESSION(session, "tmf set timeout\n"); | 1661 | ISCSI_DBG_EH(session, "tmf set timeout\n"); |
1579 | 1662 | ||
1580 | spin_unlock_bh(&session->lock); | 1663 | spin_unlock_bh(&session->lock); |
1581 | mutex_unlock(&session->eh_mutex); | 1664 | mutex_unlock(&session->eh_mutex); |
@@ -1608,44 +1691,24 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1608 | * Fail commands. session lock held and recv side suspended and xmit | 1691 | * Fail commands. session lock held and recv side suspended and xmit |
1609 | * thread flushed | 1692 | * thread flushed |
1610 | */ | 1693 | */ |
1611 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | 1694 | static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, |
1612 | int error) | 1695 | int error) |
1613 | { | 1696 | { |
1614 | struct iscsi_task *task, *tmp; | 1697 | struct iscsi_task *task; |
1615 | 1698 | int i; | |
1616 | if (conn->task) { | ||
1617 | if (lun == -1 || | ||
1618 | (conn->task->sc && conn->task->sc->device->lun == lun)) | ||
1619 | conn->task = NULL; | ||
1620 | } | ||
1621 | 1699 | ||
1622 | /* flush pending */ | 1700 | for (i = 0; i < conn->session->cmds_max; i++) { |
1623 | list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { | 1701 | task = conn->session->cmds[i]; |
1624 | if (lun == task->sc->device->lun || lun == -1) { | 1702 | if (!task->sc || task->state == ISCSI_TASK_FREE) |
1625 | ISCSI_DBG_SESSION(conn->session, | 1703 | continue; |
1626 | "failing pending sc %p itt 0x%x\n", | ||
1627 | task->sc, task->itt); | ||
1628 | fail_command(conn, task, error << 16); | ||
1629 | } | ||
1630 | } | ||
1631 | 1704 | ||
1632 | list_for_each_entry_safe(task, tmp, &conn->requeue, running) { | 1705 | if (lun != -1 && lun != task->sc->device->lun) |
1633 | if (lun == task->sc->device->lun || lun == -1) { | 1706 | continue; |
1634 | ISCSI_DBG_SESSION(conn->session, | ||
1635 | "failing requeued sc %p itt 0x%x\n", | ||
1636 | task->sc, task->itt); | ||
1637 | fail_command(conn, task, error << 16); | ||
1638 | } | ||
1639 | } | ||
1640 | 1707 | ||
1641 | /* fail all other running */ | 1708 | ISCSI_DBG_SESSION(conn->session, |
1642 | list_for_each_entry_safe(task, tmp, &conn->run_list, running) { | 1709 | "failing sc %p itt 0x%x state %d\n", |
1643 | if (lun == task->sc->device->lun || lun == -1) { | 1710 | task->sc, task->itt, task->state); |
1644 | ISCSI_DBG_SESSION(conn->session, | 1711 | fail_scsi_task(task, error); |
1645 | "failing in progress sc %p itt 0x%x\n", | ||
1646 | task->sc, task->itt); | ||
1647 | fail_command(conn, task, error << 16); | ||
1648 | } | ||
1649 | } | 1712 | } |
1650 | } | 1713 | } |
1651 | 1714 | ||
@@ -1655,7 +1718,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn) | |||
1655 | struct iscsi_host *ihost = shost_priv(shost); | 1718 | struct iscsi_host *ihost = shost_priv(shost); |
1656 | 1719 | ||
1657 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1720 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1658 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1721 | if (ihost->workq) |
1659 | flush_workqueue(ihost->workq); | 1722 | flush_workqueue(ihost->workq); |
1660 | } | 1723 | } |
1661 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | 1724 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); |
@@ -1663,21 +1726,37 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | |||
1663 | static void iscsi_start_tx(struct iscsi_conn *conn) | 1726 | static void iscsi_start_tx(struct iscsi_conn *conn) |
1664 | { | 1727 | { |
1665 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1728 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1666 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1729 | iscsi_conn_queue_work(conn); |
1667 | iscsi_conn_queue_work(conn); | ||
1668 | } | 1730 | } |
1669 | 1731 | ||
1670 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1732 | /* |
1733 | * We want to make sure a ping is in flight. It has timed out. | ||
1734 | * And we are not busy processing a pdu that is making | ||
1735 | * progress but got started before the ping and is taking a while | ||
1736 | * to complete so the ping is just stuck behind it in a queue. | ||
1737 | */ | ||
1738 | static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) | ||
1671 | { | 1739 | { |
1740 | if (conn->ping_task && | ||
1741 | time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + | ||
1742 | (conn->ping_timeout * HZ), jiffies)) | ||
1743 | return 1; | ||
1744 | else | ||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1748 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) | ||
1749 | { | ||
1750 | enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; | ||
1751 | struct iscsi_task *task = NULL; | ||
1672 | struct iscsi_cls_session *cls_session; | 1752 | struct iscsi_cls_session *cls_session; |
1673 | struct iscsi_session *session; | 1753 | struct iscsi_session *session; |
1674 | struct iscsi_conn *conn; | 1754 | struct iscsi_conn *conn; |
1675 | enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; | ||
1676 | 1755 | ||
1677 | cls_session = starget_to_session(scsi_target(scmd->device)); | 1756 | cls_session = starget_to_session(scsi_target(sc->device)); |
1678 | session = cls_session->dd_data; | 1757 | session = cls_session->dd_data; |
1679 | 1758 | ||
1680 | ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd); | 1759 | ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc); |
1681 | 1760 | ||
1682 | spin_lock(&session->lock); | 1761 | spin_lock(&session->lock); |
1683 | if (session->state != ISCSI_STATE_LOGGED_IN) { | 1762 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
@@ -1696,29 +1775,62 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | |||
1696 | goto done; | 1775 | goto done; |
1697 | } | 1776 | } |
1698 | 1777 | ||
1778 | task = (struct iscsi_task *)sc->SCp.ptr; | ||
1779 | if (!task) | ||
1780 | goto done; | ||
1781 | /* | ||
1782 | * If we have sent (at least queued to the network layer) a pdu or | ||
1783 | * recvd one for the task since the last timeout ask for | ||
1784 | * more time. If on the next timeout we have not made progress | ||
1785 | * we can check if it is the task or connection when we send the | ||
1786 | * nop as a ping. | ||
1787 | */ | ||
1788 | if (time_after_eq(task->last_xfer, task->last_timeout)) { | ||
1789 | ISCSI_DBG_EH(session, "Command making progress. Asking " | ||
1790 | "scsi-ml for more time to complete. " | ||
1791 | "Last data recv at %lu. Last timeout was at " | ||
1792 | "%lu\n.", task->last_xfer, task->last_timeout); | ||
1793 | task->have_checked_conn = false; | ||
1794 | rc = BLK_EH_RESET_TIMER; | ||
1795 | goto done; | ||
1796 | } | ||
1797 | |||
1699 | if (!conn->recv_timeout && !conn->ping_timeout) | 1798 | if (!conn->recv_timeout && !conn->ping_timeout) |
1700 | goto done; | 1799 | goto done; |
1701 | /* | 1800 | /* |
1702 | * if the ping timedout then we are in the middle of cleaning up | 1801 | * if the ping timedout then we are in the middle of cleaning up |
1703 | * and can let the iscsi eh handle it | 1802 | * and can let the iscsi eh handle it |
1704 | */ | 1803 | */ |
1705 | if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + | 1804 | if (iscsi_has_ping_timed_out(conn)) { |
1706 | (conn->ping_timeout * HZ), jiffies)) | ||
1707 | rc = BLK_EH_RESET_TIMER; | 1805 | rc = BLK_EH_RESET_TIMER; |
1806 | goto done; | ||
1807 | } | ||
1808 | |||
1809 | /* Assumes nop timeout is shorter than scsi cmd timeout */ | ||
1810 | if (task->have_checked_conn) | ||
1811 | goto done; | ||
1812 | |||
1708 | /* | 1813 | /* |
1709 | * if we are about to check the transport then give the command | 1814 | * Checking the transport already or nop from a cmd timeout still |
1710 | * more time | 1815 | * running |
1711 | */ | 1816 | */ |
1712 | if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), | 1817 | if (conn->ping_task) { |
1713 | jiffies)) | 1818 | task->have_checked_conn = true; |
1714 | rc = BLK_EH_RESET_TIMER; | ||
1715 | /* if in the middle of checking the transport then give us more time */ | ||
1716 | if (conn->ping_task) | ||
1717 | rc = BLK_EH_RESET_TIMER; | 1819 | rc = BLK_EH_RESET_TIMER; |
1820 | goto done; | ||
1821 | } | ||
1822 | |||
1823 | /* Make sure there is a transport check done */ | ||
1824 | iscsi_send_nopout(conn, NULL); | ||
1825 | task->have_checked_conn = true; | ||
1826 | rc = BLK_EH_RESET_TIMER; | ||
1827 | |||
1718 | done: | 1828 | done: |
1829 | if (task) | ||
1830 | task->last_timeout = jiffies; | ||
1719 | spin_unlock(&session->lock); | 1831 | spin_unlock(&session->lock); |
1720 | ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? | 1832 | ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? |
1721 | "timer reset" : "nh"); | 1833 | "timer reset" : "nh"); |
1722 | return rc; | 1834 | return rc; |
1723 | } | 1835 | } |
1724 | 1836 | ||
@@ -1738,13 +1850,13 @@ static void iscsi_check_transport_timeouts(unsigned long data) | |||
1738 | 1850 | ||
1739 | recv_timeout *= HZ; | 1851 | recv_timeout *= HZ; |
1740 | last_recv = conn->last_recv; | 1852 | last_recv = conn->last_recv; |
1741 | if (conn->ping_task && | 1853 | |
1742 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), | 1854 | if (iscsi_has_ping_timed_out(conn)) { |
1743 | jiffies)) { | ||
1744 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " | 1855 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " |
1745 | "expired, last rx %lu, last ping %lu, " | 1856 | "expired, recv timeout %d, last rx %lu, " |
1746 | "now %lu\n", conn->ping_timeout, last_recv, | 1857 | "last ping %lu, now %lu\n", |
1747 | conn->last_ping, jiffies); | 1858 | conn->ping_timeout, conn->recv_timeout, |
1859 | last_recv, conn->last_ping, jiffies); | ||
1748 | spin_unlock(&session->lock); | 1860 | spin_unlock(&session->lock); |
1749 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1861 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1750 | return; | 1862 | return; |
@@ -1788,6 +1900,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1788 | cls_session = starget_to_session(scsi_target(sc->device)); | 1900 | cls_session = starget_to_session(scsi_target(sc->device)); |
1789 | session = cls_session->dd_data; | 1901 | session = cls_session->dd_data; |
1790 | 1902 | ||
1903 | ISCSI_DBG_EH(session, "aborting sc %p\n", sc); | ||
1904 | |||
1791 | mutex_lock(&session->eh_mutex); | 1905 | mutex_lock(&session->eh_mutex); |
1792 | spin_lock_bh(&session->lock); | 1906 | spin_lock_bh(&session->lock); |
1793 | /* | 1907 | /* |
@@ -1795,8 +1909,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1795 | * got the command. | 1909 | * got the command. |
1796 | */ | 1910 | */ |
1797 | if (!sc->SCp.ptr) { | 1911 | if (!sc->SCp.ptr) { |
1798 | ISCSI_DBG_SESSION(session, "sc never reached iscsi layer or " | 1912 | ISCSI_DBG_EH(session, "sc never reached iscsi layer or " |
1799 | "it completed.\n"); | 1913 | "it completed.\n"); |
1800 | spin_unlock_bh(&session->lock); | 1914 | spin_unlock_bh(&session->lock); |
1801 | mutex_unlock(&session->eh_mutex); | 1915 | mutex_unlock(&session->eh_mutex); |
1802 | return SUCCESS; | 1916 | return SUCCESS; |
@@ -1810,6 +1924,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1810 | sc->SCp.phase != session->age) { | 1924 | sc->SCp.phase != session->age) { |
1811 | spin_unlock_bh(&session->lock); | 1925 | spin_unlock_bh(&session->lock); |
1812 | mutex_unlock(&session->eh_mutex); | 1926 | mutex_unlock(&session->eh_mutex); |
1927 | ISCSI_DBG_EH(session, "failing abort due to dropped " | ||
1928 | "session.\n"); | ||
1813 | return FAILED; | 1929 | return FAILED; |
1814 | } | 1930 | } |
1815 | 1931 | ||
@@ -1818,18 +1934,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1818 | age = session->age; | 1934 | age = session->age; |
1819 | 1935 | ||
1820 | task = (struct iscsi_task *)sc->SCp.ptr; | 1936 | task = (struct iscsi_task *)sc->SCp.ptr; |
1821 | ISCSI_DBG_SESSION(session, "aborting [sc %p itt 0x%x]\n", | 1937 | ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", |
1822 | sc, task->itt); | 1938 | sc, task->itt); |
1823 | 1939 | ||
1824 | /* task completed before time out */ | 1940 | /* task completed before time out */ |
1825 | if (!task->sc) { | 1941 | if (!task->sc) { |
1826 | ISCSI_DBG_SESSION(session, "sc completed while abort in " | 1942 | ISCSI_DBG_EH(session, "sc completed while abort in progress\n"); |
1827 | "progress\n"); | ||
1828 | goto success; | 1943 | goto success; |
1829 | } | 1944 | } |
1830 | 1945 | ||
1831 | if (task->state == ISCSI_TASK_PENDING) { | 1946 | if (task->state == ISCSI_TASK_PENDING) { |
1832 | fail_command(conn, task, DID_ABORT << 16); | 1947 | fail_scsi_task(task, DID_ABORT); |
1833 | goto success; | 1948 | goto success; |
1834 | } | 1949 | } |
1835 | 1950 | ||
@@ -1860,7 +1975,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1860 | * then sent more data for the cmd. | 1975 | * then sent more data for the cmd. |
1861 | */ | 1976 | */ |
1862 | spin_lock(&session->lock); | 1977 | spin_lock(&session->lock); |
1863 | fail_command(conn, task, DID_ABORT << 16); | 1978 | fail_scsi_task(task, DID_ABORT); |
1864 | conn->tmf_state = TMF_INITIAL; | 1979 | conn->tmf_state = TMF_INITIAL; |
1865 | spin_unlock(&session->lock); | 1980 | spin_unlock(&session->lock); |
1866 | iscsi_start_tx(conn); | 1981 | iscsi_start_tx(conn); |
@@ -1873,8 +1988,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1873 | if (!sc->SCp.ptr) { | 1988 | if (!sc->SCp.ptr) { |
1874 | conn->tmf_state = TMF_INITIAL; | 1989 | conn->tmf_state = TMF_INITIAL; |
1875 | /* task completed before tmf abort response */ | 1990 | /* task completed before tmf abort response */ |
1876 | ISCSI_DBG_SESSION(session, "sc completed while abort " | 1991 | ISCSI_DBG_EH(session, "sc completed while abort in " |
1877 | "in progress\n"); | 1992 | "progress\n"); |
1878 | goto success; | 1993 | goto success; |
1879 | } | 1994 | } |
1880 | /* fall through */ | 1995 | /* fall through */ |
@@ -1886,16 +2001,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1886 | success: | 2001 | success: |
1887 | spin_unlock_bh(&session->lock); | 2002 | spin_unlock_bh(&session->lock); |
1888 | success_unlocked: | 2003 | success_unlocked: |
1889 | ISCSI_DBG_SESSION(session, "abort success [sc %p itt 0x%x]\n", | 2004 | ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x]\n", |
1890 | sc, task->itt); | 2005 | sc, task->itt); |
1891 | mutex_unlock(&session->eh_mutex); | 2006 | mutex_unlock(&session->eh_mutex); |
1892 | return SUCCESS; | 2007 | return SUCCESS; |
1893 | 2008 | ||
1894 | failed: | 2009 | failed: |
1895 | spin_unlock_bh(&session->lock); | 2010 | spin_unlock_bh(&session->lock); |
1896 | failed_unlocked: | 2011 | failed_unlocked: |
1897 | ISCSI_DBG_SESSION(session, "abort failed [sc %p itt 0x%x]\n", sc, | 2012 | ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]\n", sc, |
1898 | task ? task->itt : 0); | 2013 | task ? task->itt : 0); |
1899 | mutex_unlock(&session->eh_mutex); | 2014 | mutex_unlock(&session->eh_mutex); |
1900 | return FAILED; | 2015 | return FAILED; |
1901 | } | 2016 | } |
@@ -1922,8 +2037,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1922 | cls_session = starget_to_session(scsi_target(sc->device)); | 2037 | cls_session = starget_to_session(scsi_target(sc->device)); |
1923 | session = cls_session->dd_data; | 2038 | session = cls_session->dd_data; |
1924 | 2039 | ||
1925 | ISCSI_DBG_SESSION(session, "LU Reset [sc %p lun %u]\n", | 2040 | ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]\n", sc, sc->device->lun); |
1926 | sc, sc->device->lun); | ||
1927 | 2041 | ||
1928 | mutex_lock(&session->eh_mutex); | 2042 | mutex_lock(&session->eh_mutex); |
1929 | spin_lock_bh(&session->lock); | 2043 | spin_lock_bh(&session->lock); |
@@ -1967,7 +2081,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1967 | iscsi_suspend_tx(conn); | 2081 | iscsi_suspend_tx(conn); |
1968 | 2082 | ||
1969 | spin_lock_bh(&session->lock); | 2083 | spin_lock_bh(&session->lock); |
1970 | fail_all_commands(conn, sc->device->lun, DID_ERROR); | 2084 | fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); |
1971 | conn->tmf_state = TMF_INITIAL; | 2085 | conn->tmf_state = TMF_INITIAL; |
1972 | spin_unlock_bh(&session->lock); | 2086 | spin_unlock_bh(&session->lock); |
1973 | 2087 | ||
@@ -1977,8 +2091,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1977 | unlock: | 2091 | unlock: |
1978 | spin_unlock_bh(&session->lock); | 2092 | spin_unlock_bh(&session->lock); |
1979 | done: | 2093 | done: |
1980 | ISCSI_DBG_SESSION(session, "dev reset result = %s\n", | 2094 | ISCSI_DBG_EH(session, "dev reset result = %s\n", |
1981 | rc == SUCCESS ? "SUCCESS" : "FAILED"); | 2095 | rc == SUCCESS ? "SUCCESS" : "FAILED"); |
1982 | mutex_unlock(&session->eh_mutex); | 2096 | mutex_unlock(&session->eh_mutex); |
1983 | return rc; | 2097 | return rc; |
1984 | } | 2098 | } |
@@ -2274,6 +2388,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2274 | if (cmd_task_size) | 2388 | if (cmd_task_size) |
2275 | task->dd_data = &task[1]; | 2389 | task->dd_data = &task[1]; |
2276 | task->itt = cmd_i; | 2390 | task->itt = cmd_i; |
2391 | task->state = ISCSI_TASK_FREE; | ||
2277 | INIT_LIST_HEAD(&task->running); | 2392 | INIT_LIST_HEAD(&task->running); |
2278 | } | 2393 | } |
2279 | 2394 | ||
@@ -2360,10 +2475,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2360 | conn->transport_timer.data = (unsigned long)conn; | 2475 | conn->transport_timer.data = (unsigned long)conn; |
2361 | conn->transport_timer.function = iscsi_check_transport_timeouts; | 2476 | conn->transport_timer.function = iscsi_check_transport_timeouts; |
2362 | 2477 | ||
2363 | INIT_LIST_HEAD(&conn->run_list); | ||
2364 | INIT_LIST_HEAD(&conn->mgmt_run_list); | ||
2365 | INIT_LIST_HEAD(&conn->mgmtqueue); | 2478 | INIT_LIST_HEAD(&conn->mgmtqueue); |
2366 | INIT_LIST_HEAD(&conn->xmitqueue); | 2479 | INIT_LIST_HEAD(&conn->cmdqueue); |
2367 | INIT_LIST_HEAD(&conn->requeue); | 2480 | INIT_LIST_HEAD(&conn->requeue); |
2368 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2481 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
2369 | 2482 | ||
@@ -2531,27 +2644,28 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2531 | EXPORT_SYMBOL_GPL(iscsi_conn_start); | 2644 | EXPORT_SYMBOL_GPL(iscsi_conn_start); |
2532 | 2645 | ||
2533 | static void | 2646 | static void |
2534 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | 2647 | fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) |
2535 | { | 2648 | { |
2536 | struct iscsi_task *task, *tmp; | 2649 | struct iscsi_task *task; |
2650 | int i, state; | ||
2537 | 2651 | ||
2538 | /* handle pending */ | 2652 | for (i = 0; i < conn->session->cmds_max; i++) { |
2539 | list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) { | 2653 | task = conn->session->cmds[i]; |
2540 | ISCSI_DBG_SESSION(session, "flushing pending mgmt task " | 2654 | if (task->sc) |
2541 | "itt 0x%x\n", task->itt); | 2655 | continue; |
2542 | /* release ref from prep task */ | ||
2543 | __iscsi_put_task(task); | ||
2544 | } | ||
2545 | 2656 | ||
2546 | /* handle running */ | 2657 | if (task->state == ISCSI_TASK_FREE) |
2547 | list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) { | 2658 | continue; |
2548 | ISCSI_DBG_SESSION(session, "flushing running mgmt task " | 2659 | |
2549 | "itt 0x%x\n", task->itt); | 2660 | ISCSI_DBG_SESSION(conn->session, |
2550 | /* release ref from prep task */ | 2661 | "failing mgmt itt 0x%x state %d\n", |
2551 | __iscsi_put_task(task); | 2662 | task->itt, task->state); |
2552 | } | 2663 | state = ISCSI_TASK_ABRT_SESS_RECOV; |
2664 | if (task->state == ISCSI_TASK_PENDING) | ||
2665 | state = ISCSI_TASK_COMPLETED; | ||
2666 | iscsi_complete_task(task, state); | ||
2553 | 2667 | ||
2554 | conn->task = NULL; | 2668 | } |
2555 | } | 2669 | } |
2556 | 2670 | ||
2557 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 2671 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
@@ -2559,8 +2673,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2559 | { | 2673 | { |
2560 | int old_stop_stage; | 2674 | int old_stop_stage; |
2561 | 2675 | ||
2562 | del_timer_sync(&conn->transport_timer); | ||
2563 | |||
2564 | mutex_lock(&session->eh_mutex); | 2676 | mutex_lock(&session->eh_mutex); |
2565 | spin_lock_bh(&session->lock); | 2677 | spin_lock_bh(&session->lock); |
2566 | if (conn->stop_stage == STOP_CONN_TERM) { | 2678 | if (conn->stop_stage == STOP_CONN_TERM) { |
@@ -2578,13 +2690,17 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2578 | session->state = ISCSI_STATE_TERMINATE; | 2690 | session->state = ISCSI_STATE_TERMINATE; |
2579 | else if (conn->stop_stage != STOP_CONN_RECOVER) | 2691 | else if (conn->stop_stage != STOP_CONN_RECOVER) |
2580 | session->state = ISCSI_STATE_IN_RECOVERY; | 2692 | session->state = ISCSI_STATE_IN_RECOVERY; |
2693 | spin_unlock_bh(&session->lock); | ||
2694 | |||
2695 | del_timer_sync(&conn->transport_timer); | ||
2696 | iscsi_suspend_tx(conn); | ||
2581 | 2697 | ||
2698 | spin_lock_bh(&session->lock); | ||
2582 | old_stop_stage = conn->stop_stage; | 2699 | old_stop_stage = conn->stop_stage; |
2583 | conn->stop_stage = flag; | 2700 | conn->stop_stage = flag; |
2584 | conn->c_stage = ISCSI_CONN_STOPPED; | 2701 | conn->c_stage = ISCSI_CONN_STOPPED; |
2585 | spin_unlock_bh(&session->lock); | 2702 | spin_unlock_bh(&session->lock); |
2586 | 2703 | ||
2587 | iscsi_suspend_tx(conn); | ||
2588 | /* | 2704 | /* |
2589 | * for connection level recovery we should not calculate | 2705 | * for connection level recovery we should not calculate |
2590 | * header digest. conn->hdr_size used for optimization | 2706 | * header digest. conn->hdr_size used for optimization |
@@ -2605,11 +2721,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2605 | * flush queues. | 2721 | * flush queues. |
2606 | */ | 2722 | */ |
2607 | spin_lock_bh(&session->lock); | 2723 | spin_lock_bh(&session->lock); |
2608 | if (flag == STOP_CONN_RECOVER) | 2724 | fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); |
2609 | fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED); | 2725 | fail_mgmt_tasks(session, conn); |
2610 | else | ||
2611 | fail_all_commands(conn, -1, DID_ERROR); | ||
2612 | flush_control_queues(session, conn); | ||
2613 | spin_unlock_bh(&session->lock); | 2726 | spin_unlock_bh(&session->lock); |
2614 | mutex_unlock(&session->eh_mutex); | 2727 | mutex_unlock(&session->eh_mutex); |
2615 | } | 2728 | } |
@@ -2651,6 +2764,23 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
2651 | } | 2764 | } |
2652 | EXPORT_SYMBOL_GPL(iscsi_conn_bind); | 2765 | EXPORT_SYMBOL_GPL(iscsi_conn_bind); |
2653 | 2766 | ||
2767 | static int iscsi_switch_str_param(char **param, char *new_val_buf) | ||
2768 | { | ||
2769 | char *new_val; | ||
2770 | |||
2771 | if (*param) { | ||
2772 | if (!strcmp(*param, new_val_buf)) | ||
2773 | return 0; | ||
2774 | } | ||
2775 | |||
2776 | new_val = kstrdup(new_val_buf, GFP_NOIO); | ||
2777 | if (!new_val) | ||
2778 | return -ENOMEM; | ||
2779 | |||
2780 | kfree(*param); | ||
2781 | *param = new_val; | ||
2782 | return 0; | ||
2783 | } | ||
2654 | 2784 | ||
2655 | int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | 2785 | int iscsi_set_param(struct iscsi_cls_conn *cls_conn, |
2656 | enum iscsi_param param, char *buf, int buflen) | 2786 | enum iscsi_param param, char *buf, int buflen) |
@@ -2723,38 +2853,15 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2723 | sscanf(buf, "%u", &conn->exp_statsn); | 2853 | sscanf(buf, "%u", &conn->exp_statsn); |
2724 | break; | 2854 | break; |
2725 | case ISCSI_PARAM_USERNAME: | 2855 | case ISCSI_PARAM_USERNAME: |
2726 | kfree(session->username); | 2856 | return iscsi_switch_str_param(&session->username, buf); |
2727 | session->username = kstrdup(buf, GFP_KERNEL); | ||
2728 | if (!session->username) | ||
2729 | return -ENOMEM; | ||
2730 | break; | ||
2731 | case ISCSI_PARAM_USERNAME_IN: | 2857 | case ISCSI_PARAM_USERNAME_IN: |
2732 | kfree(session->username_in); | 2858 | return iscsi_switch_str_param(&session->username_in, buf); |
2733 | session->username_in = kstrdup(buf, GFP_KERNEL); | ||
2734 | if (!session->username_in) | ||
2735 | return -ENOMEM; | ||
2736 | break; | ||
2737 | case ISCSI_PARAM_PASSWORD: | 2859 | case ISCSI_PARAM_PASSWORD: |
2738 | kfree(session->password); | 2860 | return iscsi_switch_str_param(&session->password, buf); |
2739 | session->password = kstrdup(buf, GFP_KERNEL); | ||
2740 | if (!session->password) | ||
2741 | return -ENOMEM; | ||
2742 | break; | ||
2743 | case ISCSI_PARAM_PASSWORD_IN: | 2861 | case ISCSI_PARAM_PASSWORD_IN: |
2744 | kfree(session->password_in); | 2862 | return iscsi_switch_str_param(&session->password_in, buf); |
2745 | session->password_in = kstrdup(buf, GFP_KERNEL); | ||
2746 | if (!session->password_in) | ||
2747 | return -ENOMEM; | ||
2748 | break; | ||
2749 | case ISCSI_PARAM_TARGET_NAME: | 2863 | case ISCSI_PARAM_TARGET_NAME: |
2750 | /* this should not change between logins */ | 2864 | return iscsi_switch_str_param(&session->targetname, buf); |
2751 | if (session->targetname) | ||
2752 | break; | ||
2753 | |||
2754 | session->targetname = kstrdup(buf, GFP_KERNEL); | ||
2755 | if (!session->targetname) | ||
2756 | return -ENOMEM; | ||
2757 | break; | ||
2758 | case ISCSI_PARAM_TPGT: | 2865 | case ISCSI_PARAM_TPGT: |
2759 | sscanf(buf, "%d", &session->tpgt); | 2866 | sscanf(buf, "%d", &session->tpgt); |
2760 | break; | 2867 | break; |
@@ -2762,25 +2869,11 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2762 | sscanf(buf, "%d", &conn->persistent_port); | 2869 | sscanf(buf, "%d", &conn->persistent_port); |
2763 | break; | 2870 | break; |
2764 | case ISCSI_PARAM_PERSISTENT_ADDRESS: | 2871 | case ISCSI_PARAM_PERSISTENT_ADDRESS: |
2765 | /* | 2872 | return iscsi_switch_str_param(&conn->persistent_address, buf); |
2766 | * this is the address returned in discovery so it should | ||
2767 | * not change between logins. | ||
2768 | */ | ||
2769 | if (conn->persistent_address) | ||
2770 | break; | ||
2771 | |||
2772 | conn->persistent_address = kstrdup(buf, GFP_KERNEL); | ||
2773 | if (!conn->persistent_address) | ||
2774 | return -ENOMEM; | ||
2775 | break; | ||
2776 | case ISCSI_PARAM_IFACE_NAME: | 2873 | case ISCSI_PARAM_IFACE_NAME: |
2777 | if (!session->ifacename) | 2874 | return iscsi_switch_str_param(&session->ifacename, buf); |
2778 | session->ifacename = kstrdup(buf, GFP_KERNEL); | ||
2779 | break; | ||
2780 | case ISCSI_PARAM_INITIATOR_NAME: | 2875 | case ISCSI_PARAM_INITIATOR_NAME: |
2781 | if (!session->initiatorname) | 2876 | return iscsi_switch_str_param(&session->initiatorname, buf); |
2782 | session->initiatorname = kstrdup(buf, GFP_KERNEL); | ||
2783 | break; | ||
2784 | default: | 2877 | default: |
2785 | return -ENOSYS; | 2878 | return -ENOSYS; |
2786 | } | 2879 | } |
@@ -2851,10 +2944,7 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
2851 | len = sprintf(buf, "%s\n", session->ifacename); | 2944 | len = sprintf(buf, "%s\n", session->ifacename); |
2852 | break; | 2945 | break; |
2853 | case ISCSI_PARAM_INITIATOR_NAME: | 2946 | case ISCSI_PARAM_INITIATOR_NAME: |
2854 | if (!session->initiatorname) | 2947 | len = sprintf(buf, "%s\n", session->initiatorname); |
2855 | len = sprintf(buf, "%s\n", "unknown"); | ||
2856 | else | ||
2857 | len = sprintf(buf, "%s\n", session->initiatorname); | ||
2858 | break; | 2948 | break; |
2859 | default: | 2949 | default: |
2860 | return -ENOSYS; | 2950 | return -ENOSYS; |
@@ -2920,29 +3010,16 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, | |||
2920 | 3010 | ||
2921 | switch (param) { | 3011 | switch (param) { |
2922 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 3012 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2923 | if (!ihost->netdev) | 3013 | len = sprintf(buf, "%s\n", ihost->netdev); |
2924 | len = sprintf(buf, "%s\n", "default"); | ||
2925 | else | ||
2926 | len = sprintf(buf, "%s\n", ihost->netdev); | ||
2927 | break; | 3014 | break; |
2928 | case ISCSI_HOST_PARAM_HWADDRESS: | 3015 | case ISCSI_HOST_PARAM_HWADDRESS: |
2929 | if (!ihost->hwaddress) | 3016 | len = sprintf(buf, "%s\n", ihost->hwaddress); |
2930 | len = sprintf(buf, "%s\n", "default"); | ||
2931 | else | ||
2932 | len = sprintf(buf, "%s\n", ihost->hwaddress); | ||
2933 | break; | 3017 | break; |
2934 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 3018 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2935 | if (!ihost->initiatorname) | 3019 | len = sprintf(buf, "%s\n", ihost->initiatorname); |
2936 | len = sprintf(buf, "%s\n", "unknown"); | ||
2937 | else | ||
2938 | len = sprintf(buf, "%s\n", ihost->initiatorname); | ||
2939 | break; | 3020 | break; |
2940 | case ISCSI_HOST_PARAM_IPADDRESS: | 3021 | case ISCSI_HOST_PARAM_IPADDRESS: |
2941 | if (!strlen(ihost->local_address)) | 3022 | len = sprintf(buf, "%s\n", ihost->local_address); |
2942 | len = sprintf(buf, "%s\n", "unknown"); | ||
2943 | else | ||
2944 | len = sprintf(buf, "%s\n", | ||
2945 | ihost->local_address); | ||
2946 | break; | 3023 | break; |
2947 | default: | 3024 | default: |
2948 | return -ENOSYS; | 3025 | return -ENOSYS; |
@@ -2959,17 +3036,11 @@ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, | |||
2959 | 3036 | ||
2960 | switch (param) { | 3037 | switch (param) { |
2961 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 3038 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2962 | if (!ihost->netdev) | 3039 | return iscsi_switch_str_param(&ihost->netdev, buf); |
2963 | ihost->netdev = kstrdup(buf, GFP_KERNEL); | ||
2964 | break; | ||
2965 | case ISCSI_HOST_PARAM_HWADDRESS: | 3040 | case ISCSI_HOST_PARAM_HWADDRESS: |
2966 | if (!ihost->hwaddress) | 3041 | return iscsi_switch_str_param(&ihost->hwaddress, buf); |
2967 | ihost->hwaddress = kstrdup(buf, GFP_KERNEL); | ||
2968 | break; | ||
2969 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 3042 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2970 | if (!ihost->initiatorname) | 3043 | return iscsi_switch_str_param(&ihost->initiatorname, buf); |
2971 | ihost->initiatorname = kstrdup(buf, GFP_KERNEL); | ||
2972 | break; | ||
2973 | default: | 3044 | default: |
2974 | return -ENOSYS; | 3045 | return -ENOSYS; |
2975 | } | 3046 | } |