diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 514 |
1 files changed, 250 insertions, 264 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 72b9b2a0eba3..2a2f0094570f 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -64,6 +64,10 @@ MODULE_LICENSE("GPL"); | |||
64 | #define BUG_ON(expr) | 64 | #define BUG_ON(expr) |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | static struct scsi_transport_template *iscsi_tcp_scsi_transport; | ||
68 | static struct scsi_host_template iscsi_sht; | ||
69 | static struct iscsi_transport iscsi_tcp_transport; | ||
70 | |||
67 | static unsigned int iscsi_max_lun = 512; | 71 | static unsigned int iscsi_max_lun = 512; |
68 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); | 72 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); |
69 | 73 | ||
@@ -494,39 +498,43 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn) | |||
494 | * must be called with session lock | 498 | * must be called with session lock |
495 | */ | 499 | */ |
496 | static void | 500 | static void |
497 | iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 501 | iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task) |
498 | { | 502 | { |
499 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 503 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
500 | struct iscsi_r2t_info *r2t; | 504 | struct iscsi_r2t_info *r2t; |
501 | 505 | ||
502 | /* flush ctask's r2t queues */ | 506 | /* nothing to do for mgmt tasks */ |
503 | while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { | 507 | if (!task->sc) |
504 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | 508 | return; |
509 | |||
510 | /* flush task's r2t queues */ | ||
511 | while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { | ||
512 | __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, | ||
505 | sizeof(void*)); | 513 | sizeof(void*)); |
506 | debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n"); | 514 | debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n"); |
507 | } | 515 | } |
508 | 516 | ||
509 | r2t = tcp_ctask->r2t; | 517 | r2t = tcp_task->r2t; |
510 | if (r2t != NULL) { | 518 | if (r2t != NULL) { |
511 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | 519 | __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, |
512 | sizeof(void*)); | 520 | sizeof(void*)); |
513 | tcp_ctask->r2t = NULL; | 521 | tcp_task->r2t = NULL; |
514 | } | 522 | } |
515 | } | 523 | } |
516 | 524 | ||
517 | /** | 525 | /** |
518 | * iscsi_data_rsp - SCSI Data-In Response processing | 526 | * iscsi_data_rsp - SCSI Data-In Response processing |
519 | * @conn: iscsi connection | 527 | * @conn: iscsi connection |
520 | * @ctask: scsi command task | 528 | * @task: scsi command task |
521 | **/ | 529 | **/ |
522 | static int | 530 | static int |
523 | iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 531 | iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_task *task) |
524 | { | 532 | { |
525 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 533 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
526 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 534 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
527 | struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; | 535 | struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; |
528 | struct iscsi_session *session = conn->session; | 536 | struct iscsi_session *session = conn->session; |
529 | struct scsi_cmnd *sc = ctask->sc; | 537 | struct scsi_cmnd *sc = task->sc; |
530 | int datasn = be32_to_cpu(rhdr->datasn); | 538 | int datasn = be32_to_cpu(rhdr->datasn); |
531 | unsigned total_in_length = scsi_in(sc)->length; | 539 | unsigned total_in_length = scsi_in(sc)->length; |
532 | 540 | ||
@@ -534,18 +542,18 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
534 | if (tcp_conn->in.datalen == 0) | 542 | if (tcp_conn->in.datalen == 0) |
535 | return 0; | 543 | return 0; |
536 | 544 | ||
537 | if (tcp_ctask->exp_datasn != datasn) { | 545 | if (tcp_task->exp_datasn != datasn) { |
538 | debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n", | 546 | debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n", |
539 | __FUNCTION__, tcp_ctask->exp_datasn, datasn); | 547 | __func__, tcp_task->exp_datasn, datasn); |
540 | return ISCSI_ERR_DATASN; | 548 | return ISCSI_ERR_DATASN; |
541 | } | 549 | } |
542 | 550 | ||
543 | tcp_ctask->exp_datasn++; | 551 | tcp_task->exp_datasn++; |
544 | 552 | ||
545 | tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); | 553 | tcp_task->data_offset = be32_to_cpu(rhdr->offset); |
546 | if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) { | 554 | if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) { |
547 | debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n", | 555 | debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n", |
548 | __FUNCTION__, tcp_ctask->data_offset, | 556 | __func__, tcp_task->data_offset, |
549 | tcp_conn->in.datalen, total_in_length); | 557 | tcp_conn->in.datalen, total_in_length); |
550 | return ISCSI_ERR_DATA_OFFSET; | 558 | return ISCSI_ERR_DATA_OFFSET; |
551 | } | 559 | } |
@@ -574,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
574 | /** | 582 | /** |
575 | * iscsi_solicit_data_init - initialize first Data-Out | 583 | * iscsi_solicit_data_init - initialize first Data-Out |
576 | * @conn: iscsi connection | 584 | * @conn: iscsi connection |
577 | * @ctask: scsi command task | 585 | * @task: scsi command task |
578 | * @r2t: R2T info | 586 | * @r2t: R2T info |
579 | * | 587 | * |
580 | * Notes: | 588 | * Notes: |
@@ -584,7 +592,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
584 | * This function is called with connection lock taken. | 592 | * This function is called with connection lock taken. |
585 | **/ | 593 | **/ |
586 | static void | 594 | static void |
587 | iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 595 | iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_task *task, |
588 | struct iscsi_r2t_info *r2t) | 596 | struct iscsi_r2t_info *r2t) |
589 | { | 597 | { |
590 | struct iscsi_data *hdr; | 598 | struct iscsi_data *hdr; |
@@ -595,8 +603,8 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
595 | hdr->datasn = cpu_to_be32(r2t->solicit_datasn); | 603 | hdr->datasn = cpu_to_be32(r2t->solicit_datasn); |
596 | r2t->solicit_datasn++; | 604 | r2t->solicit_datasn++; |
597 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; | 605 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; |
598 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | 606 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); |
599 | hdr->itt = ctask->hdr->itt; | 607 | hdr->itt = task->hdr->itt; |
600 | hdr->exp_statsn = r2t->exp_statsn; | 608 | hdr->exp_statsn = r2t->exp_statsn; |
601 | hdr->offset = cpu_to_be32(r2t->data_offset); | 609 | hdr->offset = cpu_to_be32(r2t->data_offset); |
602 | if (r2t->data_length > conn->max_xmit_dlength) { | 610 | if (r2t->data_length > conn->max_xmit_dlength) { |
@@ -616,14 +624,14 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
616 | /** | 624 | /** |
617 | * iscsi_r2t_rsp - iSCSI R2T Response processing | 625 | * iscsi_r2t_rsp - iSCSI R2T Response processing |
618 | * @conn: iscsi connection | 626 | * @conn: iscsi connection |
619 | * @ctask: scsi command task | 627 | * @task: scsi command task |
620 | **/ | 628 | **/ |
621 | static int | 629 | static int |
622 | iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 630 | iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) |
623 | { | 631 | { |
624 | struct iscsi_r2t_info *r2t; | 632 | struct iscsi_r2t_info *r2t; |
625 | struct iscsi_session *session = conn->session; | 633 | struct iscsi_session *session = conn->session; |
626 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 634 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
627 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 635 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
628 | struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; | 636 | struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; |
629 | int r2tsn = be32_to_cpu(rhdr->r2tsn); | 637 | int r2tsn = be32_to_cpu(rhdr->r2tsn); |
@@ -636,23 +644,23 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
636 | return ISCSI_ERR_DATALEN; | 644 | return ISCSI_ERR_DATALEN; |
637 | } | 645 | } |
638 | 646 | ||
639 | if (tcp_ctask->exp_datasn != r2tsn){ | 647 | if (tcp_task->exp_datasn != r2tsn){ |
640 | debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n", | 648 | debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n", |
641 | __FUNCTION__, tcp_ctask->exp_datasn, r2tsn); | 649 | __func__, tcp_task->exp_datasn, r2tsn); |
642 | return ISCSI_ERR_R2TSN; | 650 | return ISCSI_ERR_R2TSN; |
643 | } | 651 | } |
644 | 652 | ||
645 | /* fill-in new R2T associated with the task */ | 653 | /* fill-in new R2T associated with the task */ |
646 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); | 654 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); |
647 | 655 | ||
648 | if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { | 656 | if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) { |
649 | iscsi_conn_printk(KERN_INFO, conn, | 657 | iscsi_conn_printk(KERN_INFO, conn, |
650 | "dropping R2T itt %d in recovery.\n", | 658 | "dropping R2T itt %d in recovery.\n", |
651 | ctask->itt); | 659 | task->itt); |
652 | return 0; | 660 | return 0; |
653 | } | 661 | } |
654 | 662 | ||
655 | rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); | 663 | rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); |
656 | BUG_ON(!rc); | 664 | BUG_ON(!rc); |
657 | 665 | ||
658 | r2t->exp_statsn = rhdr->statsn; | 666 | r2t->exp_statsn = rhdr->statsn; |
@@ -660,7 +668,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
660 | if (r2t->data_length == 0) { | 668 | if (r2t->data_length == 0) { |
661 | iscsi_conn_printk(KERN_ERR, conn, | 669 | iscsi_conn_printk(KERN_ERR, conn, |
662 | "invalid R2T with zero data len\n"); | 670 | "invalid R2T with zero data len\n"); |
663 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | 671 | __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, |
664 | sizeof(void*)); | 672 | sizeof(void*)); |
665 | return ISCSI_ERR_DATALEN; | 673 | return ISCSI_ERR_DATALEN; |
666 | } | 674 | } |
@@ -671,12 +679,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
671 | r2t->data_length, session->max_burst); | 679 | r2t->data_length, session->max_burst); |
672 | 680 | ||
673 | r2t->data_offset = be32_to_cpu(rhdr->data_offset); | 681 | r2t->data_offset = be32_to_cpu(rhdr->data_offset); |
674 | if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) { | 682 | if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) { |
675 | iscsi_conn_printk(KERN_ERR, conn, | 683 | iscsi_conn_printk(KERN_ERR, conn, |
676 | "invalid R2T with data len %u at offset %u " | 684 | "invalid R2T with data len %u at offset %u " |
677 | "and total length %d\n", r2t->data_length, | 685 | "and total length %d\n", r2t->data_length, |
678 | r2t->data_offset, scsi_out(ctask->sc)->length); | 686 | r2t->data_offset, scsi_out(task->sc)->length); |
679 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | 687 | __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, |
680 | sizeof(void*)); | 688 | sizeof(void*)); |
681 | return ISCSI_ERR_DATALEN; | 689 | return ISCSI_ERR_DATALEN; |
682 | } | 690 | } |
@@ -684,13 +692,13 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
684 | r2t->ttt = rhdr->ttt; /* no flip */ | 692 | r2t->ttt = rhdr->ttt; /* no flip */ |
685 | r2t->solicit_datasn = 0; | 693 | r2t->solicit_datasn = 0; |
686 | 694 | ||
687 | iscsi_solicit_data_init(conn, ctask, r2t); | 695 | iscsi_solicit_data_init(conn, task, r2t); |
688 | 696 | ||
689 | tcp_ctask->exp_datasn = r2tsn + 1; | 697 | tcp_task->exp_datasn = r2tsn + 1; |
690 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 698 | __kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); |
691 | conn->r2t_pdus_cnt++; | 699 | conn->r2t_pdus_cnt++; |
692 | 700 | ||
693 | iscsi_requeue_ctask(ctask); | 701 | iscsi_requeue_task(task); |
694 | return 0; | 702 | return 0; |
695 | } | 703 | } |
696 | 704 | ||
@@ -733,10 +741,8 @@ static int | |||
733 | iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 741 | iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) |
734 | { | 742 | { |
735 | int rc = 0, opcode, ahslen; | 743 | int rc = 0, opcode, ahslen; |
736 | struct iscsi_session *session = conn->session; | ||
737 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 744 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
738 | struct iscsi_cmd_task *ctask; | 745 | struct iscsi_task *task; |
739 | uint32_t itt; | ||
740 | 746 | ||
741 | /* verify PDU length */ | 747 | /* verify PDU length */ |
742 | tcp_conn->in.datalen = ntoh24(hdr->dlength); | 748 | tcp_conn->in.datalen = ntoh24(hdr->dlength); |
@@ -754,7 +760,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
754 | 760 | ||
755 | opcode = hdr->opcode & ISCSI_OPCODE_MASK; | 761 | opcode = hdr->opcode & ISCSI_OPCODE_MASK; |
756 | /* verify itt (itt encoding: age+cid+itt) */ | 762 | /* verify itt (itt encoding: age+cid+itt) */ |
757 | rc = iscsi_verify_itt(conn, hdr, &itt); | 763 | rc = iscsi_verify_itt(conn, hdr->itt); |
758 | if (rc) | 764 | if (rc) |
759 | return rc; | 765 | return rc; |
760 | 766 | ||
@@ -763,16 +769,21 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
763 | 769 | ||
764 | switch(opcode) { | 770 | switch(opcode) { |
765 | case ISCSI_OP_SCSI_DATA_IN: | 771 | case ISCSI_OP_SCSI_DATA_IN: |
766 | ctask = session->cmds[itt]; | ||
767 | spin_lock(&conn->session->lock); | 772 | spin_lock(&conn->session->lock); |
768 | rc = iscsi_data_rsp(conn, ctask); | 773 | task = iscsi_itt_to_ctask(conn, hdr->itt); |
769 | spin_unlock(&conn->session->lock); | 774 | if (!task) |
770 | if (rc) | 775 | rc = ISCSI_ERR_BAD_ITT; |
771 | return rc; | 776 | else |
777 | rc = iscsi_data_rsp(conn, task); | ||
778 | if (rc) { | ||
779 | spin_unlock(&conn->session->lock); | ||
780 | break; | ||
781 | } | ||
782 | |||
772 | if (tcp_conn->in.datalen) { | 783 | if (tcp_conn->in.datalen) { |
773 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 784 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
774 | struct hash_desc *rx_hash = NULL; | 785 | struct hash_desc *rx_hash = NULL; |
775 | struct scsi_data_buffer *sdb = scsi_in(ctask->sc); | 786 | struct scsi_data_buffer *sdb = scsi_in(task->sc); |
776 | 787 | ||
777 | /* | 788 | /* |
778 | * Setup copy of Data-In into the Scsi_Cmnd | 789 | * Setup copy of Data-In into the Scsi_Cmnd |
@@ -787,17 +798,21 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
787 | 798 | ||
788 | debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, " | 799 | debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, " |
789 | "datalen=%d)\n", tcp_conn, | 800 | "datalen=%d)\n", tcp_conn, |
790 | tcp_ctask->data_offset, | 801 | tcp_task->data_offset, |
791 | tcp_conn->in.datalen); | 802 | tcp_conn->in.datalen); |
792 | return iscsi_segment_seek_sg(&tcp_conn->in.segment, | 803 | rc = iscsi_segment_seek_sg(&tcp_conn->in.segment, |
793 | sdb->table.sgl, | 804 | sdb->table.sgl, |
794 | sdb->table.nents, | 805 | sdb->table.nents, |
795 | tcp_ctask->data_offset, | 806 | tcp_task->data_offset, |
796 | tcp_conn->in.datalen, | 807 | tcp_conn->in.datalen, |
797 | iscsi_tcp_process_data_in, | 808 | iscsi_tcp_process_data_in, |
798 | rx_hash); | 809 | rx_hash); |
810 | spin_unlock(&conn->session->lock); | ||
811 | return rc; | ||
799 | } | 812 | } |
800 | /* fall through */ | 813 | rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); |
814 | spin_unlock(&conn->session->lock); | ||
815 | break; | ||
801 | case ISCSI_OP_SCSI_CMD_RSP: | 816 | case ISCSI_OP_SCSI_CMD_RSP: |
802 | if (tcp_conn->in.datalen) { | 817 | if (tcp_conn->in.datalen) { |
803 | iscsi_tcp_data_recv_prep(tcp_conn); | 818 | iscsi_tcp_data_recv_prep(tcp_conn); |
@@ -806,15 +821,17 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
806 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); | 821 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); |
807 | break; | 822 | break; |
808 | case ISCSI_OP_R2T: | 823 | case ISCSI_OP_R2T: |
809 | ctask = session->cmds[itt]; | 824 | spin_lock(&conn->session->lock); |
810 | if (ahslen) | 825 | task = iscsi_itt_to_ctask(conn, hdr->itt); |
826 | if (!task) | ||
827 | rc = ISCSI_ERR_BAD_ITT; | ||
828 | else if (ahslen) | ||
811 | rc = ISCSI_ERR_AHSLEN; | 829 | rc = ISCSI_ERR_AHSLEN; |
812 | else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) { | 830 | else if (task->sc->sc_data_direction == DMA_TO_DEVICE) |
813 | spin_lock(&session->lock); | 831 | rc = iscsi_r2t_rsp(conn, task); |
814 | rc = iscsi_r2t_rsp(conn, ctask); | 832 | else |
815 | spin_unlock(&session->lock); | ||
816 | } else | ||
817 | rc = ISCSI_ERR_PROTO; | 833 | rc = ISCSI_ERR_PROTO; |
834 | spin_unlock(&conn->session->lock); | ||
818 | break; | 835 | break; |
819 | case ISCSI_OP_LOGIN_RSP: | 836 | case ISCSI_OP_LOGIN_RSP: |
820 | case ISCSI_OP_TEXT_RSP: | 837 | case ISCSI_OP_TEXT_RSP: |
@@ -1176,7 +1193,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen) | |||
1176 | { | 1193 | { |
1177 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1194 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1178 | 1195 | ||
1179 | debug_tcp("%s(%p%s)\n", __FUNCTION__, tcp_conn, | 1196 | debug_tcp("%s(%p%s)\n", __func__, tcp_conn, |
1180 | conn->hdrdgst_en? ", digest enabled" : ""); | 1197 | conn->hdrdgst_en? ", digest enabled" : ""); |
1181 | 1198 | ||
1182 | /* Clear the data segment - needs to be filled in by the | 1199 | /* Clear the data segment - needs to be filled in by the |
@@ -1185,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen) | |||
1185 | 1202 | ||
1186 | /* If header digest is enabled, compute the CRC and | 1203 | /* If header digest is enabled, compute the CRC and |
1187 | * place the digest into the same buffer. We make | 1204 | * place the digest into the same buffer. We make |
1188 | * sure that both iscsi_tcp_ctask and mtask have | 1205 | * sure that both iscsi_tcp_task and mtask have |
1189 | * sufficient room. | 1206 | * sufficient room. |
1190 | */ | 1207 | */ |
1191 | if (conn->hdrdgst_en) { | 1208 | if (conn->hdrdgst_en) { |
@@ -1217,7 +1234,7 @@ iscsi_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, | |||
1217 | struct hash_desc *tx_hash = NULL; | 1234 | struct hash_desc *tx_hash = NULL; |
1218 | unsigned int hdr_spec_len; | 1235 | unsigned int hdr_spec_len; |
1219 | 1236 | ||
1220 | debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __FUNCTION__, | 1237 | debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __func__, |
1221 | tcp_conn, offset, len, | 1238 | tcp_conn, offset, len, |
1222 | conn->datadgst_en? ", digest enabled" : ""); | 1239 | conn->datadgst_en? ", digest enabled" : ""); |
1223 | 1240 | ||
@@ -1242,7 +1259,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data, | |||
1242 | struct hash_desc *tx_hash = NULL; | 1259 | struct hash_desc *tx_hash = NULL; |
1243 | unsigned int hdr_spec_len; | 1260 | unsigned int hdr_spec_len; |
1244 | 1261 | ||
1245 | debug_tcp("%s(%p, datalen=%d%s)\n", __FUNCTION__, tcp_conn, len, | 1262 | debug_tcp("%s(%p, datalen=%d%s)\n", __func__, tcp_conn, len, |
1246 | conn->datadgst_en? ", digest enabled" : ""); | 1263 | conn->datadgst_en? ", digest enabled" : ""); |
1247 | 1264 | ||
1248 | /* Make sure the datalen matches what the caller | 1265 | /* Make sure the datalen matches what the caller |
@@ -1260,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data, | |||
1260 | /** | 1277 | /** |
1261 | * iscsi_solicit_data_cont - initialize next Data-Out | 1278 | * iscsi_solicit_data_cont - initialize next Data-Out |
1262 | * @conn: iscsi connection | 1279 | * @conn: iscsi connection |
1263 | * @ctask: scsi command task | 1280 | * @task: scsi command task |
1264 | * @r2t: R2T info | 1281 | * @r2t: R2T info |
1265 | * @left: bytes left to transfer | 1282 | * @left: bytes left to transfer |
1266 | * | 1283 | * |
@@ -1271,7 +1288,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data, | |||
1271 | * Called under connection lock. | 1288 | * Called under connection lock. |
1272 | **/ | 1289 | **/ |
1273 | static int | 1290 | static int |
1274 | iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 1291 | iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_task *task, |
1275 | struct iscsi_r2t_info *r2t) | 1292 | struct iscsi_r2t_info *r2t) |
1276 | { | 1293 | { |
1277 | struct iscsi_data *hdr; | 1294 | struct iscsi_data *hdr; |
@@ -1288,8 +1305,8 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1288 | hdr->datasn = cpu_to_be32(r2t->solicit_datasn); | 1305 | hdr->datasn = cpu_to_be32(r2t->solicit_datasn); |
1289 | r2t->solicit_datasn++; | 1306 | r2t->solicit_datasn++; |
1290 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; | 1307 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; |
1291 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | 1308 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); |
1292 | hdr->itt = ctask->hdr->itt; | 1309 | hdr->itt = task->hdr->itt; |
1293 | hdr->exp_statsn = r2t->exp_statsn; | 1310 | hdr->exp_statsn = r2t->exp_statsn; |
1294 | new_offset = r2t->data_offset + r2t->sent; | 1311 | new_offset = r2t->data_offset + r2t->sent; |
1295 | hdr->offset = cpu_to_be32(new_offset); | 1312 | hdr->offset = cpu_to_be32(new_offset); |
@@ -1307,89 +1324,76 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1307 | } | 1324 | } |
1308 | 1325 | ||
1309 | /** | 1326 | /** |
1310 | * iscsi_tcp_ctask - Initialize iSCSI SCSI_READ or SCSI_WRITE commands | 1327 | * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands |
1311 | * @conn: iscsi connection | 1328 | * @conn: iscsi connection |
1312 | * @ctask: scsi command task | 1329 | * @task: scsi command task |
1313 | * @sc: scsi command | 1330 | * @sc: scsi command |
1314 | **/ | 1331 | **/ |
1315 | static int | 1332 | static int |
1316 | iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask) | 1333 | iscsi_tcp_task_init(struct iscsi_task *task) |
1317 | { | 1334 | { |
1318 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1335 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
1319 | struct iscsi_conn *conn = ctask->conn; | 1336 | struct iscsi_conn *conn = task->conn; |
1320 | struct scsi_cmnd *sc = ctask->sc; | 1337 | struct scsi_cmnd *sc = task->sc; |
1321 | int err; | 1338 | int err; |
1322 | 1339 | ||
1323 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); | 1340 | if (!sc) { |
1324 | tcp_ctask->sent = 0; | 1341 | /* |
1325 | tcp_ctask->exp_datasn = 0; | 1342 | * mgmt tasks do not have a scatterlist since they come |
1343 | * in from the iscsi interface. | ||
1344 | */ | ||
1345 | debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, | ||
1346 | task->itt); | ||
1347 | |||
1348 | /* Prepare PDU, optionally w/ immediate data */ | ||
1349 | iscsi_tcp_send_hdr_prep(conn, task->hdr, sizeof(*task->hdr)); | ||
1350 | |||
1351 | /* If we have immediate data, attach a payload */ | ||
1352 | if (task->data_count) | ||
1353 | iscsi_tcp_send_linear_data_prepare(conn, task->data, | ||
1354 | task->data_count); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | BUG_ON(__kfifo_len(tcp_task->r2tqueue)); | ||
1359 | tcp_task->sent = 0; | ||
1360 | tcp_task->exp_datasn = 0; | ||
1326 | 1361 | ||
1327 | /* Prepare PDU, optionally w/ immediate data */ | 1362 | /* Prepare PDU, optionally w/ immediate data */ |
1328 | debug_scsi("ctask deq [cid %d itt 0x%x imm %d unsol %d]\n", | 1363 | debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n", |
1329 | conn->id, ctask->itt, ctask->imm_count, | 1364 | conn->id, task->itt, task->imm_count, |
1330 | ctask->unsol_count); | 1365 | task->unsol_count); |
1331 | iscsi_tcp_send_hdr_prep(conn, ctask->hdr, ctask->hdr_len); | 1366 | iscsi_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len); |
1332 | 1367 | ||
1333 | if (!ctask->imm_count) | 1368 | if (!task->imm_count) |
1334 | return 0; | 1369 | return 0; |
1335 | 1370 | ||
1336 | /* If we have immediate data, attach a payload */ | 1371 | /* If we have immediate data, attach a payload */ |
1337 | err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl, | 1372 | err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl, |
1338 | scsi_out(sc)->table.nents, | 1373 | scsi_out(sc)->table.nents, |
1339 | 0, ctask->imm_count); | 1374 | 0, task->imm_count); |
1340 | if (err) | 1375 | if (err) |
1341 | return err; | 1376 | return err; |
1342 | tcp_ctask->sent += ctask->imm_count; | 1377 | tcp_task->sent += task->imm_count; |
1343 | ctask->imm_count = 0; | 1378 | task->imm_count = 0; |
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1347 | /** | ||
1348 | * iscsi_tcp_mtask_xmit - xmit management(immediate) task | ||
1349 | * @conn: iscsi connection | ||
1350 | * @mtask: task management task | ||
1351 | * | ||
1352 | * Notes: | ||
1353 | * The function can return -EAGAIN in which case caller must | ||
1354 | * call it again later, or recover. '0' return code means successful | ||
1355 | * xmit. | ||
1356 | **/ | ||
1357 | static int | ||
1358 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | ||
1359 | { | ||
1360 | int rc; | ||
1361 | |||
1362 | /* Flush any pending data first. */ | ||
1363 | rc = iscsi_tcp_flush(conn); | ||
1364 | if (rc < 0) | ||
1365 | return rc; | ||
1366 | |||
1367 | if (mtask->hdr->itt == RESERVED_ITT) { | ||
1368 | struct iscsi_session *session = conn->session; | ||
1369 | |||
1370 | spin_lock_bh(&session->lock); | ||
1371 | iscsi_free_mgmt_task(conn, mtask); | ||
1372 | spin_unlock_bh(&session->lock); | ||
1373 | } | ||
1374 | |||
1375 | return 0; | 1379 | return 0; |
1376 | } | 1380 | } |
1377 | 1381 | ||
1378 | /* | 1382 | /* |
1379 | * iscsi_tcp_ctask_xmit - xmit normal PDU task | 1383 | * iscsi_tcp_task_xmit - xmit normal PDU task |
1380 | * @conn: iscsi connection | 1384 | * @task: iscsi command task |
1381 | * @ctask: iscsi command task | ||
1382 | * | 1385 | * |
1383 | * We're expected to return 0 when everything was transmitted succesfully, | 1386 | * We're expected to return 0 when everything was transmitted succesfully, |
1384 | * -EAGAIN if there's still data in the queue, or != 0 for any other kind | 1387 | * -EAGAIN if there's still data in the queue, or != 0 for any other kind |
1385 | * of error. | 1388 | * of error. |
1386 | */ | 1389 | */ |
1387 | static int | 1390 | static int |
1388 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1391 | iscsi_tcp_task_xmit(struct iscsi_task *task) |
1389 | { | 1392 | { |
1390 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1393 | struct iscsi_conn *conn = task->conn; |
1391 | struct scsi_cmnd *sc = ctask->sc; | 1394 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
1392 | struct scsi_data_buffer *sdb = scsi_out(sc); | 1395 | struct scsi_cmnd *sc = task->sc; |
1396 | struct scsi_data_buffer *sdb; | ||
1393 | int rc = 0; | 1397 | int rc = 0; |
1394 | 1398 | ||
1395 | flush: | 1399 | flush: |
@@ -1398,31 +1402,39 @@ flush: | |||
1398 | if (rc < 0) | 1402 | if (rc < 0) |
1399 | return rc; | 1403 | return rc; |
1400 | 1404 | ||
1405 | /* mgmt command */ | ||
1406 | if (!sc) { | ||
1407 | if (task->hdr->itt == RESERVED_ITT) | ||
1408 | iscsi_put_task(task); | ||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1401 | /* Are we done already? */ | 1412 | /* Are we done already? */ |
1402 | if (sc->sc_data_direction != DMA_TO_DEVICE) | 1413 | if (sc->sc_data_direction != DMA_TO_DEVICE) |
1403 | return 0; | 1414 | return 0; |
1404 | 1415 | ||
1405 | if (ctask->unsol_count != 0) { | 1416 | sdb = scsi_out(sc); |
1406 | struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr; | 1417 | if (task->unsol_count != 0) { |
1418 | struct iscsi_data *hdr = &tcp_task->unsol_dtask.hdr; | ||
1407 | 1419 | ||
1408 | /* Prepare a header for the unsolicited PDU. | 1420 | /* Prepare a header for the unsolicited PDU. |
1409 | * The amount of data we want to send will be | 1421 | * The amount of data we want to send will be |
1410 | * in ctask->data_count. | 1422 | * in task->data_count. |
1411 | * FIXME: return the data count instead. | 1423 | * FIXME: return the data count instead. |
1412 | */ | 1424 | */ |
1413 | iscsi_prep_unsolicit_data_pdu(ctask, hdr); | 1425 | iscsi_prep_unsolicit_data_pdu(task, hdr); |
1414 | 1426 | ||
1415 | debug_tcp("unsol dout [itt 0x%x doff %d dlen %d]\n", | 1427 | debug_tcp("unsol dout [itt 0x%x doff %d dlen %d]\n", |
1416 | ctask->itt, tcp_ctask->sent, ctask->data_count); | 1428 | task->itt, tcp_task->sent, task->data_count); |
1417 | 1429 | ||
1418 | iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr)); | 1430 | iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr)); |
1419 | rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl, | 1431 | rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl, |
1420 | sdb->table.nents, tcp_ctask->sent, | 1432 | sdb->table.nents, tcp_task->sent, |
1421 | ctask->data_count); | 1433 | task->data_count); |
1422 | if (rc) | 1434 | if (rc) |
1423 | goto fail; | 1435 | goto fail; |
1424 | tcp_ctask->sent += ctask->data_count; | 1436 | tcp_task->sent += task->data_count; |
1425 | ctask->unsol_count -= ctask->data_count; | 1437 | task->unsol_count -= task->data_count; |
1426 | goto flush; | 1438 | goto flush; |
1427 | } else { | 1439 | } else { |
1428 | struct iscsi_session *session = conn->session; | 1440 | struct iscsi_session *session = conn->session; |
@@ -1431,22 +1443,22 @@ flush: | |||
1431 | /* All unsolicited PDUs sent. Check for solicited PDUs. | 1443 | /* All unsolicited PDUs sent. Check for solicited PDUs. |
1432 | */ | 1444 | */ |
1433 | spin_lock_bh(&session->lock); | 1445 | spin_lock_bh(&session->lock); |
1434 | r2t = tcp_ctask->r2t; | 1446 | r2t = tcp_task->r2t; |
1435 | if (r2t != NULL) { | 1447 | if (r2t != NULL) { |
1436 | /* Continue with this R2T? */ | 1448 | /* Continue with this R2T? */ |
1437 | if (!iscsi_solicit_data_cont(conn, ctask, r2t)) { | 1449 | if (!iscsi_solicit_data_cont(conn, task, r2t)) { |
1438 | debug_scsi(" done with r2t %p\n", r2t); | 1450 | debug_scsi(" done with r2t %p\n", r2t); |
1439 | 1451 | ||
1440 | __kfifo_put(tcp_ctask->r2tpool.queue, | 1452 | __kfifo_put(tcp_task->r2tpool.queue, |
1441 | (void*)&r2t, sizeof(void*)); | 1453 | (void*)&r2t, sizeof(void*)); |
1442 | tcp_ctask->r2t = r2t = NULL; | 1454 | tcp_task->r2t = r2t = NULL; |
1443 | } | 1455 | } |
1444 | } | 1456 | } |
1445 | 1457 | ||
1446 | if (r2t == NULL) { | 1458 | if (r2t == NULL) { |
1447 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, | 1459 | __kfifo_get(tcp_task->r2tqueue, (void*)&tcp_task->r2t, |
1448 | sizeof(void*)); | 1460 | sizeof(void*)); |
1449 | r2t = tcp_ctask->r2t; | 1461 | r2t = tcp_task->r2t; |
1450 | } | 1462 | } |
1451 | spin_unlock_bh(&session->lock); | 1463 | spin_unlock_bh(&session->lock); |
1452 | 1464 | ||
@@ -1457,7 +1469,7 @@ flush: | |||
1457 | } | 1469 | } |
1458 | 1470 | ||
1459 | debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n", | 1471 | debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n", |
1460 | r2t, r2t->solicit_datasn - 1, ctask->itt, | 1472 | r2t, r2t->solicit_datasn - 1, task->itt, |
1461 | r2t->data_offset + r2t->sent, r2t->data_count); | 1473 | r2t->data_offset + r2t->sent, r2t->data_count); |
1462 | 1474 | ||
1463 | iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr, | 1475 | iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr, |
@@ -1469,7 +1481,7 @@ flush: | |||
1469 | r2t->data_count); | 1481 | r2t->data_count); |
1470 | if (rc) | 1482 | if (rc) |
1471 | goto fail; | 1483 | goto fail; |
1472 | tcp_ctask->sent += r2t->data_count; | 1484 | tcp_task->sent += r2t->data_count; |
1473 | r2t->sent += r2t->data_count; | 1485 | r2t->sent += r2t->data_count; |
1474 | goto flush; | 1486 | goto flush; |
1475 | } | 1487 | } |
@@ -1486,7 +1498,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1486 | struct iscsi_cls_conn *cls_conn; | 1498 | struct iscsi_cls_conn *cls_conn; |
1487 | struct iscsi_tcp_conn *tcp_conn; | 1499 | struct iscsi_tcp_conn *tcp_conn; |
1488 | 1500 | ||
1489 | cls_conn = iscsi_conn_setup(cls_session, conn_idx); | 1501 | cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx); |
1490 | if (!cls_conn) | 1502 | if (!cls_conn) |
1491 | return NULL; | 1503 | return NULL; |
1492 | conn = cls_conn->dd_data; | 1504 | conn = cls_conn->dd_data; |
@@ -1496,18 +1508,14 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1496 | */ | 1508 | */ |
1497 | conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; | 1509 | conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; |
1498 | 1510 | ||
1499 | tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); | 1511 | tcp_conn = conn->dd_data; |
1500 | if (!tcp_conn) | ||
1501 | goto tcp_conn_alloc_fail; | ||
1502 | |||
1503 | conn->dd_data = tcp_conn; | ||
1504 | tcp_conn->iscsi_conn = conn; | 1512 | tcp_conn->iscsi_conn = conn; |
1505 | 1513 | ||
1506 | tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, | 1514 | tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, |
1507 | CRYPTO_ALG_ASYNC); | 1515 | CRYPTO_ALG_ASYNC); |
1508 | tcp_conn->tx_hash.flags = 0; | 1516 | tcp_conn->tx_hash.flags = 0; |
1509 | if (IS_ERR(tcp_conn->tx_hash.tfm)) | 1517 | if (IS_ERR(tcp_conn->tx_hash.tfm)) |
1510 | goto free_tcp_conn; | 1518 | goto free_conn; |
1511 | 1519 | ||
1512 | tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, | 1520 | tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, |
1513 | CRYPTO_ALG_ASYNC); | 1521 | CRYPTO_ALG_ASYNC); |
@@ -1519,14 +1527,12 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1519 | 1527 | ||
1520 | free_tx_tfm: | 1528 | free_tx_tfm: |
1521 | crypto_free_hash(tcp_conn->tx_hash.tfm); | 1529 | crypto_free_hash(tcp_conn->tx_hash.tfm); |
1522 | free_tcp_conn: | 1530 | free_conn: |
1523 | iscsi_conn_printk(KERN_ERR, conn, | 1531 | iscsi_conn_printk(KERN_ERR, conn, |
1524 | "Could not create connection due to crc32c " | 1532 | "Could not create connection due to crc32c " |
1525 | "loading error. Make sure the crc32c " | 1533 | "loading error. Make sure the crc32c " |
1526 | "module is built as a module or into the " | 1534 | "module is built as a module or into the " |
1527 | "kernel\n"); | 1535 | "kernel\n"); |
1528 | kfree(tcp_conn); | ||
1529 | tcp_conn_alloc_fail: | ||
1530 | iscsi_conn_teardown(cls_conn); | 1536 | iscsi_conn_teardown(cls_conn); |
1531 | return NULL; | 1537 | return NULL; |
1532 | } | 1538 | } |
@@ -1547,7 +1553,6 @@ iscsi_tcp_release_conn(struct iscsi_conn *conn) | |||
1547 | 1553 | ||
1548 | spin_lock_bh(&session->lock); | 1554 | spin_lock_bh(&session->lock); |
1549 | tcp_conn->sock = NULL; | 1555 | tcp_conn->sock = NULL; |
1550 | conn->recv_lock = NULL; | ||
1551 | spin_unlock_bh(&session->lock); | 1556 | spin_unlock_bh(&session->lock); |
1552 | sockfd_put(sock); | 1557 | sockfd_put(sock); |
1553 | } | 1558 | } |
@@ -1559,20 +1564,32 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | |||
1559 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1564 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1560 | 1565 | ||
1561 | iscsi_tcp_release_conn(conn); | 1566 | iscsi_tcp_release_conn(conn); |
1562 | iscsi_conn_teardown(cls_conn); | ||
1563 | 1567 | ||
1564 | if (tcp_conn->tx_hash.tfm) | 1568 | if (tcp_conn->tx_hash.tfm) |
1565 | crypto_free_hash(tcp_conn->tx_hash.tfm); | 1569 | crypto_free_hash(tcp_conn->tx_hash.tfm); |
1566 | if (tcp_conn->rx_hash.tfm) | 1570 | if (tcp_conn->rx_hash.tfm) |
1567 | crypto_free_hash(tcp_conn->rx_hash.tfm); | 1571 | crypto_free_hash(tcp_conn->rx_hash.tfm); |
1568 | 1572 | ||
1569 | kfree(tcp_conn); | 1573 | iscsi_conn_teardown(cls_conn); |
1570 | } | 1574 | } |
1571 | 1575 | ||
1572 | static void | 1576 | static void |
1573 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | 1577 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) |
1574 | { | 1578 | { |
1575 | struct iscsi_conn *conn = cls_conn->dd_data; | 1579 | struct iscsi_conn *conn = cls_conn->dd_data; |
1580 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
1581 | |||
1582 | /* userspace may have goofed up and not bound us */ | ||
1583 | if (!tcp_conn->sock) | ||
1584 | return; | ||
1585 | /* | ||
1586 | * Make sure our recv side is stopped. | ||
1587 | * Older tools called conn stop before ep_disconnect | ||
1588 | * so IO could still be coming in. | ||
1589 | */ | ||
1590 | write_lock_bh(&tcp_conn->sock->sk->sk_callback_lock); | ||
1591 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); | ||
1592 | write_unlock_bh(&tcp_conn->sock->sk->sk_callback_lock); | ||
1576 | 1593 | ||
1577 | iscsi_conn_stop(cls_conn, flag); | 1594 | iscsi_conn_stop(cls_conn, flag); |
1578 | iscsi_tcp_release_conn(conn); | 1595 | iscsi_tcp_release_conn(conn); |
@@ -1623,6 +1640,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
1623 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, | 1640 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, |
1624 | int is_leading) | 1641 | int is_leading) |
1625 | { | 1642 | { |
1643 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | ||
1644 | struct iscsi_host *ihost = shost_priv(shost); | ||
1626 | struct iscsi_conn *conn = cls_conn->dd_data; | 1645 | struct iscsi_conn *conn = cls_conn->dd_data; |
1627 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1646 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1628 | struct sock *sk; | 1647 | struct sock *sk; |
@@ -1646,8 +1665,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
1646 | if (err) | 1665 | if (err) |
1647 | goto free_socket; | 1666 | goto free_socket; |
1648 | 1667 | ||
1649 | err = iscsi_tcp_get_addr(conn, sock, conn->local_address, | 1668 | err = iscsi_tcp_get_addr(conn, sock, ihost->local_address, |
1650 | &conn->local_port, kernel_getsockname); | 1669 | &ihost->local_port, kernel_getsockname); |
1651 | if (err) | 1670 | if (err) |
1652 | goto free_socket; | 1671 | goto free_socket; |
1653 | 1672 | ||
@@ -1664,13 +1683,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
1664 | sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ | 1683 | sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ |
1665 | sk->sk_allocation = GFP_ATOMIC; | 1684 | sk->sk_allocation = GFP_ATOMIC; |
1666 | 1685 | ||
1667 | /* FIXME: disable Nagle's algorithm */ | ||
1668 | |||
1669 | /* | ||
1670 | * Intercept TCP callbacks for sendfile like receive | ||
1671 | * processing. | ||
1672 | */ | ||
1673 | conn->recv_lock = &sk->sk_callback_lock; | ||
1674 | iscsi_conn_set_callbacks(conn); | 1686 | iscsi_conn_set_callbacks(conn); |
1675 | tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; | 1687 | tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; |
1676 | /* | 1688 | /* |
@@ -1684,21 +1696,6 @@ free_socket: | |||
1684 | return err; | 1696 | return err; |
1685 | } | 1697 | } |
1686 | 1698 | ||
1687 | /* called with host lock */ | ||
1688 | static void | ||
1689 | iscsi_tcp_mtask_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | ||
1690 | { | ||
1691 | debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt); | ||
1692 | |||
1693 | /* Prepare PDU, optionally w/ immediate data */ | ||
1694 | iscsi_tcp_send_hdr_prep(conn, mtask->hdr, sizeof(*mtask->hdr)); | ||
1695 | |||
1696 | /* If we have immediate data, attach a payload */ | ||
1697 | if (mtask->data_count) | ||
1698 | iscsi_tcp_send_linear_data_prepare(conn, mtask->data, | ||
1699 | mtask->data_count); | ||
1700 | } | ||
1701 | |||
1702 | static int | 1699 | static int |
1703 | iscsi_r2tpool_alloc(struct iscsi_session *session) | 1700 | iscsi_r2tpool_alloc(struct iscsi_session *session) |
1704 | { | 1701 | { |
@@ -1709,8 +1706,8 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) | |||
1709 | * initialize per-task: R2T pool and xmit queue | 1706 | * initialize per-task: R2T pool and xmit queue |
1710 | */ | 1707 | */ |
1711 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 1708 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1712 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 1709 | struct iscsi_task *task = session->cmds[cmd_i]; |
1713 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1710 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
1714 | 1711 | ||
1715 | /* | 1712 | /* |
1716 | * pre-allocated x4 as much r2ts to handle race when | 1713 | * pre-allocated x4 as much r2ts to handle race when |
@@ -1719,16 +1716,16 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) | |||
1719 | */ | 1716 | */ |
1720 | 1717 | ||
1721 | /* R2T pool */ | 1718 | /* R2T pool */ |
1722 | if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, NULL, | 1719 | if (iscsi_pool_init(&tcp_task->r2tpool, session->max_r2t * 4, NULL, |
1723 | sizeof(struct iscsi_r2t_info))) { | 1720 | sizeof(struct iscsi_r2t_info))) { |
1724 | goto r2t_alloc_fail; | 1721 | goto r2t_alloc_fail; |
1725 | } | 1722 | } |
1726 | 1723 | ||
1727 | /* R2T xmit queue */ | 1724 | /* R2T xmit queue */ |
1728 | tcp_ctask->r2tqueue = kfifo_alloc( | 1725 | tcp_task->r2tqueue = kfifo_alloc( |
1729 | session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); | 1726 | session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); |
1730 | if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) { | 1727 | if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) { |
1731 | iscsi_pool_free(&tcp_ctask->r2tpool); | 1728 | iscsi_pool_free(&tcp_task->r2tpool); |
1732 | goto r2t_alloc_fail; | 1729 | goto r2t_alloc_fail; |
1733 | } | 1730 | } |
1734 | } | 1731 | } |
@@ -1737,11 +1734,11 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) | |||
1737 | 1734 | ||
1738 | r2t_alloc_fail: | 1735 | r2t_alloc_fail: |
1739 | for (i = 0; i < cmd_i; i++) { | 1736 | for (i = 0; i < cmd_i; i++) { |
1740 | struct iscsi_cmd_task *ctask = session->cmds[i]; | 1737 | struct iscsi_task *task = session->cmds[i]; |
1741 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1738 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
1742 | 1739 | ||
1743 | kfifo_free(tcp_ctask->r2tqueue); | 1740 | kfifo_free(tcp_task->r2tqueue); |
1744 | iscsi_pool_free(&tcp_ctask->r2tpool); | 1741 | iscsi_pool_free(&tcp_task->r2tpool); |
1745 | } | 1742 | } |
1746 | return -ENOMEM; | 1743 | return -ENOMEM; |
1747 | } | 1744 | } |
@@ -1752,11 +1749,11 @@ iscsi_r2tpool_free(struct iscsi_session *session) | |||
1752 | int i; | 1749 | int i; |
1753 | 1750 | ||
1754 | for (i = 0; i < session->cmds_max; i++) { | 1751 | for (i = 0; i < session->cmds_max; i++) { |
1755 | struct iscsi_cmd_task *ctask = session->cmds[i]; | 1752 | struct iscsi_task *task = session->cmds[i]; |
1756 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1753 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
1757 | 1754 | ||
1758 | kfifo_free(tcp_ctask->r2tqueue); | 1755 | kfifo_free(tcp_task->r2tqueue); |
1759 | iscsi_pool_free(&tcp_ctask->r2tpool); | 1756 | iscsi_pool_free(&tcp_task->r2tpool); |
1760 | } | 1757 | } |
1761 | } | 1758 | } |
1762 | 1759 | ||
@@ -1821,29 +1818,6 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
1821 | return len; | 1818 | return len; |
1822 | } | 1819 | } |
1823 | 1820 | ||
1824 | static int | ||
1825 | iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, | ||
1826 | char *buf) | ||
1827 | { | ||
1828 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
1829 | int len; | ||
1830 | |||
1831 | switch (param) { | ||
1832 | case ISCSI_HOST_PARAM_IPADDRESS: | ||
1833 | spin_lock_bh(&session->lock); | ||
1834 | if (!session->leadconn) | ||
1835 | len = -ENODEV; | ||
1836 | else | ||
1837 | len = sprintf(buf, "%s\n", | ||
1838 | session->leadconn->local_address); | ||
1839 | spin_unlock_bh(&session->lock); | ||
1840 | break; | ||
1841 | default: | ||
1842 | return iscsi_host_get_param(shost, param, buf); | ||
1843 | } | ||
1844 | return len; | ||
1845 | } | ||
1846 | |||
1847 | static void | 1821 | static void |
1848 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | 1822 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) |
1849 | { | 1823 | { |
@@ -1869,54 +1843,70 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | |||
1869 | } | 1843 | } |
1870 | 1844 | ||
1871 | static struct iscsi_cls_session * | 1845 | static struct iscsi_cls_session * |
1872 | iscsi_tcp_session_create(struct iscsi_transport *iscsit, | 1846 | iscsi_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, |
1873 | struct scsi_transport_template *scsit, | 1847 | uint16_t qdepth, uint32_t initial_cmdsn, |
1874 | uint16_t cmds_max, uint16_t qdepth, | 1848 | uint32_t *hostno) |
1875 | uint32_t initial_cmdsn, uint32_t *hostno) | ||
1876 | { | 1849 | { |
1877 | struct iscsi_cls_session *cls_session; | 1850 | struct iscsi_cls_session *cls_session; |
1878 | struct iscsi_session *session; | 1851 | struct iscsi_session *session; |
1879 | uint32_t hn; | 1852 | struct Scsi_Host *shost; |
1880 | int cmd_i; | 1853 | int cmd_i; |
1881 | 1854 | ||
1882 | cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, | 1855 | if (ep) { |
1883 | sizeof(struct iscsi_tcp_cmd_task), | 1856 | printk(KERN_ERR "iscsi_tcp: invalid ep %p.\n", ep); |
1884 | sizeof(struct iscsi_tcp_mgmt_task), | ||
1885 | initial_cmdsn, &hn); | ||
1886 | if (!cls_session) | ||
1887 | return NULL; | 1857 | return NULL; |
1888 | *hostno = hn; | ||
1889 | |||
1890 | session = class_to_transport_session(cls_session); | ||
1891 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | ||
1892 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | ||
1893 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | ||
1894 | |||
1895 | ctask->hdr = &tcp_ctask->hdr.cmd_hdr; | ||
1896 | ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE; | ||
1897 | } | 1858 | } |
1898 | 1859 | ||
1899 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { | 1860 | shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth); |
1900 | struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; | 1861 | if (!shost) |
1901 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; | 1862 | return NULL; |
1863 | shost->transportt = iscsi_tcp_scsi_transport; | ||
1864 | shost->max_lun = iscsi_max_lun; | ||
1865 | shost->max_id = 0; | ||
1866 | shost->max_channel = 0; | ||
1867 | shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; | ||
1868 | |||
1869 | if (iscsi_host_add(shost, NULL)) | ||
1870 | goto free_host; | ||
1871 | *hostno = shost->host_no; | ||
1872 | |||
1873 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, | ||
1874 | sizeof(struct iscsi_tcp_task), | ||
1875 | initial_cmdsn, 0); | ||
1876 | if (!cls_session) | ||
1877 | goto remove_host; | ||
1878 | session = cls_session->dd_data; | ||
1879 | |||
1880 | shost->can_queue = session->scsi_cmds_max; | ||
1881 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | ||
1882 | struct iscsi_task *task = session->cmds[cmd_i]; | ||
1883 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
1902 | 1884 | ||
1903 | mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr; | 1885 | task->hdr = &tcp_task->hdr.cmd_hdr; |
1886 | task->hdr_max = sizeof(tcp_task->hdr) - ISCSI_DIGEST_SIZE; | ||
1904 | } | 1887 | } |
1905 | 1888 | ||
1906 | if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) | 1889 | if (iscsi_r2tpool_alloc(session)) |
1907 | goto r2tpool_alloc_fail; | 1890 | goto remove_session; |
1908 | |||
1909 | return cls_session; | 1891 | return cls_session; |
1910 | 1892 | ||
1911 | r2tpool_alloc_fail: | 1893 | remove_session: |
1912 | iscsi_session_teardown(cls_session); | 1894 | iscsi_session_teardown(cls_session); |
1895 | remove_host: | ||
1896 | iscsi_host_remove(shost); | ||
1897 | free_host: | ||
1898 | iscsi_host_free(shost); | ||
1913 | return NULL; | 1899 | return NULL; |
1914 | } | 1900 | } |
1915 | 1901 | ||
1916 | static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) | 1902 | static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) |
1917 | { | 1903 | { |
1918 | iscsi_r2tpool_free(class_to_transport_session(cls_session)); | 1904 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
1919 | iscsi_session_teardown(cls_session); | 1905 | |
1906 | iscsi_r2tpool_free(cls_session->dd_data); | ||
1907 | |||
1908 | iscsi_host_remove(shost); | ||
1909 | iscsi_host_free(shost); | ||
1920 | } | 1910 | } |
1921 | 1911 | ||
1922 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) | 1912 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) |
@@ -1971,14 +1961,11 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
1971 | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | | 1961 | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | |
1972 | ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | | 1962 | ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | |
1973 | ISCSI_LU_RESET_TMO | | 1963 | ISCSI_LU_RESET_TMO | |
1974 | ISCSI_PING_TMO | ISCSI_RECV_TMO, | 1964 | ISCSI_PING_TMO | ISCSI_RECV_TMO | |
1965 | ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, | ||
1975 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | | 1966 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | |
1976 | ISCSI_HOST_INITIATOR_NAME | | 1967 | ISCSI_HOST_INITIATOR_NAME | |
1977 | ISCSI_HOST_NETDEV_NAME, | 1968 | ISCSI_HOST_NETDEV_NAME, |
1978 | .host_template = &iscsi_sht, | ||
1979 | .conndata_size = sizeof(struct iscsi_conn), | ||
1980 | .max_conn = 1, | ||
1981 | .max_cmd_len = 16, | ||
1982 | /* session management */ | 1969 | /* session management */ |
1983 | .create_session = iscsi_tcp_session_create, | 1970 | .create_session = iscsi_tcp_session_create, |
1984 | .destroy_session = iscsi_tcp_session_destroy, | 1971 | .destroy_session = iscsi_tcp_session_destroy, |
@@ -1992,16 +1979,14 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
1992 | .start_conn = iscsi_conn_start, | 1979 | .start_conn = iscsi_conn_start, |
1993 | .stop_conn = iscsi_tcp_conn_stop, | 1980 | .stop_conn = iscsi_tcp_conn_stop, |
1994 | /* iscsi host params */ | 1981 | /* iscsi host params */ |
1995 | .get_host_param = iscsi_tcp_host_get_param, | 1982 | .get_host_param = iscsi_host_get_param, |
1996 | .set_host_param = iscsi_host_set_param, | 1983 | .set_host_param = iscsi_host_set_param, |
1997 | /* IO */ | 1984 | /* IO */ |
1998 | .send_pdu = iscsi_conn_send_pdu, | 1985 | .send_pdu = iscsi_conn_send_pdu, |
1999 | .get_stats = iscsi_conn_get_stats, | 1986 | .get_stats = iscsi_conn_get_stats, |
2000 | .init_cmd_task = iscsi_tcp_ctask_init, | 1987 | .init_task = iscsi_tcp_task_init, |
2001 | .init_mgmt_task = iscsi_tcp_mtask_init, | 1988 | .xmit_task = iscsi_tcp_task_xmit, |
2002 | .xmit_cmd_task = iscsi_tcp_ctask_xmit, | 1989 | .cleanup_task = iscsi_tcp_cleanup_task, |
2003 | .xmit_mgmt_task = iscsi_tcp_mtask_xmit, | ||
2004 | .cleanup_cmd_task = iscsi_tcp_cleanup_ctask, | ||
2005 | /* recovery */ | 1990 | /* recovery */ |
2006 | .session_recovery_timedout = iscsi_session_recovery_timedout, | 1991 | .session_recovery_timedout = iscsi_session_recovery_timedout, |
2007 | }; | 1992 | }; |
@@ -2014,9 +1999,10 @@ iscsi_tcp_init(void) | |||
2014 | iscsi_max_lun); | 1999 | iscsi_max_lun); |
2015 | return -EINVAL; | 2000 | return -EINVAL; |
2016 | } | 2001 | } |
2017 | iscsi_tcp_transport.max_lun = iscsi_max_lun; | ||
2018 | 2002 | ||
2019 | if (!iscsi_register_transport(&iscsi_tcp_transport)) | 2003 | iscsi_tcp_scsi_transport = iscsi_register_transport( |
2004 | &iscsi_tcp_transport); | ||
2005 | if (!iscsi_tcp_scsi_transport) | ||
2020 | return -ENODEV; | 2006 | return -ENODEV; |
2021 | 2007 | ||
2022 | return 0; | 2008 | return 0; |