|
@@ -608,54 +608,12 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
|
|
|
iscsi_sw_tcp_release_conn(conn);
|
|
|
}
|
|
|
|
|
|
-static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
|
|
|
- char *buf, int *port,
|
|
|
- int (*getname)(struct socket *,
|
|
|
- struct sockaddr *,
|
|
|
- int *addrlen))
|
|
|
-{
|
|
|
- struct sockaddr_storage *addr;
|
|
|
- struct sockaddr_in6 *sin6;
|
|
|
- struct sockaddr_in *sin;
|
|
|
- int rc = 0, len;
|
|
|
-
|
|
|
- addr = kmalloc(sizeof(*addr), GFP_KERNEL);
|
|
|
- if (!addr)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (getname(sock, (struct sockaddr *) addr, &len)) {
|
|
|
- rc = -ENODEV;
|
|
|
- goto free_addr;
|
|
|
- }
|
|
|
-
|
|
|
- switch (addr->ss_family) {
|
|
|
- case AF_INET:
|
|
|
- sin = (struct sockaddr_in *)addr;
|
|
|
- spin_lock_bh(&conn->session->lock);
|
|
|
- sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
|
|
|
- *port = be16_to_cpu(sin->sin_port);
|
|
|
- spin_unlock_bh(&conn->session->lock);
|
|
|
- break;
|
|
|
- case AF_INET6:
|
|
|
- sin6 = (struct sockaddr_in6 *)addr;
|
|
|
- spin_lock_bh(&conn->session->lock);
|
|
|
- sprintf(buf, "%pI6", &sin6->sin6_addr);
|
|
|
- *port = be16_to_cpu(sin6->sin6_port);
|
|
|
- spin_unlock_bh(&conn->session->lock);
|
|
|
- break;
|
|
|
- }
|
|
|
-free_addr:
|
|
|
- kfree(addr);
|
|
|
- return rc;
|
|
|
-}
|
|
|
-
|
|
|
static int
|
|
|
iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
|
|
|
struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
|
|
|
int is_leading)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
|
|
- struct iscsi_host *ihost = shost_priv(shost);
|
|
|
+ struct iscsi_session *session = cls_session->dd_data;
|
|
|
struct iscsi_conn *conn = cls_conn->dd_data;
|
|
|
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
|
|
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,
|
|
|
"sockfd_lookup failed %d\n", err);
|
|
|
return -EEXIST;
|
|
|
}
|
|
|
- /*
|
|
|
- * copy these values now because if we drop the session
|
|
|
- * userspace may still want to query the values since we will
|
|
|
- * be using them for the reconnect
|
|
|
- */
|
|
|
- err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address,
|
|
|
- &conn->portal_port, kernel_getpeername);
|
|
|
- if (err)
|
|
|
- goto free_socket;
|
|
|
-
|
|
|
- err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address,
|
|
|
- &ihost->local_port, kernel_getsockname);
|
|
|
- if (err)
|
|
|
- goto free_socket;
|
|
|
|
|
|
err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
|
|
|
if (err)
|
|
|
goto free_socket;
|
|
|
|
|
|
+ spin_lock_bh(&session->lock);
|
|
|
/* bind iSCSI connection and socket */
|
|
|
tcp_sw_conn->sock = sock;
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
|
|
|
/* setup Socket parameters */
|
|
|
sk = sock->sk;
|
|
@@ -752,24 +698,74 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
|
|
enum iscsi_param param, char *buf)
|
|
|
{
|
|
|
struct iscsi_conn *conn = cls_conn->dd_data;
|
|
|
- int len;
|
|
|
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
|
|
+ struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
|
|
+ struct sockaddr_in6 addr;
|
|
|
+ int rc, len;
|
|
|
|
|
|
switch(param) {
|
|
|
case ISCSI_PARAM_CONN_PORT:
|
|
|
- spin_lock_bh(&conn->session->lock);
|
|
|
- len = sprintf(buf, "%hu\n", conn->portal_port);
|
|
|
- spin_unlock_bh(&conn->session->lock);
|
|
|
- break;
|
|
|
case ISCSI_PARAM_CONN_ADDRESS:
|
|
|
spin_lock_bh(&conn->session->lock);
|
|
|
- len = sprintf(buf, "%s\n", conn->portal_address);
|
|
|
+ if (!tcp_sw_conn || !tcp_sw_conn->sock) {
|
|
|
+ spin_unlock_bh(&conn->session->lock);
|
|
|
+ return -ENOTCONN;
|
|
|
+ }
|
|
|
+ rc = kernel_getpeername(tcp_sw_conn->sock,
|
|
|
+ (struct sockaddr *)&addr, &len);
|
|
|
spin_unlock_bh(&conn->session->lock);
|
|
|
- break;
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
|
|
|
+ &addr, param, buf);
|
|
|
default:
|
|
|
return iscsi_conn_get_param(cls_conn, param, buf);
|
|
|
}
|
|
|
|
|
|
- return len;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
|
|
|
+ enum iscsi_host_param param, char *buf)
|
|
|
+{
|
|
|
+ struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
|
|
|
+ struct iscsi_session *session = tcp_sw_host->session;
|
|
|
+ struct iscsi_conn *conn;
|
|
|
+ struct iscsi_tcp_conn *tcp_conn;
|
|
|
+ struct iscsi_sw_tcp_conn *tcp_sw_conn;
|
|
|
+ struct sockaddr_in6 addr;
|
|
|
+ int rc, len;
|
|
|
+
|
|
|
+ switch (param) {
|
|
|
+ case ISCSI_HOST_PARAM_IPADDRESS:
|
|
|
+ spin_lock_bh(&session->lock);
|
|
|
+ conn = session->leadconn;
|
|
|
+ if (!conn) {
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ return -ENOTCONN;
|
|
|
+ }
|
|
|
+ tcp_conn = conn->dd_data;
|
|
|
+
|
|
|
+ tcp_sw_conn = tcp_conn->dd_data;
|
|
|
+ if (!tcp_sw_conn->sock) {
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ return -ENOTCONN;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = kernel_getsockname(tcp_sw_conn->sock,
|
|
|
+ (struct sockaddr *)&addr, &len);
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
|
|
|
+ &addr, param, buf);
|
|
|
+ default:
|
|
|
+ return iscsi_host_get_param(shost, param, buf);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -797,6 +793,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
|
|
|
{
|
|
|
struct iscsi_cls_session *cls_session;
|
|
|
struct iscsi_session *session;
|
|
|
+ struct iscsi_sw_tcp_host *tcp_sw_host;
|
|
|
struct Scsi_Host *shost;
|
|
|
|
|
|
if (ep) {
|
|
@@ -804,7 +801,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
|
|
|
+ shost = iscsi_host_alloc(&iscsi_sw_tcp_sht,
|
|
|
+ sizeof(struct iscsi_sw_tcp_host), 1);
|
|
|
if (!shost)
|
|
|
return NULL;
|
|
|
shost->transportt = iscsi_sw_tcp_scsi_transport;
|
|
@@ -825,6 +823,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
|
|
|
if (!cls_session)
|
|
|
goto remove_host;
|
|
|
session = cls_session->dd_data;
|
|
|
+ tcp_sw_host = iscsi_host_priv(shost);
|
|
|
+ tcp_sw_host->session = session;
|
|
|
|
|
|
shost->can_queue = session->scsi_cmds_max;
|
|
|
if (iscsi_tcp_r2tpool_alloc(session))
|
|
@@ -929,7 +929,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
|
|
|
.start_conn = iscsi_conn_start,
|
|
|
.stop_conn = iscsi_sw_tcp_conn_stop,
|
|
|
/* iscsi host params */
|
|
|
- .get_host_param = iscsi_host_get_param,
|
|
|
+ .get_host_param = iscsi_sw_tcp_host_get_param,
|
|
|
.set_host_param = iscsi_host_set_param,
|
|
|
/* IO */
|
|
|
.send_pdu = iscsi_conn_send_pdu,
|