diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2007-05-30 13:57:24 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-02 15:37:19 -0400 |
commit | 2223696192c687f2853e42b7c1e0d3ef002081fd (patch) | |
tree | 9eef082af7f3286781134226bfc98ec401d41e79 /drivers/scsi | |
parent | 4e7aba73f9f6e9fe6d3fa10d3fd63cd4882ba3d0 (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')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 127 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 8 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 4 |
3 files changed, 108 insertions, 31 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: | |||
1870 | static void | 1870 | static void |
1871 | iscsi_tcp_release_conn(struct iscsi_conn *conn) | 1871 | iscsi_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 | ||
1887 | static void | 1891 | static 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 | ||
1919 | static 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 | } | ||
1954 | free_addr: | ||
1955 | kfree(addr); | ||
1956 | return rc; | ||
1957 | } | ||
1958 | |||
1915 | static int | 1959 | static int |
1916 | iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | 1960 | iscsi_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 | |||
2019 | free_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 | ||
2161 | static int | ||
2162 | iscsi_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 | |||
2115 | static void | 2184 | static void |
2116 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | 2185 | iscsi_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, |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 315ab691056f..b87b460832ea 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -106,6 +106,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
106 | .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | | 106 | .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | |
107 | ISCSI_TARGET_NAME | ISCSI_TPGT, | 107 | ISCSI_TARGET_NAME | ISCSI_TPGT, |
108 | .host_param_mask = ISCSI_HOST_HWADDRESS | | 108 | .host_param_mask = ISCSI_HOST_HWADDRESS | |
109 | ISCSI_HOST_IPADDRESS | | ||
109 | ISCSI_HOST_INITIATOR_NAME, | 110 | ISCSI_HOST_INITIATOR_NAME, |
110 | .sessiondata_size = sizeof(struct ddb_entry), | 111 | .sessiondata_size = sizeof(struct ddb_entry), |
111 | .host_template = &qla4xxx_driver_template, | 112 | .host_template = &qla4xxx_driver_template, |
@@ -192,8 +193,13 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost, | |||
192 | case ISCSI_HOST_PARAM_HWADDRESS: | 193 | case ISCSI_HOST_PARAM_HWADDRESS: |
193 | len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN); | 194 | len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN); |
194 | break; | 195 | break; |
196 | case ISCSI_HOST_PARAM_IPADDRESS: | ||
197 | len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0], | ||
198 | ha->ip_address[1], ha->ip_address[2], | ||
199 | ha->ip_address[3]); | ||
200 | break; | ||
195 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 201 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
196 | len = sprintf(buf, ha->name_string); | 202 | len = sprintf(buf, "%s\n", ha->name_string); |
197 | break; | 203 | break; |
198 | default: | 204 | default: |
199 | return -ENOSYS; | 205 | return -ENOSYS; |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 859bd2100856..9b54eea20560 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #define ISCSI_SESSION_ATTRS 15 | 33 | #define ISCSI_SESSION_ATTRS 15 |
34 | #define ISCSI_CONN_ATTRS 11 | 34 | #define ISCSI_CONN_ATTRS 11 |
35 | #define ISCSI_HOST_ATTRS 2 | 35 | #define ISCSI_HOST_ATTRS 3 |
36 | #define ISCSI_TRANSPORT_VERSION "2.0-724" | 36 | #define ISCSI_TRANSPORT_VERSION "2.0-724" |
37 | 37 | ||
38 | struct iscsi_internal { | 38 | struct iscsi_internal { |
@@ -1261,6 +1261,7 @@ show_host_param_##param(struct class_device *cdev, char *buf) \ | |||
1261 | static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \ | 1261 | static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \ |
1262 | NULL); | 1262 | NULL); |
1263 | 1263 | ||
1264 | iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS); | ||
1264 | iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS); | 1265 | iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS); |
1265 | iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME); | 1266 | iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME); |
1266 | 1267 | ||
@@ -1398,6 +1399,7 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1398 | priv->t.host_size = sizeof(struct iscsi_host); | 1399 | priv->t.host_size = sizeof(struct iscsi_host); |
1399 | transport_container_register(&priv->t.host_attrs); | 1400 | transport_container_register(&priv->t.host_attrs); |
1400 | 1401 | ||
1402 | SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS); | ||
1401 | SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS); | 1403 | SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS); |
1402 | SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME); | 1404 | SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME); |
1403 | BUG_ON(count > ISCSI_HOST_ATTRS); | 1405 | BUG_ON(count > ISCSI_HOST_ATTRS); |