aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-02-16 16:04:36 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-24 12:41:10 -0500
commita79af8a64d395bd89de8695a5ea5e1a7f01f02a8 (patch)
tree510c13cb1e283c2809c0ca7e8d5f2dedd9ad6b76 /drivers
parent00f3708e6ed1698d6aee3901ea991197e31a8007 (diff)
[SCSI] iscsi_tcp: use iscsi_conn_get_addr_param libiscsi function
This has iscsi_tcp use the iscsi_conn_get_addr_param libiscsi function. It also drops the use of the libiscsi session portal buffers, so they can be removed in the next patches. Instead of copying the values at bind time we get them during get() time. If we are not connected userspace will now get -ENOTCONN, so it knows that connection is disconnected instead of a possible stale value. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/iscsi_tcp.c134
-rw-r--r--drivers/scsi/iscsi_tcp.h4
2 files changed, 71 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,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 94644bad0ed7..666fe09378fa 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -55,6 +55,10 @@ struct iscsi_sw_tcp_conn {
55 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); 55 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
56}; 56};
57 57
58struct iscsi_sw_tcp_host {
59 struct iscsi_session *session;
60};
61
58struct iscsi_sw_tcp_hdrbuf { 62struct iscsi_sw_tcp_hdrbuf {
59 struct iscsi_hdr hdrbuf; 63 struct iscsi_hdr hdrbuf;
60 char hdrextbuf[ISCSI_MAX_AHS_SIZE + 64 char hdrextbuf[ISCSI_MAX_AHS_SIZE +