diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 134 |
1 files changed, 67 insertions, 67 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index fec47de72535..a860452a8f71 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -608,54 +608,12 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | |||
608 | iscsi_sw_tcp_release_conn(conn); | 608 | iscsi_sw_tcp_release_conn(conn); |
609 | } | 609 | } |
610 | 610 | ||
611 | static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock, | ||
612 | char *buf, int *port, | ||
613 | int (*getname)(struct socket *, | ||
614 | struct sockaddr *, | ||
615 | int *addrlen)) | ||
616 | { | ||
617 | struct sockaddr_storage *addr; | ||
618 | struct sockaddr_in6 *sin6; | ||
619 | struct sockaddr_in *sin; | ||
620 | int rc = 0, len; | ||
621 | |||
622 | addr = kmalloc(sizeof(*addr), GFP_KERNEL); | ||
623 | if (!addr) | ||
624 | return -ENOMEM; | ||
625 | |||
626 | if (getname(sock, (struct sockaddr *) addr, &len)) { | ||
627 | rc = -ENODEV; | ||
628 | goto free_addr; | ||
629 | } | ||
630 | |||
631 | switch (addr->ss_family) { | ||
632 | case AF_INET: | ||
633 | sin = (struct sockaddr_in *)addr; | ||
634 | spin_lock_bh(&conn->session->lock); | ||
635 | sprintf(buf, "%pI4", &sin->sin_addr.s_addr); | ||
636 | *port = be16_to_cpu(sin->sin_port); | ||
637 | spin_unlock_bh(&conn->session->lock); | ||
638 | break; | ||
639 | case AF_INET6: | ||
640 | sin6 = (struct sockaddr_in6 *)addr; | ||
641 | spin_lock_bh(&conn->session->lock); | ||
642 | sprintf(buf, "%pI6", &sin6->sin6_addr); | ||
643 | *port = be16_to_cpu(sin6->sin6_port); | ||
644 | spin_unlock_bh(&conn->session->lock); | ||
645 | break; | ||
646 | } | ||
647 | free_addr: | ||
648 | kfree(addr); | ||
649 | return rc; | ||
650 | } | ||
651 | |||
652 | static int | 611 | static int |
653 | iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, | 612 | iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, |
654 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, | 613 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, |
655 | int is_leading) | 614 | int is_leading) |
656 | { | 615 | { |
657 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 616 | struct iscsi_session *session = cls_session->dd_data; |
658 | struct iscsi_host *ihost = shost_priv(shost); | ||
659 | struct iscsi_conn *conn = cls_conn->dd_data; | 617 | struct iscsi_conn *conn = cls_conn->dd_data; |
660 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 618 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
661 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; | 619 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; |
@@ -670,27 +628,15 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
670 | "sockfd_lookup failed %d\n", err); | 628 | "sockfd_lookup failed %d\n", err); |
671 | return -EEXIST; | 629 | return -EEXIST; |
672 | } | 630 | } |
673 | /* | ||
674 | * copy these values now because if we drop the session | ||
675 | * userspace may still want to query the values since we will | ||
676 | * be using them for the reconnect | ||
677 | */ | ||
678 | err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address, | ||
679 | &conn->portal_port, kernel_getpeername); | ||
680 | if (err) | ||
681 | goto free_socket; | ||
682 | |||
683 | err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address, | ||
684 | &ihost->local_port, kernel_getsockname); | ||
685 | if (err) | ||
686 | goto free_socket; | ||
687 | 631 | ||
688 | err = iscsi_conn_bind(cls_session, cls_conn, is_leading); | 632 | err = iscsi_conn_bind(cls_session, cls_conn, is_leading); |
689 | if (err) | 633 | if (err) |
690 | goto free_socket; | 634 | goto free_socket; |
691 | 635 | ||
636 | spin_lock_bh(&session->lock); | ||
692 | /* bind iSCSI connection and socket */ | 637 | /* bind iSCSI connection and socket */ |
693 | tcp_sw_conn->sock = sock; | 638 | tcp_sw_conn->sock = sock; |
639 | spin_unlock_bh(&session->lock); | ||
694 | 640 | ||
695 | /* setup Socket parameters */ | 641 | /* setup Socket parameters */ |
696 | sk = sock->sk; | 642 | sk = sock->sk; |
@@ -752,24 +698,74 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
752 | enum iscsi_param param, char *buf) | 698 | enum iscsi_param param, char *buf) |
753 | { | 699 | { |
754 | struct iscsi_conn *conn = cls_conn->dd_data; | 700 | struct iscsi_conn *conn = cls_conn->dd_data; |
755 | int len; | 701 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
702 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; | ||
703 | struct sockaddr_in6 addr; | ||
704 | int rc, len; | ||
756 | 705 | ||
757 | switch(param) { | 706 | switch(param) { |
758 | case ISCSI_PARAM_CONN_PORT: | 707 | case ISCSI_PARAM_CONN_PORT: |
759 | spin_lock_bh(&conn->session->lock); | ||
760 | len = sprintf(buf, "%hu\n", conn->portal_port); | ||
761 | spin_unlock_bh(&conn->session->lock); | ||
762 | break; | ||
763 | case ISCSI_PARAM_CONN_ADDRESS: | 708 | case ISCSI_PARAM_CONN_ADDRESS: |
764 | spin_lock_bh(&conn->session->lock); | 709 | spin_lock_bh(&conn->session->lock); |
765 | len = sprintf(buf, "%s\n", conn->portal_address); | 710 | if (!tcp_sw_conn || !tcp_sw_conn->sock) { |
711 | spin_unlock_bh(&conn->session->lock); | ||
712 | return -ENOTCONN; | ||
713 | } | ||
714 | rc = kernel_getpeername(tcp_sw_conn->sock, | ||
715 | (struct sockaddr *)&addr, &len); | ||
766 | spin_unlock_bh(&conn->session->lock); | 716 | spin_unlock_bh(&conn->session->lock); |
767 | break; | 717 | if (rc) |
718 | return rc; | ||
719 | |||
720 | return iscsi_conn_get_addr_param((struct sockaddr_storage *) | ||
721 | &addr, param, buf); | ||
768 | default: | 722 | default: |
769 | return iscsi_conn_get_param(cls_conn, param, buf); | 723 | return iscsi_conn_get_param(cls_conn, param, buf); |
770 | } | 724 | } |
771 | 725 | ||
772 | return len; | 726 | return 0; |
727 | } | ||
728 | |||
729 | static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost, | ||
730 | enum iscsi_host_param param, char *buf) | ||
731 | { | ||
732 | struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost); | ||
733 | struct iscsi_session *session = tcp_sw_host->session; | ||
734 | struct iscsi_conn *conn; | ||
735 | struct iscsi_tcp_conn *tcp_conn; | ||
736 | struct iscsi_sw_tcp_conn *tcp_sw_conn; | ||
737 | struct sockaddr_in6 addr; | ||
738 | int rc, len; | ||
739 | |||
740 | switch (param) { | ||
741 | case ISCSI_HOST_PARAM_IPADDRESS: | ||
742 | spin_lock_bh(&session->lock); | ||
743 | conn = session->leadconn; | ||
744 | if (!conn) { | ||
745 | spin_unlock_bh(&session->lock); | ||
746 | return -ENOTCONN; | ||
747 | } | ||
748 | tcp_conn = conn->dd_data; | ||
749 | |||
750 | tcp_sw_conn = tcp_conn->dd_data; | ||
751 | if (!tcp_sw_conn->sock) { | ||
752 | spin_unlock_bh(&session->lock); | ||
753 | return -ENOTCONN; | ||
754 | } | ||
755 | |||
756 | rc = kernel_getsockname(tcp_sw_conn->sock, | ||
757 | (struct sockaddr *)&addr, &len); | ||
758 | spin_unlock_bh(&session->lock); | ||
759 | if (rc) | ||
760 | return rc; | ||
761 | |||
762 | return iscsi_conn_get_addr_param((struct sockaddr_storage *) | ||
763 | &addr, param, buf); | ||
764 | default: | ||
765 | return iscsi_host_get_param(shost, param, buf); | ||
766 | } | ||
767 | |||
768 | return 0; | ||
773 | } | 769 | } |
774 | 770 | ||
775 | static void | 771 | static void |
@@ -797,6 +793,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
797 | { | 793 | { |
798 | struct iscsi_cls_session *cls_session; | 794 | struct iscsi_cls_session *cls_session; |
799 | struct iscsi_session *session; | 795 | struct iscsi_session *session; |
796 | struct iscsi_sw_tcp_host *tcp_sw_host; | ||
800 | struct Scsi_Host *shost; | 797 | struct Scsi_Host *shost; |
801 | 798 | ||
802 | if (ep) { | 799 | if (ep) { |
@@ -804,7 +801,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
804 | return NULL; | 801 | return NULL; |
805 | } | 802 | } |
806 | 803 | ||
807 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1); | 804 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, |
805 | sizeof(struct iscsi_sw_tcp_host), 1); | ||
808 | if (!shost) | 806 | if (!shost) |
809 | return NULL; | 807 | return NULL; |
810 | shost->transportt = iscsi_sw_tcp_scsi_transport; | 808 | shost->transportt = iscsi_sw_tcp_scsi_transport; |
@@ -825,6 +823,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
825 | if (!cls_session) | 823 | if (!cls_session) |
826 | goto remove_host; | 824 | goto remove_host; |
827 | session = cls_session->dd_data; | 825 | session = cls_session->dd_data; |
826 | tcp_sw_host = iscsi_host_priv(shost); | ||
827 | tcp_sw_host->session = session; | ||
828 | 828 | ||
829 | shost->can_queue = session->scsi_cmds_max; | 829 | shost->can_queue = session->scsi_cmds_max; |
830 | if (iscsi_tcp_r2tpool_alloc(session)) | 830 | if (iscsi_tcp_r2tpool_alloc(session)) |
@@ -929,7 +929,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = { | |||
929 | .start_conn = iscsi_conn_start, | 929 | .start_conn = iscsi_conn_start, |
930 | .stop_conn = iscsi_sw_tcp_conn_stop, | 930 | .stop_conn = iscsi_sw_tcp_conn_stop, |
931 | /* iscsi host params */ | 931 | /* iscsi host params */ |
932 | .get_host_param = iscsi_host_get_param, | 932 | .get_host_param = iscsi_sw_tcp_host_get_param, |
933 | .set_host_param = iscsi_host_set_param, | 933 | .set_host_param = iscsi_host_set_param, |
934 | /* IO */ | 934 | /* IO */ |
935 | .send_pdu = iscsi_conn_send_pdu, | 935 | .send_pdu = iscsi_conn_send_pdu, |