summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/iscsi_if.h2
-rw-r--r--kernel/iscsi_tcp.c123
-rw-r--r--kernel/scsi_transport_iscsi.c4
-rw-r--r--usr/initiator.h8
-rw-r--r--usr/iscsi_sysfs.c58
-rw-r--r--usr/iscsi_sysfs.h2
-rw-r--r--usr/iscsiadm.c11
7 files changed, 149 insertions, 59 deletions
diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index a9812a7..3911c31 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
@@ -271,11 +271,13 @@ enum iscsi_param {
enum iscsi_host_param {
ISCSI_HOST_PARAM_HWADDRESS,
ISCSI_HOST_PARAM_INITIATOR_NAME,
+ ISCSI_HOST_PARAM_IPADDRESS,
ISCSI_HOST_PARAM_MAX,
};
#define ISCSI_HOST_HWADDRESS (1 << ISCSI_HOST_PARAM_HWADDRESS)
#define ISCSI_HOST_INITIATOR_NAME (1 << ISCSI_HOST_PARAM_INITIATOR_NAME)
+#define ISCSI_HOST_IPADDRESS (1 << ISCSI_HOST_PARAM_IPADDRESS)
#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
diff --git a/kernel/iscsi_tcp.c b/kernel/iscsi_tcp.c
index 80b52e7..2fc7853 100644
--- a/kernel/iscsi_tcp.c
+++ b/kernel/iscsi_tcp.c
@@ -1869,18 +1869,22 @@ tcp_conn_alloc_fail:
static void
iscsi_tcp_release_conn(struct iscsi_conn *conn)
{
+ struct iscsi_session *session = conn->session;
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct socket *sock = tcp_conn->sock;
- if (!tcp_conn->sock)
+ if (!sock)
return;
- sock_hold(tcp_conn->sock->sk);
+ sock_hold(sock->sk);
iscsi_conn_restore_callbacks(tcp_conn);
- sock_put(tcp_conn->sock->sk);
+ sock_put(sock->sk);
- sockfd_put(tcp_conn->sock);
+ spin_lock_bh(&session->lock);
tcp_conn->sock = NULL;
conn->recv_lock = NULL;
+ spin_unlock_bh(&session->lock);
+ sockfd_put(sock);
}
static void
@@ -2071,39 +2075,83 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
return 0;
}
+static int iscsi_tcp_get_addr(struct iscsi_session *session,
+ char *buf, int peer, int get_addr)
+{
+ struct iscsi_tcp_conn *tcp_conn;
+ struct sockaddr_storage *addr;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+ int rc = 0, len;
+
+ addr = kmalloc(GFP_KERNEL, sizeof(*addr));
+ if (!addr)
+ return -ENOMEM;
+
+ spin_lock_bh(&session->lock);
+ if (!session->leadconn) {
+ len = -ENODEV;
+ goto free_addr;
+ }
+ tcp_conn = session->leadconn->dd_data;
+
+ if (!tcp_conn->sock) {
+ rc = -ENODEV;
+ goto free_addr;
+ }
+
+ if (tcp_conn->sock->ops->getname(tcp_conn->sock,
+ (struct sockaddr *) addr, &len,
+ peer)) {
+ rc = -ENODEV;
+ goto free_addr;
+ }
+
+ if (get_addr) {
+ switch (addr->ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)addr;
+ rc = sprintf(buf, NIPQUAD_FMT "\n",
+ NIPQUAD(sin->sin_addr.s_addr));
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)addr;
+ rc = sprintf(buf, NIP6_FMT "\n",
+ NIP6(sin6->sin6_addr));
+ break;
+ }
+ } else {
+ switch (addr->ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)addr;
+ rc = sprintf(buf, "%hu\n",
+ be16_to_cpu(sin->sin_port ));
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)addr;
+ rc = sprintf(buf, "%hu\n",
+ be16_to_cpu(sin6->sin6_port ));
+ break;
+ }
+ }
+free_addr:
+ spin_unlock_bh(&session->lock);
+ kfree(addr);
+ return len;
+}
+
static int
iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
enum iscsi_param param, char *buf)
{
struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct inet_sock *inet;
- struct ipv6_pinfo *np;
- struct sock *sk;
int len;
switch(param) {
case ISCSI_PARAM_CONN_PORT:
- if (!tcp_conn->sock)
- return -EINVAL;
-
- inet = inet_sk(tcp_conn->sock->sk);
- len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport));
- break;
+ return iscsi_tcp_get_addr(conn->session, buf, 1, 0);
case ISCSI_PARAM_CONN_ADDRESS:
- if (!tcp_conn->sock)
- return -EINVAL;
-
- sk = tcp_conn->sock->sk;
- if (sk->sk_family == PF_INET) {
- inet = inet_sk(sk);
- len = sprintf(buf, NIPQUAD_FMT "\n",
- NIPQUAD(inet->daddr));
- } else {
- np = inet6_sk(sk);
- len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
- }
- break;
+ return iscsi_tcp_get_addr(conn->session, buf, 1, 1);
default:
return iscsi_conn_get_param(cls_conn, param, buf);
}
@@ -2111,6 +2159,23 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
return len;
}
+static int
+iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ char *buf)
+{
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ int len;
+
+ switch (param) {
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ len = iscsi_tcp_get_addr(session, buf, 0, 1);
+ break;
+ default:
+ return iscsi_host_get_param(shost, param, buf);
+ }
+ return len;
+}
+
static void
iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
{
@@ -2225,7 +2290,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
ISCSI_TARGET_NAME | ISCSI_TPGT |
ISCSI_USERNAME | ISCSI_PASSWORD |
ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,
- .host_param_mask = ISCSI_HOST_HWADDRESS |
+ .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
ISCSI_HOST_INITIATOR_NAME,
.host_template = &iscsi_sht,
.conndata_size = sizeof(struct iscsi_conn),
@@ -2244,7 +2309,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
.start_conn = iscsi_conn_start,
.stop_conn = iscsi_tcp_conn_stop,
/* iscsi host params */
- .get_host_param = iscsi_host_get_param,
+ .get_host_param = iscsi_tcp_host_get_param,
.set_host_param = iscsi_host_set_param,
/* IO */
.send_pdu = iscsi_conn_send_pdu,
diff --git a/kernel/scsi_transport_iscsi.c b/kernel/scsi_transport_iscsi.c
index ee90569..e30fcf7 100644
--- a/kernel/scsi_transport_iscsi.c
+++ b/kernel/scsi_transport_iscsi.c
@@ -32,7 +32,7 @@
#define ISCSI_SESSION_ATTRS 15
#define ISCSI_CONN_ATTRS 11
-#define ISCSI_HOST_ATTRS 2
+#define ISCSI_HOST_ATTRS 3
#define ISCSI_TRANSPORT_VERSION "2.0-724"
struct iscsi_internal {
@@ -1261,6 +1261,7 @@ show_host_param_##param(struct class_device *cdev, char *buf) \
static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
NULL);
+iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
@@ -1398,6 +1399,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
priv->t.host_size = sizeof(struct iscsi_host);
transport_container_register(&priv->t.host_attrs);
+ SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
BUG_ON(count > ISCSI_HOST_ATTRS);
diff --git a/usr/initiator.h b/usr/initiator.h
index 5ddf555..1a1a7fa 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
@@ -276,6 +276,7 @@ typedef struct iscsi_session {
struct session_info {
struct list_head list;
char targetname[TARGET_NAME_MAXLEN + 1];
+ char local_address[NI_MAXHOST + 1];
char address[NI_MAXHOST + 1];
char persistent_address[NI_MAXHOST + 1];
char hwaddress[ISCSI_MAX_IFACE_LEN];
@@ -285,6 +286,13 @@ struct session_info {
int tpgt;
};
+struct host_info {
+ char iname[TARGET_NAME_MAXLEN + 1];
+ char hwaddress[ISCSI_MAX_IFACE_LEN];
+ char ipaddress[NI_MAXHOST + 1];
+ int host_no;
+};
+
/* login.c */
#define ISCSI_SESSION_TYPE_NORMAL 0
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
index e75dac7..d5a5258 100644
--- a/usr/iscsi_sysfs.c
+++ b/usr/iscsi_sysfs.c
@@ -377,27 +377,22 @@ int get_netdev_from_mac(char *address, char *dev)
int sysfs_for_each_host(void *data, int *nr_found, sysfs_host_op_fn *fn)
{
struct dirent **namelist;
- int rc = 0, i, n, host_no;
- char *iname, *hwaddress;
+ int rc = 0, i, n;
+ struct host_info *info;
- iname = malloc(TARGET_NAME_MAXLEN + 1);
- if (!iname)
+ info = calloc(1, sizeof(*info));
+ if (!info)
return ENOMEM;
- hwaddress = malloc(ISCSI_MAX_IFACE_LEN);
- if (!hwaddress) {
- rc = ENOMEM;
- goto free_iname;
- }
-
sprintf(sysfs_file, ISCSI_HOST_DIR);
n = scandir(sysfs_file, &namelist, trans_filter,
versionsort);
if (n <= 0)
- goto free_address;
+ goto free_info;
for (i = 0; i < n; i++) {
- if (sscanf(namelist[i]->d_name, "host%u", &host_no) != 1) {
+ if (sscanf(namelist[i]->d_name, "host%u", &info->host_no) !=
+ 1) {
log_error("Invalid iscsi host dir: %s",
namelist[i]->d_name);
break;
@@ -406,23 +401,33 @@ int sysfs_for_each_host(void *data, int *nr_found, sysfs_host_op_fn *fn)
memset(sysfs_file, 0, PATH_MAX);
sprintf(sysfs_file, ISCSI_HOST_DIR"/%s/initiatorname",
namelist[i]->d_name);
- rc = read_sysfs_file(sysfs_file, iname, "%s\n");
+ rc = read_sysfs_file(sysfs_file, info->iname, "%s\n");
if (rc) {
log_error("Could not read initiatorname for host %u. "
- "Error %d\n", host_no, rc);
+ "Error %d\n", info->host_no, rc);
+ break;
+ }
+
+ memset(sysfs_file, 0, PATH_MAX);
+ sprintf(sysfs_file, ISCSI_HOST_DIR"/%s/ipaddress",
+ namelist[i]->d_name);
+ rc = read_sysfs_file(sysfs_file, info->ipaddress, "%s\n");
+ if (rc) {
+ log_error("Could not read ipaddress for host %u. "
+ "Error %d\n", info->host_no, rc);
break;
}
memset(sysfs_file, 0, PATH_MAX);
sprintf(sysfs_file, ISCSI_HOST_DIR"/%s/hwaddress",
namelist[i]->d_name);
- rc = read_sysfs_file(sysfs_file, hwaddress, "%s\n");
+ rc = read_sysfs_file(sysfs_file, info->hwaddress, "%s\n");
if (rc) {
log_error("Could not read hwaddress for host %u. "
- "Error %d\n", host_no, rc);
+ "Error %d\n", info->host_no, rc);
break;
}
- rc = fn(data, host_no, iname, hwaddress);
+ rc = fn(data, info);
if (rc != 0)
break;
(*nr_found)++;
@@ -432,10 +437,8 @@ int sysfs_for_each_host(void *data, int *nr_found, sysfs_host_op_fn *fn)
free(namelist[i]);
free(namelist);
-free_address:
- free(hwaddress);
-free_iname:
- free(iname);
+free_info:
+ free(info);
return rc;
}
@@ -541,11 +544,20 @@ int get_sessioninfo_by_sysfs_id(struct session_info *info, char *session)
if (ret)
log_debug(7, "could not read hwaddress for %s\n", sysfs_file);
+
+ memset(sysfs_file, 0, PATH_MAX);
+ sprintf(sysfs_file, ISCSI_HOST_DIR"/host%u/ipaddress", host_no);
+ ret = read_sysfs_file(sysfs_file, info->local_address, "%s\n");
+ if (ret)
+ log_debug(7, "could not read local address for %s\n",
+ sysfs_file);
+
log_debug(7, "found targetname %s address %s pers address %s port %d "
- "pers port %d hwaddress %s\n",
+ "pers port %d hwaddress %s src address %s\n",
info->targetname, info->address ? info->address : "NA",
info->persistent_address ? info->persistent_address : "NA",
- info->port, info->persistent_port, info->hwaddress);
+ info->port, info->persistent_port, info->hwaddress,
+ info->local_address);
return 0;
}
diff --git a/usr/iscsi_sysfs.h b/usr/iscsi_sysfs.h
index 7169d4d..7140a92 100644
--- a/usr/iscsi_sysfs.h
+++ b/usr/iscsi_sysfs.h
@@ -35,7 +35,7 @@ extern int get_sessioninfo_by_sysfs_id(struct session_info *info,
char *sys_session);
typedef int (sysfs_session_op_fn)(void *, struct session_info *);
-typedef int (sysfs_host_op_fn)(void *, uint32_t, char *, char *);
+typedef int (sysfs_host_op_fn)(void *, struct host_info *);
extern int sysfs_for_each_session(void *data, int *nr_found,
sysfs_session_op_fn *fn);
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index a92cbc9..ef68e90 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -167,14 +167,13 @@ str_to_type(char *str)
}
/* flat P0 style for now */
-static int print_host(void *data, uint32_t host_no, char *iname,
- char *hwaddress)
+static int print_host(void *data, struct host_info *info)
{
struct iscsi_transport *t;
- t = get_transport_by_hba(host_no);
- printf("%s %s,%s %u\n", iname, t ? t->name : "NA",
- hwaddress, host_no);
+ t = get_transport_by_hba(info->host_no);
+ printf("%s %s,%s,%s %u\n", info->iname, t ? t->name : "NA",
+ info->hwaddress, info->ipaddress, info->host_no);
return 0;
}
@@ -856,6 +855,8 @@ static void print_sessions_tree(struct list_head *list, int level)
t = get_transport_by_sid(curr->sid);
printf("\t\tDriver: %s\n", t ? t->name : "NA");
printf("\t\tHWaddress: %s\n", curr->hwaddress);
+ printf("\t\tLocal address: %s\n", strlen(curr->local_address) ?
+ curr->local_address : "Unknown");
printf("\t\tSID: %d\n", curr->sid);
print_iscsi_state(curr->sid);