aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-05-30 13:57:24 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-02 15:37:19 -0400
commit2223696192c687f2853e42b7c1e0d3ef002081fd (patch)
tree9eef082af7f3286781134226bfc98ec401d41e79 /drivers/scsi/iscsi_tcp.c
parent4e7aba73f9f6e9fe6d3fa10d3fd63cd4882ba3d0 (diff)
[SCSI] iscsi class, qla4xxx, iscsi_tcp: export local address
This patch exports the local address for the session. For qla4xxx this is the ip of the hba's port. For software this is the src addr of the socket. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Cc: David C Somayajulu <david.somayajulu@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c127
1 files changed, 98 insertions, 29 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7ce177e30a53..da66fb524b5b 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1870,18 +1870,22 @@ tcp_conn_alloc_fail:
1870static void 1870static void
1871iscsi_tcp_release_conn(struct iscsi_conn *conn) 1871iscsi_tcp_release_conn(struct iscsi_conn *conn)
1872{ 1872{
1873 struct iscsi_session *session = conn->session;
1873 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1874 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1875 struct socket *sock = tcp_conn->sock;
1874 1876
1875 if (!tcp_conn->sock) 1877 if (!sock)
1876 return; 1878 return;
1877 1879
1878 sock_hold(tcp_conn->sock->sk); 1880 sock_hold(sock->sk);
1879 iscsi_conn_restore_callbacks(tcp_conn); 1881 iscsi_conn_restore_callbacks(tcp_conn);
1880 sock_put(tcp_conn->sock->sk); 1882 sock_put(sock->sk);
1881 1883
1882 sockfd_put(tcp_conn->sock); 1884 spin_lock_bh(&session->lock);
1883 tcp_conn->sock = NULL; 1885 tcp_conn->sock = NULL;
1884 conn->recv_lock = NULL; 1886 conn->recv_lock = NULL;
1887 spin_unlock_bh(&session->lock);
1888 sockfd_put(sock);
1885} 1889}
1886 1890
1887static void 1891static void
@@ -1912,6 +1916,46 @@ iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
1912 tcp_conn->hdr_size = sizeof(struct iscsi_hdr); 1916 tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
1913} 1917}
1914 1918
1919static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
1920 char *buf, int *port,
1921 int (*getname)(struct socket *, struct sockaddr *,
1922 int *addrlen))
1923{
1924 struct sockaddr_storage *addr;
1925 struct sockaddr_in6 *sin6;
1926 struct sockaddr_in *sin;
1927 int rc = 0, len;
1928
1929 addr = kmalloc(GFP_KERNEL, sizeof(*addr));
1930 if (!addr)
1931 return -ENOMEM;
1932
1933 if (getname(sock, (struct sockaddr *) addr, &len)) {
1934 rc = -ENODEV;
1935 goto free_addr;
1936 }
1937
1938 switch (addr->ss_family) {
1939 case AF_INET:
1940 sin = (struct sockaddr_in *)addr;
1941 spin_lock_bh(&conn->session->lock);
1942 sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
1943 *port = be16_to_cpu(sin->sin_port);
1944 spin_unlock_bh(&conn->session->lock);
1945 break;
1946 case AF_INET6:
1947 sin6 = (struct sockaddr_in6 *)addr;
1948 spin_lock_bh(&conn->session->lock);
1949 sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
1950 *port = be16_to_cpu(sin6->sin6_port);
1951 spin_unlock_bh(&conn->session->lock);
1952 break;
1953 }
1954free_addr:
1955 kfree(addr);
1956 return rc;
1957}
1958
1915static int 1959static int
1916iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, 1960iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
1917 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, 1961 struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -1929,10 +1973,24 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
1929 printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); 1973 printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
1930 return -EEXIST; 1974 return -EEXIST;
1931 } 1975 }
1976 /*
1977 * copy these values now because if we drop the session
1978 * userspace may still want to query the values since we will
1979 * be using them for the reconnect
1980 */
1981 err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,
1982 &conn->portal_port, kernel_getpeername);
1983 if (err)
1984 goto free_socket;
1985
1986 err = iscsi_tcp_get_addr(conn, sock, conn->local_address,
1987 &conn->local_port, kernel_getsockname);
1988 if (err)
1989 goto free_socket;
1932 1990
1933 err = iscsi_conn_bind(cls_session, cls_conn, is_leading); 1991 err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
1934 if (err) 1992 if (err)
1935 return err; 1993 goto free_socket;
1936 1994
1937 /* bind iSCSI connection and socket */ 1995 /* bind iSCSI connection and socket */
1938 tcp_conn->sock = sock; 1996 tcp_conn->sock = sock;
@@ -1956,8 +2014,11 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
1956 * set receive state machine into initial state 2014 * set receive state machine into initial state
1957 */ 2015 */
1958 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; 2016 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
1959
1960 return 0; 2017 return 0;
2018
2019free_socket:
2020 sockfd_put(sock);
2021 return err;
1961} 2022}
1962 2023
1963/* called with host lock */ 2024/* called with host lock */
@@ -2077,33 +2138,18 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
2077 enum iscsi_param param, char *buf) 2138 enum iscsi_param param, char *buf)
2078{ 2139{
2079 struct iscsi_conn *conn = cls_conn->dd_data; 2140 struct iscsi_conn *conn = cls_conn->dd_data;
2080 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
2081 struct inet_sock *inet;
2082 struct ipv6_pinfo *np;
2083 struct sock *sk;
2084 int len; 2141 int len;
2085 2142
2086 switch(param) { 2143 switch(param) {
2087 case ISCSI_PARAM_CONN_PORT: 2144 case ISCSI_PARAM_CONN_PORT:
2088 if (!tcp_conn->sock) 2145 spin_lock_bh(&conn->session->lock);
2089 return -EINVAL; 2146 len = sprintf(buf, "%hu\n", conn->portal_port);
2090 2147 spin_unlock_bh(&conn->session->lock);
2091 inet = inet_sk(tcp_conn->sock->sk);
2092 len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
2093 break; 2148 break;
2094 case ISCSI_PARAM_CONN_ADDRESS: 2149 case ISCSI_PARAM_CONN_ADDRESS:
2095 if (!tcp_conn->sock) 2150 spin_lock_bh(&conn->session->lock);
2096 return -EINVAL; 2151 len = sprintf(buf, "%s\n", conn->portal_address);
2097 2152 spin_unlock_bh(&conn->session->lock);
2098 sk = tcp_conn->sock->sk;
2099 if (sk->sk_family == PF_INET) {
2100 inet = inet_sk(sk);
2101 len = sprintf(buf, NIPQUAD_FMT "\n",
2102 NIPQUAD(inet->daddr));
2103 } else {
2104 np = inet6_sk(sk);
2105 len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
2106 }
2107 break; 2153 break;
2108 default: 2154 default:
2109 return iscsi_conn_get_param(cls_conn, param, buf); 2155 return iscsi_conn_get_param(cls_conn, param, buf);
@@ -2112,6 +2158,29 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
2112 return len; 2158 return len;
2113} 2159}
2114 2160
2161static int
2162iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
2163 char *buf)
2164{
2165 struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
2166 int len;
2167
2168 switch (param) {
2169 case ISCSI_HOST_PARAM_IPADDRESS:
2170 spin_lock_bh(&session->lock);
2171 if (!session->leadconn)
2172 len = -ENODEV;
2173 else
2174 len = sprintf(buf, "%s\n",
2175 session->leadconn->local_address);
2176 spin_unlock_bh(&session->lock);
2177 break;
2178 default:
2179 return iscsi_host_get_param(shost, param, buf);
2180 }
2181 return len;
2182}
2183
2115static void 2184static void
2116iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) 2185iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
2117{ 2186{
@@ -2233,7 +2302,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
2233 ISCSI_TARGET_NAME | ISCSI_TPGT | 2302 ISCSI_TARGET_NAME | ISCSI_TPGT |
2234 ISCSI_USERNAME | ISCSI_PASSWORD | 2303 ISCSI_USERNAME | ISCSI_PASSWORD |
2235 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN, 2304 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
2236 .host_param_mask = ISCSI_HOST_HWADDRESS | 2305 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
2237 ISCSI_HOST_INITIATOR_NAME, 2306 ISCSI_HOST_INITIATOR_NAME,
2238 .host_template = &iscsi_sht, 2307 .host_template = &iscsi_sht,
2239 .conndata_size = sizeof(struct iscsi_conn), 2308 .conndata_size = sizeof(struct iscsi_conn),
@@ -2252,7 +2321,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
2252 .start_conn = iscsi_conn_start, 2321 .start_conn = iscsi_conn_start,
2253 .stop_conn = iscsi_tcp_conn_stop, 2322 .stop_conn = iscsi_tcp_conn_stop,
2254 /* iscsi host params */ 2323 /* iscsi host params */
2255 .get_host_param = iscsi_host_get_param, 2324 .get_host_param = iscsi_tcp_host_get_param,
2256 .set_host_param = iscsi_host_set_param, 2325 .set_host_param = iscsi_host_set_param,
2257 /* IO */ 2326 /* IO */
2258 .send_pdu = iscsi_conn_send_pdu, 2327 .send_pdu = iscsi_conn_send_pdu,