aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c134
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
611static 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 }
647free_addr:
648 kfree(addr);
649 return rc;
650}
651
652static int 611static int
653iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, 612iscsi_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
729static 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
775static void 771static 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,