diff options
-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 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 2 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 8 |
5 files changed, 118 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); |
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 81a542506dfe..642998069e00 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h | |||
@@ -271,11 +271,13 @@ enum iscsi_param { | |||
271 | enum iscsi_host_param { | 271 | enum iscsi_host_param { |
272 | ISCSI_HOST_PARAM_HWADDRESS, | 272 | ISCSI_HOST_PARAM_HWADDRESS, |
273 | ISCSI_HOST_PARAM_INITIATOR_NAME, | 273 | ISCSI_HOST_PARAM_INITIATOR_NAME, |
274 | ISCSI_HOST_PARAM_IPADDRESS, | ||
274 | ISCSI_HOST_PARAM_MAX, | 275 | ISCSI_HOST_PARAM_MAX, |
275 | }; | 276 | }; |
276 | 277 | ||
277 | #define ISCSI_HOST_HWADDRESS (1 << ISCSI_HOST_PARAM_HWADDRESS) | 278 | #define ISCSI_HOST_HWADDRESS (1 << ISCSI_HOST_PARAM_HWADDRESS) |
278 | #define ISCSI_HOST_INITIATOR_NAME (1 << ISCSI_HOST_PARAM_INITIATOR_NAME) | 279 | #define ISCSI_HOST_INITIATOR_NAME (1 << ISCSI_HOST_PARAM_INITIATOR_NAME) |
280 | #define ISCSI_HOST_IPADDRESS (1 << ISCSI_HOST_PARAM_IPADDRESS) | ||
279 | 281 | ||
280 | #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) | 282 | #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) |
281 | #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) | 283 | #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 2f303a3b270e..eea33f7b1544 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -72,6 +72,8 @@ struct iscsi_nopin; | |||
72 | #define ISCSI_AGE_SHIFT 28 | 72 | #define ISCSI_AGE_SHIFT 28 |
73 | #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) | 73 | #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) |
74 | 74 | ||
75 | #define ISCSI_ADDRESS_BUF_LEN 64 | ||
76 | |||
75 | struct iscsi_mgmt_task { | 77 | struct iscsi_mgmt_task { |
76 | /* | 78 | /* |
77 | * Becuae LLDs allocate their hdr differently, this is a pointer to | 79 | * Becuae LLDs allocate their hdr differently, this is a pointer to |
@@ -174,6 +176,12 @@ struct iscsi_conn { | |||
174 | /* values userspace uses to id a conn */ | 176 | /* values userspace uses to id a conn */ |
175 | int persistent_port; | 177 | int persistent_port; |
176 | char *persistent_address; | 178 | char *persistent_address; |
179 | /* remote portal currently connected to */ | ||
180 | int portal_port; | ||
181 | char portal_address[ISCSI_ADDRESS_BUF_LEN]; | ||
182 | /* local address */ | ||
183 | int local_port; | ||
184 | char local_address[ISCSI_ADDRESS_BUF_LEN]; | ||
177 | 185 | ||
178 | /* MIB-statistics */ | 186 | /* MIB-statistics */ |
179 | uint64_t txdata_octets; | 187 | uint64_t txdata_octets; |