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;
"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;
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
{
struct iscsi_cls_session *cls_session;
struct iscsi_session *session;
+ struct iscsi_sw_tcp_host *tcp_sw_host;
struct Scsi_Host *shost;
if (ep) {
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;
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))
.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,