Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Mike Christie and committed by
James Bottomley
a79af8a6 00f3708e

+71 -67
+67 -67
drivers/scsi/iscsi_tcp.c
··· 608 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 611 static int 653 612 iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, 654 613 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, 655 614 int is_leading) 656 615 { 657 - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); 658 - struct iscsi_host *ihost = shost_priv(shost); 616 + struct iscsi_session *session = cls_session->dd_data; 659 617 struct iscsi_conn *conn = cls_conn->dd_data; 660 618 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 661 619 struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; ··· 628 670 "sockfd_lookup failed %d\n", err); 629 671 return -EEXIST; 630 672 } 631 - /* 632 - * copy these values now because if we drop the session 633 - * userspace may still want to query the values since we will 634 - * be using them for the reconnect 635 - */ 636 - err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address, 637 - &conn->portal_port, kernel_getpeername); 638 - if (err) 639 - goto free_socket; 640 - 641 - err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address, 642 - &ihost->local_port, kernel_getsockname); 643 - if (err) 644 - goto free_socket; 645 673 646 674 err = iscsi_conn_bind(cls_session, cls_conn, is_leading); 647 675 if (err) 648 676 goto free_socket; 649 677 678 + spin_lock_bh(&session->lock); 650 679 /* bind iSCSI connection and socket */ 651 680 tcp_sw_conn->sock = sock; 681 + spin_unlock_bh(&session->lock); 652 682 653 683 /* setup Socket parameters */ 654 684 sk = sock->sk; ··· 698 752 enum iscsi_param param, char *buf) 699 753 { 700 754 struct iscsi_conn *conn = cls_conn->dd_data; 701 - int len; 755 + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 756 + struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; 757 + struct sockaddr_in6 addr; 758 + int rc, len; 702 759 703 760 switch(param) { 704 761 case ISCSI_PARAM_CONN_PORT: 705 - spin_lock_bh(&conn->session->lock); 706 - len = sprintf(buf, "%hu\n", conn->portal_port); 707 - spin_unlock_bh(&conn->session->lock); 708 - break; 709 762 case ISCSI_PARAM_CONN_ADDRESS: 710 763 spin_lock_bh(&conn->session->lock); 711 - len = sprintf(buf, "%s\n", conn->portal_address); 764 + if (!tcp_sw_conn || !tcp_sw_conn->sock) { 765 + spin_unlock_bh(&conn->session->lock); 766 + return -ENOTCONN; 767 + } 768 + rc = kernel_getpeername(tcp_sw_conn->sock, 769 + (struct sockaddr *)&addr, &len); 712 770 spin_unlock_bh(&conn->session->lock); 713 - break; 771 + if (rc) 772 + return rc; 773 + 774 + return iscsi_conn_get_addr_param((struct sockaddr_storage *) 775 + &addr, param, buf); 714 776 default: 715 777 return iscsi_conn_get_param(cls_conn, param, buf); 716 778 } 717 779 718 - return len; 780 + return 0; 781 + } 782 + 783 + static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost, 784 + enum iscsi_host_param param, char *buf) 785 + { 786 + struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost); 787 + struct iscsi_session *session = tcp_sw_host->session; 788 + struct iscsi_conn *conn; 789 + struct iscsi_tcp_conn *tcp_conn; 790 + struct iscsi_sw_tcp_conn *tcp_sw_conn; 791 + struct sockaddr_in6 addr; 792 + int rc, len; 793 + 794 + switch (param) { 795 + case ISCSI_HOST_PARAM_IPADDRESS: 796 + spin_lock_bh(&session->lock); 797 + conn = session->leadconn; 798 + if (!conn) { 799 + spin_unlock_bh(&session->lock); 800 + return -ENOTCONN; 801 + } 802 + tcp_conn = conn->dd_data; 803 + 804 + tcp_sw_conn = tcp_conn->dd_data; 805 + if (!tcp_sw_conn->sock) { 806 + spin_unlock_bh(&session->lock); 807 + return -ENOTCONN; 808 + } 809 + 810 + rc = kernel_getsockname(tcp_sw_conn->sock, 811 + (struct sockaddr *)&addr, &len); 812 + spin_unlock_bh(&session->lock); 813 + if (rc) 814 + return rc; 815 + 816 + return iscsi_conn_get_addr_param((struct sockaddr_storage *) 817 + &addr, param, buf); 818 + default: 819 + return iscsi_host_get_param(shost, param, buf); 820 + } 821 + 822 + return 0; 719 823 } 720 824 721 825 static void ··· 793 797 { 794 798 struct iscsi_cls_session *cls_session; 795 799 struct iscsi_session *session; 800 + struct iscsi_sw_tcp_host *tcp_sw_host; 796 801 struct Scsi_Host *shost; 797 802 798 803 if (ep) { ··· 801 804 return NULL; 802 805 } 803 806 804 - shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1); 807 + shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 808 + sizeof(struct iscsi_sw_tcp_host), 1); 805 809 if (!shost) 806 810 return NULL; 807 811 shost->transportt = iscsi_sw_tcp_scsi_transport; ··· 823 825 if (!cls_session) 824 826 goto remove_host; 825 827 session = cls_session->dd_data; 828 + tcp_sw_host = iscsi_host_priv(shost); 829 + tcp_sw_host->session = session; 826 830 827 831 shost->can_queue = session->scsi_cmds_max; 828 832 if (iscsi_tcp_r2tpool_alloc(session)) ··· 929 929 .start_conn = iscsi_conn_start, 930 930 .stop_conn = iscsi_sw_tcp_conn_stop, 931 931 /* iscsi host params */ 932 - .get_host_param = iscsi_host_get_param, 932 + .get_host_param = iscsi_sw_tcp_host_get_param, 933 933 .set_host_param = iscsi_host_set_param, 934 934 /* IO */ 935 935 .send_pdu = iscsi_conn_send_pdu,
+4
drivers/scsi/iscsi_tcp.h
··· 55 55 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); 56 56 }; 57 57 58 + struct iscsi_sw_tcp_host { 59 + struct iscsi_session *session; 60 + }; 61 + 58 62 struct iscsi_sw_tcp_hdrbuf { 59 63 struct iscsi_hdr hdrbuf; 60 64 char hdrextbuf[ISCSI_MAX_AHS_SIZE +