diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 468 |
1 files changed, 241 insertions, 227 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index e72b4ad47d35..59908aead531 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -81,7 +81,8 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn) | |||
81 | struct Scsi_Host *shost = conn->session->host; | 81 | struct Scsi_Host *shost = conn->session->host; |
82 | struct iscsi_host *ihost = shost_priv(shost); | 82 | struct iscsi_host *ihost = shost_priv(shost); |
83 | 83 | ||
84 | queue_work(ihost->workq, &conn->xmitwork); | 84 | if (ihost->workq) |
85 | queue_work(ihost->workq, &conn->xmitwork); | ||
85 | } | 86 | } |
86 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); | 87 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); |
87 | 88 | ||
@@ -109,11 +110,9 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
109 | * if the window closed with IO queued, then kick the | 110 | * if the window closed with IO queued, then kick the |
110 | * xmit thread | 111 | * xmit thread |
111 | */ | 112 | */ |
112 | if (!list_empty(&session->leadconn->xmitqueue) || | 113 | if (!list_empty(&session->leadconn->cmdqueue) || |
113 | !list_empty(&session->leadconn->mgmtqueue)) { | 114 | !list_empty(&session->leadconn->mgmtqueue)) |
114 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 115 | iscsi_conn_queue_work(session->leadconn); |
115 | iscsi_conn_queue_work(session->leadconn); | ||
116 | } | ||
117 | } | 116 | } |
118 | } | 117 | } |
119 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 118 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
@@ -257,9 +256,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
257 | itt_t itt; | 256 | itt_t itt; |
258 | int rc; | 257 | int rc; |
259 | 258 | ||
260 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); | 259 | if (conn->session->tt->alloc_pdu) { |
261 | if (rc) | 260 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); |
262 | return rc; | 261 | if (rc) |
262 | return rc; | ||
263 | } | ||
263 | hdr = (struct iscsi_cmd *) task->hdr; | 264 | hdr = (struct iscsi_cmd *) task->hdr; |
264 | itt = hdr->itt; | 265 | itt = hdr->itt; |
265 | memset(hdr, 0, sizeof(*hdr)); | 266 | memset(hdr, 0, sizeof(*hdr)); |
@@ -364,7 +365,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
364 | return -EIO; | 365 | return -EIO; |
365 | 366 | ||
366 | task->state = ISCSI_TASK_RUNNING; | 367 | task->state = ISCSI_TASK_RUNNING; |
367 | list_move_tail(&task->running, &conn->run_list); | ||
368 | 368 | ||
369 | conn->scsicmd_pdus_cnt++; | 369 | conn->scsicmd_pdus_cnt++; |
370 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " | 370 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " |
@@ -380,26 +380,25 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
380 | } | 380 | } |
381 | 381 | ||
382 | /** | 382 | /** |
383 | * iscsi_complete_command - finish a task | 383 | * iscsi_free_task - free a task |
384 | * @task: iscsi cmd task | 384 | * @task: iscsi cmd task |
385 | * | 385 | * |
386 | * Must be called with session lock. | 386 | * Must be called with session lock. |
387 | * This function returns the scsi command to scsi-ml or cleans | 387 | * This function returns the scsi command to scsi-ml or cleans |
388 | * up mgmt tasks then returns the task to the pool. | 388 | * up mgmt tasks then returns the task to the pool. |
389 | */ | 389 | */ |
390 | static void iscsi_complete_command(struct iscsi_task *task) | 390 | static void iscsi_free_task(struct iscsi_task *task) |
391 | { | 391 | { |
392 | struct iscsi_conn *conn = task->conn; | 392 | struct iscsi_conn *conn = task->conn; |
393 | struct iscsi_session *session = conn->session; | 393 | struct iscsi_session *session = conn->session; |
394 | struct scsi_cmnd *sc = task->sc; | 394 | struct scsi_cmnd *sc = task->sc; |
395 | 395 | ||
396 | ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n", | ||
397 | task->itt, task->state, task->sc); | ||
398 | |||
396 | session->tt->cleanup_task(task); | 399 | session->tt->cleanup_task(task); |
397 | list_del_init(&task->running); | 400 | task->state = ISCSI_TASK_FREE; |
398 | task->state = ISCSI_TASK_COMPLETED; | ||
399 | task->sc = NULL; | 401 | task->sc = NULL; |
400 | |||
401 | if (conn->task == task) | ||
402 | conn->task = NULL; | ||
403 | /* | 402 | /* |
404 | * login task is preallocated so do not free | 403 | * login task is preallocated so do not free |
405 | */ | 404 | */ |
@@ -408,9 +407,6 @@ static void iscsi_complete_command(struct iscsi_task *task) | |||
408 | 407 | ||
409 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); | 408 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); |
410 | 409 | ||
411 | if (conn->ping_task == task) | ||
412 | conn->ping_task = NULL; | ||
413 | |||
414 | if (sc) { | 410 | if (sc) { |
415 | task->sc = NULL; | 411 | task->sc = NULL; |
416 | /* SCSI eh reuses commands to verify us */ | 412 | /* SCSI eh reuses commands to verify us */ |
@@ -433,7 +429,7 @@ EXPORT_SYMBOL_GPL(__iscsi_get_task); | |||
433 | static void __iscsi_put_task(struct iscsi_task *task) | 429 | static void __iscsi_put_task(struct iscsi_task *task) |
434 | { | 430 | { |
435 | if (atomic_dec_and_test(&task->refcount)) | 431 | if (atomic_dec_and_test(&task->refcount)) |
436 | iscsi_complete_command(task); | 432 | iscsi_free_task(task); |
437 | } | 433 | } |
438 | 434 | ||
439 | void iscsi_put_task(struct iscsi_task *task) | 435 | void iscsi_put_task(struct iscsi_task *task) |
@@ -446,26 +442,74 @@ void iscsi_put_task(struct iscsi_task *task) | |||
446 | } | 442 | } |
447 | EXPORT_SYMBOL_GPL(iscsi_put_task); | 443 | EXPORT_SYMBOL_GPL(iscsi_put_task); |
448 | 444 | ||
445 | /** | ||
446 | * iscsi_complete_task - finish a task | ||
447 | * @task: iscsi cmd task | ||
448 | * @state: state to complete task with | ||
449 | * | ||
450 | * Must be called with session lock. | ||
451 | */ | ||
452 | static void iscsi_complete_task(struct iscsi_task *task, int state) | ||
453 | { | ||
454 | struct iscsi_conn *conn = task->conn; | ||
455 | |||
456 | ISCSI_DBG_SESSION(conn->session, | ||
457 | "complete task itt 0x%x state %d sc %p\n", | ||
458 | task->itt, task->state, task->sc); | ||
459 | if (task->state == ISCSI_TASK_COMPLETED || | ||
460 | task->state == ISCSI_TASK_ABRT_TMF || | ||
461 | task->state == ISCSI_TASK_ABRT_SESS_RECOV) | ||
462 | return; | ||
463 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); | ||
464 | task->state = state; | ||
465 | |||
466 | if (!list_empty(&task->running)) | ||
467 | list_del_init(&task->running); | ||
468 | |||
469 | if (conn->task == task) | ||
470 | conn->task = NULL; | ||
471 | |||
472 | if (conn->ping_task == task) | ||
473 | conn->ping_task = NULL; | ||
474 | |||
475 | /* release get from queueing */ | ||
476 | __iscsi_put_task(task); | ||
477 | } | ||
478 | |||
449 | /* | 479 | /* |
450 | * session lock must be held | 480 | * session lock must be held and if not called for a task that is |
481 | * still pending or from the xmit thread, then xmit thread must | ||
482 | * be suspended. | ||
451 | */ | 483 | */ |
452 | static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | 484 | static void fail_scsi_task(struct iscsi_task *task, int err) |
453 | int err) | ||
454 | { | 485 | { |
486 | struct iscsi_conn *conn = task->conn; | ||
455 | struct scsi_cmnd *sc; | 487 | struct scsi_cmnd *sc; |
488 | int state; | ||
456 | 489 | ||
490 | /* | ||
491 | * if a command completes and we get a successful tmf response | ||
492 | * we will hit this because the scsi eh abort code does not take | ||
493 | * a ref to the task. | ||
494 | */ | ||
457 | sc = task->sc; | 495 | sc = task->sc; |
458 | if (!sc) | 496 | if (!sc) |
459 | return; | 497 | return; |
460 | 498 | ||
461 | if (task->state == ISCSI_TASK_PENDING) | 499 | if (task->state == ISCSI_TASK_PENDING) { |
462 | /* | 500 | /* |
463 | * cmd never made it to the xmit thread, so we should not count | 501 | * cmd never made it to the xmit thread, so we should not count |
464 | * the cmd in the sequencing | 502 | * the cmd in the sequencing |
465 | */ | 503 | */ |
466 | conn->session->queued_cmdsn--; | 504 | conn->session->queued_cmdsn--; |
505 | /* it was never sent so just complete like normal */ | ||
506 | state = ISCSI_TASK_COMPLETED; | ||
507 | } else if (err == DID_TRANSPORT_DISRUPTED) | ||
508 | state = ISCSI_TASK_ABRT_SESS_RECOV; | ||
509 | else | ||
510 | state = ISCSI_TASK_ABRT_TMF; | ||
467 | 511 | ||
468 | sc->result = err; | 512 | sc->result = err << 16; |
469 | if (!scsi_bidi_cmnd(sc)) | 513 | if (!scsi_bidi_cmnd(sc)) |
470 | scsi_set_resid(sc, scsi_bufflen(sc)); | 514 | scsi_set_resid(sc, scsi_bufflen(sc)); |
471 | else { | 515 | else { |
@@ -473,10 +517,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | |||
473 | scsi_in(sc)->resid = scsi_in(sc)->length; | 517 | scsi_in(sc)->resid = scsi_in(sc)->length; |
474 | } | 518 | } |
475 | 519 | ||
476 | if (conn->task == task) | 520 | iscsi_complete_task(task, state); |
477 | conn->task = NULL; | ||
478 | /* release ref from queuecommand */ | ||
479 | __iscsi_put_task(task); | ||
480 | } | 521 | } |
481 | 522 | ||
482 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | 523 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
@@ -516,7 +557,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
516 | session->state = ISCSI_STATE_LOGGING_OUT; | 557 | session->state = ISCSI_STATE_LOGGING_OUT; |
517 | 558 | ||
518 | task->state = ISCSI_TASK_RUNNING; | 559 | 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 " | 560 | ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " |
521 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, | 561 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, |
522 | hdr->itt, task->data_count); | 562 | hdr->itt, task->data_count); |
@@ -528,6 +568,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
528 | char *data, uint32_t data_size) | 568 | char *data, uint32_t data_size) |
529 | { | 569 | { |
530 | struct iscsi_session *session = conn->session; | 570 | struct iscsi_session *session = conn->session; |
571 | struct iscsi_host *ihost = shost_priv(session->host); | ||
531 | struct iscsi_task *task; | 572 | struct iscsi_task *task; |
532 | itt_t itt; | 573 | itt_t itt; |
533 | 574 | ||
@@ -544,6 +585,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
544 | */ | 585 | */ |
545 | task = conn->login_task; | 586 | task = conn->login_task; |
546 | else { | 587 | else { |
588 | if (session->state != ISCSI_STATE_LOGGED_IN) | ||
589 | return NULL; | ||
590 | |||
547 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); | 591 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); |
548 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); | 592 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
549 | 593 | ||
@@ -559,6 +603,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
559 | atomic_set(&task->refcount, 1); | 603 | atomic_set(&task->refcount, 1); |
560 | task->conn = conn; | 604 | task->conn = conn; |
561 | task->sc = NULL; | 605 | task->sc = NULL; |
606 | INIT_LIST_HEAD(&task->running); | ||
607 | task->state = ISCSI_TASK_PENDING; | ||
562 | 608 | ||
563 | if (data_size) { | 609 | if (data_size) { |
564 | memcpy(task->data, data, data_size); | 610 | memcpy(task->data, data, data_size); |
@@ -566,11 +612,14 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
566 | } else | 612 | } else |
567 | task->data_count = 0; | 613 | task->data_count = 0; |
568 | 614 | ||
569 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { | 615 | if (conn->session->tt->alloc_pdu) { |
570 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " | 616 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { |
571 | "pdu for mgmt task.\n"); | 617 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " |
572 | goto requeue_task; | 618 | "pdu for mgmt task.\n"); |
619 | goto free_task; | ||
620 | } | ||
573 | } | 621 | } |
622 | |||
574 | itt = task->hdr->itt; | 623 | itt = task->hdr->itt; |
575 | task->hdr_len = sizeof(struct iscsi_hdr); | 624 | task->hdr_len = sizeof(struct iscsi_hdr); |
576 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | 625 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
@@ -583,30 +632,22 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
583 | task->conn->session->age); | 632 | task->conn->session->age); |
584 | } | 633 | } |
585 | 634 | ||
586 | INIT_LIST_HEAD(&task->running); | 635 | 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)) | 636 | if (iscsi_prep_mgmt_task(conn, task)) |
591 | goto free_task; | 637 | goto free_task; |
592 | 638 | ||
593 | if (session->tt->xmit_task(task)) | 639 | if (session->tt->xmit_task(task)) |
594 | goto free_task; | 640 | goto free_task; |
595 | 641 | } else { | |
596 | } else | 642 | list_add_tail(&task->running, &conn->mgmtqueue); |
597 | iscsi_conn_queue_work(conn); | 643 | iscsi_conn_queue_work(conn); |
644 | } | ||
598 | 645 | ||
599 | return task; | 646 | return task; |
600 | 647 | ||
601 | free_task: | 648 | free_task: |
602 | __iscsi_put_task(task); | 649 | __iscsi_put_task(task); |
603 | return NULL; | 650 | 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 | } | 651 | } |
611 | 652 | ||
612 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 653 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -701,11 +742,10 @@ invalid_datalen: | |||
701 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 742 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
702 | } | 743 | } |
703 | out: | 744 | out: |
704 | ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n", | 745 | ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n", |
705 | sc, sc->result, task->itt); | 746 | sc, sc->result, task->itt); |
706 | conn->scsirsp_pdus_cnt++; | 747 | conn->scsirsp_pdus_cnt++; |
707 | 748 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | |
708 | __iscsi_put_task(task); | ||
709 | } | 749 | } |
710 | 750 | ||
711 | /** | 751 | /** |
@@ -724,6 +764,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
724 | if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS)) | 764 | if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS)) |
725 | return; | 765 | return; |
726 | 766 | ||
767 | iscsi_update_cmdsn(conn->session, (struct iscsi_nopin *)hdr); | ||
727 | sc->result = (DID_OK << 16) | rhdr->cmd_status; | 768 | sc->result = (DID_OK << 16) | rhdr->cmd_status; |
728 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; | 769 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; |
729 | if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW | | 770 | if (rhdr->flags & (ISCSI_FLAG_DATA_UNDERFLOW | |
@@ -738,8 +779,11 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
738 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 779 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
739 | } | 780 | } |
740 | 781 | ||
782 | ISCSI_DBG_SESSION(conn->session, "data in with status done " | ||
783 | "[sc %p res %d itt 0x%x]\n", | ||
784 | sc, sc->result, task->itt); | ||
741 | conn->scsirsp_pdus_cnt++; | 785 | conn->scsirsp_pdus_cnt++; |
742 | __iscsi_put_task(task); | 786 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
743 | } | 787 | } |
744 | 788 | ||
745 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 789 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) |
@@ -823,7 +867,7 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
823 | * | 867 | * |
824 | * The session lock must be held. | 868 | * The session lock must be held. |
825 | */ | 869 | */ |
826 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | 870 | struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
827 | { | 871 | { |
828 | struct iscsi_session *session = conn->session; | 872 | struct iscsi_session *session = conn->session; |
829 | int i; | 873 | int i; |
@@ -840,6 +884,7 @@ static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | |||
840 | 884 | ||
841 | return session->cmds[i]; | 885 | return session->cmds[i]; |
842 | } | 886 | } |
887 | EXPORT_SYMBOL_GPL(iscsi_itt_to_task); | ||
843 | 888 | ||
844 | /** | 889 | /** |
845 | * __iscsi_complete_pdu - complete pdu | 890 | * __iscsi_complete_pdu - complete pdu |
@@ -959,7 +1004,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
959 | } | 1004 | } |
960 | 1005 | ||
961 | iscsi_tmf_rsp(conn, hdr); | 1006 | iscsi_tmf_rsp(conn, hdr); |
962 | __iscsi_put_task(task); | 1007 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
963 | break; | 1008 | break; |
964 | case ISCSI_OP_NOOP_IN: | 1009 | case ISCSI_OP_NOOP_IN: |
965 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 1010 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
@@ -977,7 +1022,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
977 | goto recv_pdu; | 1022 | goto recv_pdu; |
978 | 1023 | ||
979 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | 1024 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); |
980 | __iscsi_put_task(task); | 1025 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
981 | break; | 1026 | break; |
982 | default: | 1027 | default: |
983 | rc = ISCSI_ERR_BAD_OPCODE; | 1028 | rc = ISCSI_ERR_BAD_OPCODE; |
@@ -989,7 +1034,7 @@ out: | |||
989 | recv_pdu: | 1034 | recv_pdu: |
990 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | 1035 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
991 | rc = ISCSI_ERR_CONN_FAILED; | 1036 | rc = ISCSI_ERR_CONN_FAILED; |
992 | __iscsi_put_task(task); | 1037 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
993 | return rc; | 1038 | return rc; |
994 | } | 1039 | } |
995 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); | 1040 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); |
@@ -1166,7 +1211,12 @@ void iscsi_requeue_task(struct iscsi_task *task) | |||
1166 | { | 1211 | { |
1167 | struct iscsi_conn *conn = task->conn; | 1212 | struct iscsi_conn *conn = task->conn; |
1168 | 1213 | ||
1169 | list_move_tail(&task->running, &conn->requeue); | 1214 | /* |
1215 | * this may be on the requeue list already if the xmit_task callout | ||
1216 | * is handling the r2ts while we are adding new ones | ||
1217 | */ | ||
1218 | if (list_empty(&task->running)) | ||
1219 | list_add_tail(&task->running, &conn->requeue); | ||
1170 | iscsi_conn_queue_work(conn); | 1220 | iscsi_conn_queue_work(conn); |
1171 | } | 1221 | } |
1172 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); | 1222 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
@@ -1206,6 +1256,7 @@ check_mgmt: | |||
1206 | while (!list_empty(&conn->mgmtqueue)) { | 1256 | while (!list_empty(&conn->mgmtqueue)) { |
1207 | conn->task = list_entry(conn->mgmtqueue.next, | 1257 | conn->task = list_entry(conn->mgmtqueue.next, |
1208 | struct iscsi_task, running); | 1258 | struct iscsi_task, running); |
1259 | list_del_init(&conn->task->running); | ||
1209 | if (iscsi_prep_mgmt_task(conn, conn->task)) { | 1260 | if (iscsi_prep_mgmt_task(conn, conn->task)) { |
1210 | __iscsi_put_task(conn->task); | 1261 | __iscsi_put_task(conn->task); |
1211 | conn->task = NULL; | 1262 | conn->task = NULL; |
@@ -1217,23 +1268,26 @@ check_mgmt: | |||
1217 | } | 1268 | } |
1218 | 1269 | ||
1219 | /* process pending command queue */ | 1270 | /* process pending command queue */ |
1220 | while (!list_empty(&conn->xmitqueue)) { | 1271 | while (!list_empty(&conn->cmdqueue)) { |
1221 | if (conn->tmf_state == TMF_QUEUED) | 1272 | if (conn->tmf_state == TMF_QUEUED) |
1222 | break; | 1273 | break; |
1223 | 1274 | ||
1224 | conn->task = list_entry(conn->xmitqueue.next, | 1275 | conn->task = list_entry(conn->cmdqueue.next, |
1225 | struct iscsi_task, running); | 1276 | struct iscsi_task, running); |
1277 | list_del_init(&conn->task->running); | ||
1226 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1278 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1227 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); | 1279 | fail_scsi_task(conn->task, DID_IMM_RETRY); |
1228 | continue; | 1280 | continue; |
1229 | } | 1281 | } |
1230 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); | 1282 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1231 | if (rc) { | 1283 | if (rc) { |
1232 | if (rc == -ENOMEM) { | 1284 | if (rc == -ENOMEM) { |
1285 | list_add_tail(&conn->task->running, | ||
1286 | &conn->cmdqueue); | ||
1233 | conn->task = NULL; | 1287 | conn->task = NULL; |
1234 | goto again; | 1288 | goto again; |
1235 | } else | 1289 | } else |
1236 | fail_command(conn, conn->task, DID_ABORT << 16); | 1290 | fail_scsi_task(conn->task, DID_ABORT); |
1237 | continue; | 1291 | continue; |
1238 | } | 1292 | } |
1239 | rc = iscsi_xmit_task(conn); | 1293 | rc = iscsi_xmit_task(conn); |
@@ -1260,8 +1314,8 @@ check_mgmt: | |||
1260 | 1314 | ||
1261 | conn->task = list_entry(conn->requeue.next, | 1315 | conn->task = list_entry(conn->requeue.next, |
1262 | struct iscsi_task, running); | 1316 | struct iscsi_task, running); |
1317 | list_del_init(&conn->task->running); | ||
1263 | conn->task->state = ISCSI_TASK_RUNNING; | 1318 | conn->task->state = ISCSI_TASK_RUNNING; |
1264 | list_move_tail(conn->requeue.next, &conn->run_list); | ||
1265 | rc = iscsi_xmit_task(conn); | 1319 | rc = iscsi_xmit_task(conn); |
1266 | if (rc) | 1320 | if (rc) |
1267 | goto again; | 1321 | goto again; |
@@ -1328,6 +1382,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1328 | { | 1382 | { |
1329 | struct iscsi_cls_session *cls_session; | 1383 | struct iscsi_cls_session *cls_session; |
1330 | struct Scsi_Host *host; | 1384 | struct Scsi_Host *host; |
1385 | struct iscsi_host *ihost; | ||
1331 | int reason = 0; | 1386 | int reason = 0; |
1332 | struct iscsi_session *session; | 1387 | struct iscsi_session *session; |
1333 | struct iscsi_conn *conn; | 1388 | struct iscsi_conn *conn; |
@@ -1338,6 +1393,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1338 | sc->SCp.ptr = NULL; | 1393 | sc->SCp.ptr = NULL; |
1339 | 1394 | ||
1340 | host = sc->device->host; | 1395 | host = sc->device->host; |
1396 | ihost = shost_priv(host); | ||
1341 | spin_unlock(host->host_lock); | 1397 | spin_unlock(host->host_lock); |
1342 | 1398 | ||
1343 | cls_session = starget_to_session(scsi_target(sc->device)); | 1399 | cls_session = starget_to_session(scsi_target(sc->device)); |
@@ -1350,13 +1406,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1350 | goto fault; | 1406 | goto fault; |
1351 | } | 1407 | } |
1352 | 1408 | ||
1353 | /* | 1409 | 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 | /* | 1410 | /* |
1361 | * to handle the race between when we set the recovery state | 1411 | * to handle the race between when we set the recovery state |
1362 | * and block the session we requeue here (commands could | 1412 | * and block the session we requeue here (commands could |
@@ -1364,12 +1414,15 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1364 | * up because the block code is not locked) | 1414 | * up because the block code is not locked) |
1365 | */ | 1415 | */ |
1366 | switch (session->state) { | 1416 | switch (session->state) { |
1417 | case ISCSI_STATE_FAILED: | ||
1367 | case ISCSI_STATE_IN_RECOVERY: | 1418 | case ISCSI_STATE_IN_RECOVERY: |
1368 | reason = FAILURE_SESSION_IN_RECOVERY; | 1419 | reason = FAILURE_SESSION_IN_RECOVERY; |
1369 | goto reject; | 1420 | sc->result = DID_IMM_RETRY << 16; |
1421 | break; | ||
1370 | case ISCSI_STATE_LOGGING_OUT: | 1422 | case ISCSI_STATE_LOGGING_OUT: |
1371 | reason = FAILURE_SESSION_LOGGING_OUT; | 1423 | reason = FAILURE_SESSION_LOGGING_OUT; |
1372 | goto reject; | 1424 | sc->result = DID_IMM_RETRY << 16; |
1425 | break; | ||
1373 | case ISCSI_STATE_RECOVERY_FAILED: | 1426 | case ISCSI_STATE_RECOVERY_FAILED: |
1374 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; | 1427 | reason = FAILURE_SESSION_RECOVERY_TIMEOUT; |
1375 | sc->result = DID_TRANSPORT_FAILFAST << 16; | 1428 | sc->result = DID_TRANSPORT_FAILFAST << 16; |
@@ -1402,9 +1455,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1402 | reason = FAILURE_OOM; | 1455 | reason = FAILURE_OOM; |
1403 | goto reject; | 1456 | goto reject; |
1404 | } | 1457 | } |
1405 | list_add_tail(&task->running, &conn->xmitqueue); | ||
1406 | 1458 | ||
1407 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 1459 | if (!ihost->workq) { |
1408 | reason = iscsi_prep_scsi_cmd_pdu(task); | 1460 | reason = iscsi_prep_scsi_cmd_pdu(task); |
1409 | if (reason) { | 1461 | if (reason) { |
1410 | if (reason == -ENOMEM) { | 1462 | if (reason == -ENOMEM) { |
@@ -1419,8 +1471,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1419 | reason = FAILURE_SESSION_NOT_READY; | 1471 | reason = FAILURE_SESSION_NOT_READY; |
1420 | goto prepd_reject; | 1472 | goto prepd_reject; |
1421 | } | 1473 | } |
1422 | } else | 1474 | } else { |
1475 | list_add_tail(&task->running, &conn->cmdqueue); | ||
1423 | iscsi_conn_queue_work(conn); | 1476 | iscsi_conn_queue_work(conn); |
1477 | } | ||
1424 | 1478 | ||
1425 | session->queued_cmdsn++; | 1479 | session->queued_cmdsn++; |
1426 | spin_unlock(&session->lock); | 1480 | spin_unlock(&session->lock); |
@@ -1429,7 +1483,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1429 | 1483 | ||
1430 | prepd_reject: | 1484 | prepd_reject: |
1431 | sc->scsi_done = NULL; | 1485 | sc->scsi_done = NULL; |
1432 | iscsi_complete_command(task); | 1486 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
1433 | reject: | 1487 | reject: |
1434 | spin_unlock(&session->lock); | 1488 | spin_unlock(&session->lock); |
1435 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", | 1489 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", |
@@ -1439,7 +1493,7 @@ reject: | |||
1439 | 1493 | ||
1440 | prepd_fault: | 1494 | prepd_fault: |
1441 | sc->scsi_done = NULL; | 1495 | sc->scsi_done = NULL; |
1442 | iscsi_complete_command(task); | 1496 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); |
1443 | fault: | 1497 | fault: |
1444 | spin_unlock(&session->lock); | 1498 | spin_unlock(&session->lock); |
1445 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", | 1499 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", |
@@ -1608,44 +1662,24 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1608 | * Fail commands. session lock held and recv side suspended and xmit | 1662 | * Fail commands. session lock held and recv side suspended and xmit |
1609 | * thread flushed | 1663 | * thread flushed |
1610 | */ | 1664 | */ |
1611 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | 1665 | static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, |
1612 | int error) | 1666 | int error) |
1613 | { | 1667 | { |
1614 | struct iscsi_task *task, *tmp; | 1668 | struct iscsi_task *task; |
1615 | 1669 | 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 | 1670 | ||
1622 | /* flush pending */ | 1671 | for (i = 0; i < conn->session->cmds_max; i++) { |
1623 | list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { | 1672 | task = conn->session->cmds[i]; |
1624 | if (lun == task->sc->device->lun || lun == -1) { | 1673 | if (!task->sc || task->state == ISCSI_TASK_FREE) |
1625 | ISCSI_DBG_SESSION(conn->session, | 1674 | 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 | 1675 | ||
1632 | list_for_each_entry_safe(task, tmp, &conn->requeue, running) { | 1676 | if (lun != -1 && lun != task->sc->device->lun) |
1633 | if (lun == task->sc->device->lun || lun == -1) { | 1677 | 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 | 1678 | ||
1641 | /* fail all other running */ | 1679 | ISCSI_DBG_SESSION(conn->session, |
1642 | list_for_each_entry_safe(task, tmp, &conn->run_list, running) { | 1680 | "failing sc %p itt 0x%x state %d\n", |
1643 | if (lun == task->sc->device->lun || lun == -1) { | 1681 | task->sc, task->itt, task->state); |
1644 | ISCSI_DBG_SESSION(conn->session, | 1682 | 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 | } | 1683 | } |
1650 | } | 1684 | } |
1651 | 1685 | ||
@@ -1655,7 +1689,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn) | |||
1655 | struct iscsi_host *ihost = shost_priv(shost); | 1689 | struct iscsi_host *ihost = shost_priv(shost); |
1656 | 1690 | ||
1657 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1691 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1658 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1692 | if (ihost->workq) |
1659 | flush_workqueue(ihost->workq); | 1693 | flush_workqueue(ihost->workq); |
1660 | } | 1694 | } |
1661 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | 1695 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); |
@@ -1663,8 +1697,23 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | |||
1663 | static void iscsi_start_tx(struct iscsi_conn *conn) | 1697 | static void iscsi_start_tx(struct iscsi_conn *conn) |
1664 | { | 1698 | { |
1665 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1699 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1666 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1700 | iscsi_conn_queue_work(conn); |
1667 | iscsi_conn_queue_work(conn); | 1701 | } |
1702 | |||
1703 | /* | ||
1704 | * We want to make sure a ping is in flight. It has timed out. | ||
1705 | * And we are not busy processing a pdu that is making | ||
1706 | * progress but got started before the ping and is taking a while | ||
1707 | * to complete so the ping is just stuck behind it in a queue. | ||
1708 | */ | ||
1709 | static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) | ||
1710 | { | ||
1711 | if (conn->ping_task && | ||
1712 | time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + | ||
1713 | (conn->ping_timeout * HZ), jiffies)) | ||
1714 | return 1; | ||
1715 | else | ||
1716 | return 0; | ||
1668 | } | 1717 | } |
1669 | 1718 | ||
1670 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1719 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) |
@@ -1702,16 +1751,20 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | |||
1702 | * if the ping timedout then we are in the middle of cleaning up | 1751 | * if the ping timedout then we are in the middle of cleaning up |
1703 | * and can let the iscsi eh handle it | 1752 | * and can let the iscsi eh handle it |
1704 | */ | 1753 | */ |
1705 | if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + | 1754 | if (iscsi_has_ping_timed_out(conn)) { |
1706 | (conn->ping_timeout * HZ), jiffies)) | ||
1707 | rc = BLK_EH_RESET_TIMER; | 1755 | rc = BLK_EH_RESET_TIMER; |
1756 | goto done; | ||
1757 | } | ||
1708 | /* | 1758 | /* |
1709 | * if we are about to check the transport then give the command | 1759 | * if we are about to check the transport then give the command |
1710 | * more time | 1760 | * more time |
1711 | */ | 1761 | */ |
1712 | if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), | 1762 | if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), |
1713 | jiffies)) | 1763 | jiffies)) { |
1714 | rc = BLK_EH_RESET_TIMER; | 1764 | rc = BLK_EH_RESET_TIMER; |
1765 | goto done; | ||
1766 | } | ||
1767 | |||
1715 | /* if in the middle of checking the transport then give us more time */ | 1768 | /* if in the middle of checking the transport then give us more time */ |
1716 | if (conn->ping_task) | 1769 | if (conn->ping_task) |
1717 | rc = BLK_EH_RESET_TIMER; | 1770 | rc = BLK_EH_RESET_TIMER; |
@@ -1738,13 +1791,13 @@ static void iscsi_check_transport_timeouts(unsigned long data) | |||
1738 | 1791 | ||
1739 | recv_timeout *= HZ; | 1792 | recv_timeout *= HZ; |
1740 | last_recv = conn->last_recv; | 1793 | last_recv = conn->last_recv; |
1741 | if (conn->ping_task && | 1794 | |
1742 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), | 1795 | if (iscsi_has_ping_timed_out(conn)) { |
1743 | jiffies)) { | ||
1744 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " | 1796 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " |
1745 | "expired, last rx %lu, last ping %lu, " | 1797 | "expired, recv timeout %d, last rx %lu, " |
1746 | "now %lu\n", conn->ping_timeout, last_recv, | 1798 | "last ping %lu, now %lu\n", |
1747 | conn->last_ping, jiffies); | 1799 | conn->ping_timeout, conn->recv_timeout, |
1800 | last_recv, conn->last_ping, jiffies); | ||
1748 | spin_unlock(&session->lock); | 1801 | spin_unlock(&session->lock); |
1749 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1802 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1750 | return; | 1803 | return; |
@@ -1788,6 +1841,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1788 | cls_session = starget_to_session(scsi_target(sc->device)); | 1841 | cls_session = starget_to_session(scsi_target(sc->device)); |
1789 | session = cls_session->dd_data; | 1842 | session = cls_session->dd_data; |
1790 | 1843 | ||
1844 | ISCSI_DBG_SESSION(session, "aborting sc %p\n", sc); | ||
1845 | |||
1791 | mutex_lock(&session->eh_mutex); | 1846 | mutex_lock(&session->eh_mutex); |
1792 | spin_lock_bh(&session->lock); | 1847 | spin_lock_bh(&session->lock); |
1793 | /* | 1848 | /* |
@@ -1810,6 +1865,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1810 | sc->SCp.phase != session->age) { | 1865 | sc->SCp.phase != session->age) { |
1811 | spin_unlock_bh(&session->lock); | 1866 | spin_unlock_bh(&session->lock); |
1812 | mutex_unlock(&session->eh_mutex); | 1867 | mutex_unlock(&session->eh_mutex); |
1868 | ISCSI_DBG_SESSION(session, "failing abort due to dropped " | ||
1869 | "session.\n"); | ||
1813 | return FAILED; | 1870 | return FAILED; |
1814 | } | 1871 | } |
1815 | 1872 | ||
@@ -1829,7 +1886,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1829 | } | 1886 | } |
1830 | 1887 | ||
1831 | if (task->state == ISCSI_TASK_PENDING) { | 1888 | if (task->state == ISCSI_TASK_PENDING) { |
1832 | fail_command(conn, task, DID_ABORT << 16); | 1889 | fail_scsi_task(task, DID_ABORT); |
1833 | goto success; | 1890 | goto success; |
1834 | } | 1891 | } |
1835 | 1892 | ||
@@ -1860,7 +1917,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1860 | * then sent more data for the cmd. | 1917 | * then sent more data for the cmd. |
1861 | */ | 1918 | */ |
1862 | spin_lock(&session->lock); | 1919 | spin_lock(&session->lock); |
1863 | fail_command(conn, task, DID_ABORT << 16); | 1920 | fail_scsi_task(task, DID_ABORT); |
1864 | conn->tmf_state = TMF_INITIAL; | 1921 | conn->tmf_state = TMF_INITIAL; |
1865 | spin_unlock(&session->lock); | 1922 | spin_unlock(&session->lock); |
1866 | iscsi_start_tx(conn); | 1923 | iscsi_start_tx(conn); |
@@ -1967,7 +2024,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1967 | iscsi_suspend_tx(conn); | 2024 | iscsi_suspend_tx(conn); |
1968 | 2025 | ||
1969 | spin_lock_bh(&session->lock); | 2026 | spin_lock_bh(&session->lock); |
1970 | fail_all_commands(conn, sc->device->lun, DID_ERROR); | 2027 | fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); |
1971 | conn->tmf_state = TMF_INITIAL; | 2028 | conn->tmf_state = TMF_INITIAL; |
1972 | spin_unlock_bh(&session->lock); | 2029 | spin_unlock_bh(&session->lock); |
1973 | 2030 | ||
@@ -2274,6 +2331,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2274 | if (cmd_task_size) | 2331 | if (cmd_task_size) |
2275 | task->dd_data = &task[1]; | 2332 | task->dd_data = &task[1]; |
2276 | task->itt = cmd_i; | 2333 | task->itt = cmd_i; |
2334 | task->state = ISCSI_TASK_FREE; | ||
2277 | INIT_LIST_HEAD(&task->running); | 2335 | INIT_LIST_HEAD(&task->running); |
2278 | } | 2336 | } |
2279 | 2337 | ||
@@ -2360,10 +2418,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2360 | conn->transport_timer.data = (unsigned long)conn; | 2418 | conn->transport_timer.data = (unsigned long)conn; |
2361 | conn->transport_timer.function = iscsi_check_transport_timeouts; | 2419 | conn->transport_timer.function = iscsi_check_transport_timeouts; |
2362 | 2420 | ||
2363 | INIT_LIST_HEAD(&conn->run_list); | ||
2364 | INIT_LIST_HEAD(&conn->mgmt_run_list); | ||
2365 | INIT_LIST_HEAD(&conn->mgmtqueue); | 2421 | INIT_LIST_HEAD(&conn->mgmtqueue); |
2366 | INIT_LIST_HEAD(&conn->xmitqueue); | 2422 | INIT_LIST_HEAD(&conn->cmdqueue); |
2367 | INIT_LIST_HEAD(&conn->requeue); | 2423 | INIT_LIST_HEAD(&conn->requeue); |
2368 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2424 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
2369 | 2425 | ||
@@ -2531,27 +2587,28 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2531 | EXPORT_SYMBOL_GPL(iscsi_conn_start); | 2587 | EXPORT_SYMBOL_GPL(iscsi_conn_start); |
2532 | 2588 | ||
2533 | static void | 2589 | static void |
2534 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | 2590 | fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) |
2535 | { | 2591 | { |
2536 | struct iscsi_task *task, *tmp; | 2592 | struct iscsi_task *task; |
2593 | int i, state; | ||
2537 | 2594 | ||
2538 | /* handle pending */ | 2595 | for (i = 0; i < conn->session->cmds_max; i++) { |
2539 | list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) { | 2596 | task = conn->session->cmds[i]; |
2540 | ISCSI_DBG_SESSION(session, "flushing pending mgmt task " | 2597 | if (task->sc) |
2541 | "itt 0x%x\n", task->itt); | 2598 | continue; |
2542 | /* release ref from prep task */ | ||
2543 | __iscsi_put_task(task); | ||
2544 | } | ||
2545 | 2599 | ||
2546 | /* handle running */ | 2600 | if (task->state == ISCSI_TASK_FREE) |
2547 | list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) { | 2601 | continue; |
2548 | ISCSI_DBG_SESSION(session, "flushing running mgmt task " | 2602 | |
2549 | "itt 0x%x\n", task->itt); | 2603 | ISCSI_DBG_SESSION(conn->session, |
2550 | /* release ref from prep task */ | 2604 | "failing mgmt itt 0x%x state %d\n", |
2551 | __iscsi_put_task(task); | 2605 | task->itt, task->state); |
2552 | } | 2606 | state = ISCSI_TASK_ABRT_SESS_RECOV; |
2607 | if (task->state == ISCSI_TASK_PENDING) | ||
2608 | state = ISCSI_TASK_COMPLETED; | ||
2609 | iscsi_complete_task(task, state); | ||
2553 | 2610 | ||
2554 | conn->task = NULL; | 2611 | } |
2555 | } | 2612 | } |
2556 | 2613 | ||
2557 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 2614 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
@@ -2559,8 +2616,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2559 | { | 2616 | { |
2560 | int old_stop_stage; | 2617 | int old_stop_stage; |
2561 | 2618 | ||
2562 | del_timer_sync(&conn->transport_timer); | ||
2563 | |||
2564 | mutex_lock(&session->eh_mutex); | 2619 | mutex_lock(&session->eh_mutex); |
2565 | spin_lock_bh(&session->lock); | 2620 | spin_lock_bh(&session->lock); |
2566 | if (conn->stop_stage == STOP_CONN_TERM) { | 2621 | if (conn->stop_stage == STOP_CONN_TERM) { |
@@ -2578,13 +2633,17 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2578 | session->state = ISCSI_STATE_TERMINATE; | 2633 | session->state = ISCSI_STATE_TERMINATE; |
2579 | else if (conn->stop_stage != STOP_CONN_RECOVER) | 2634 | else if (conn->stop_stage != STOP_CONN_RECOVER) |
2580 | session->state = ISCSI_STATE_IN_RECOVERY; | 2635 | session->state = ISCSI_STATE_IN_RECOVERY; |
2636 | spin_unlock_bh(&session->lock); | ||
2637 | |||
2638 | del_timer_sync(&conn->transport_timer); | ||
2639 | iscsi_suspend_tx(conn); | ||
2581 | 2640 | ||
2641 | spin_lock_bh(&session->lock); | ||
2582 | old_stop_stage = conn->stop_stage; | 2642 | old_stop_stage = conn->stop_stage; |
2583 | conn->stop_stage = flag; | 2643 | conn->stop_stage = flag; |
2584 | conn->c_stage = ISCSI_CONN_STOPPED; | 2644 | conn->c_stage = ISCSI_CONN_STOPPED; |
2585 | spin_unlock_bh(&session->lock); | 2645 | spin_unlock_bh(&session->lock); |
2586 | 2646 | ||
2587 | iscsi_suspend_tx(conn); | ||
2588 | /* | 2647 | /* |
2589 | * for connection level recovery we should not calculate | 2648 | * for connection level recovery we should not calculate |
2590 | * header digest. conn->hdr_size used for optimization | 2649 | * header digest. conn->hdr_size used for optimization |
@@ -2605,11 +2664,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2605 | * flush queues. | 2664 | * flush queues. |
2606 | */ | 2665 | */ |
2607 | spin_lock_bh(&session->lock); | 2666 | spin_lock_bh(&session->lock); |
2608 | if (flag == STOP_CONN_RECOVER) | 2667 | fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); |
2609 | fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED); | 2668 | 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); | 2669 | spin_unlock_bh(&session->lock); |
2614 | mutex_unlock(&session->eh_mutex); | 2670 | mutex_unlock(&session->eh_mutex); |
2615 | } | 2671 | } |
@@ -2651,6 +2707,23 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
2651 | } | 2707 | } |
2652 | EXPORT_SYMBOL_GPL(iscsi_conn_bind); | 2708 | EXPORT_SYMBOL_GPL(iscsi_conn_bind); |
2653 | 2709 | ||
2710 | static int iscsi_switch_str_param(char **param, char *new_val_buf) | ||
2711 | { | ||
2712 | char *new_val; | ||
2713 | |||
2714 | if (*param) { | ||
2715 | if (!strcmp(*param, new_val_buf)) | ||
2716 | return 0; | ||
2717 | } | ||
2718 | |||
2719 | new_val = kstrdup(new_val_buf, GFP_NOIO); | ||
2720 | if (!new_val) | ||
2721 | return -ENOMEM; | ||
2722 | |||
2723 | kfree(*param); | ||
2724 | *param = new_val; | ||
2725 | return 0; | ||
2726 | } | ||
2654 | 2727 | ||
2655 | int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | 2728 | int iscsi_set_param(struct iscsi_cls_conn *cls_conn, |
2656 | enum iscsi_param param, char *buf, int buflen) | 2729 | enum iscsi_param param, char *buf, int buflen) |
@@ -2723,38 +2796,15 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2723 | sscanf(buf, "%u", &conn->exp_statsn); | 2796 | sscanf(buf, "%u", &conn->exp_statsn); |
2724 | break; | 2797 | break; |
2725 | case ISCSI_PARAM_USERNAME: | 2798 | case ISCSI_PARAM_USERNAME: |
2726 | kfree(session->username); | 2799 | 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: | 2800 | case ISCSI_PARAM_USERNAME_IN: |
2732 | kfree(session->username_in); | 2801 | 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: | 2802 | case ISCSI_PARAM_PASSWORD: |
2738 | kfree(session->password); | 2803 | 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: | 2804 | case ISCSI_PARAM_PASSWORD_IN: |
2744 | kfree(session->password_in); | 2805 | 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: | 2806 | case ISCSI_PARAM_TARGET_NAME: |
2750 | /* this should not change between logins */ | 2807 | 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: | 2808 | case ISCSI_PARAM_TPGT: |
2759 | sscanf(buf, "%d", &session->tpgt); | 2809 | sscanf(buf, "%d", &session->tpgt); |
2760 | break; | 2810 | break; |
@@ -2762,25 +2812,11 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2762 | sscanf(buf, "%d", &conn->persistent_port); | 2812 | sscanf(buf, "%d", &conn->persistent_port); |
2763 | break; | 2813 | break; |
2764 | case ISCSI_PARAM_PERSISTENT_ADDRESS: | 2814 | case ISCSI_PARAM_PERSISTENT_ADDRESS: |
2765 | /* | 2815 | 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: | 2816 | case ISCSI_PARAM_IFACE_NAME: |
2777 | if (!session->ifacename) | 2817 | return iscsi_switch_str_param(&session->ifacename, buf); |
2778 | session->ifacename = kstrdup(buf, GFP_KERNEL); | ||
2779 | break; | ||
2780 | case ISCSI_PARAM_INITIATOR_NAME: | 2818 | case ISCSI_PARAM_INITIATOR_NAME: |
2781 | if (!session->initiatorname) | 2819 | return iscsi_switch_str_param(&session->initiatorname, buf); |
2782 | session->initiatorname = kstrdup(buf, GFP_KERNEL); | ||
2783 | break; | ||
2784 | default: | 2820 | default: |
2785 | return -ENOSYS; | 2821 | return -ENOSYS; |
2786 | } | 2822 | } |
@@ -2851,10 +2887,7 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
2851 | len = sprintf(buf, "%s\n", session->ifacename); | 2887 | len = sprintf(buf, "%s\n", session->ifacename); |
2852 | break; | 2888 | break; |
2853 | case ISCSI_PARAM_INITIATOR_NAME: | 2889 | case ISCSI_PARAM_INITIATOR_NAME: |
2854 | if (!session->initiatorname) | 2890 | 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; | 2891 | break; |
2859 | default: | 2892 | default: |
2860 | return -ENOSYS; | 2893 | return -ENOSYS; |
@@ -2920,29 +2953,16 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, | |||
2920 | 2953 | ||
2921 | switch (param) { | 2954 | switch (param) { |
2922 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 2955 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2923 | if (!ihost->netdev) | 2956 | 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; | 2957 | break; |
2928 | case ISCSI_HOST_PARAM_HWADDRESS: | 2958 | case ISCSI_HOST_PARAM_HWADDRESS: |
2929 | if (!ihost->hwaddress) | 2959 | 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; | 2960 | break; |
2934 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 2961 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2935 | if (!ihost->initiatorname) | 2962 | 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; | 2963 | break; |
2940 | case ISCSI_HOST_PARAM_IPADDRESS: | 2964 | case ISCSI_HOST_PARAM_IPADDRESS: |
2941 | if (!strlen(ihost->local_address)) | 2965 | 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; | 2966 | break; |
2947 | default: | 2967 | default: |
2948 | return -ENOSYS; | 2968 | return -ENOSYS; |
@@ -2959,17 +2979,11 @@ int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, | |||
2959 | 2979 | ||
2960 | switch (param) { | 2980 | switch (param) { |
2961 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 2981 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2962 | if (!ihost->netdev) | 2982 | return iscsi_switch_str_param(&ihost->netdev, buf); |
2963 | ihost->netdev = kstrdup(buf, GFP_KERNEL); | ||
2964 | break; | ||
2965 | case ISCSI_HOST_PARAM_HWADDRESS: | 2983 | case ISCSI_HOST_PARAM_HWADDRESS: |
2966 | if (!ihost->hwaddress) | 2984 | return iscsi_switch_str_param(&ihost->hwaddress, buf); |
2967 | ihost->hwaddress = kstrdup(buf, GFP_KERNEL); | ||
2968 | break; | ||
2969 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 2985 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2970 | if (!ihost->initiatorname) | 2986 | return iscsi_switch_str_param(&ihost->initiatorname, buf); |
2971 | ihost->initiatorname = kstrdup(buf, GFP_KERNEL); | ||
2972 | break; | ||
2973 | default: | 2987 | default: |
2974 | return -ENOSYS; | 2988 | return -ENOSYS; |
2975 | } | 2989 | } |