diff options
-rw-r--r-- | include/iscsi_if.h | 2 | ||||
-rw-r--r-- | kernel/iscsi_tcp.c | 123 | ||||
-rw-r--r-- | kernel/scsi_transport_iscsi.c | 4 | ||||
-rw-r--r-- | usr/initiator.h | 8 | ||||
-rw-r--r-- | usr/iscsi_sysfs.c | 58 | ||||
-rw-r--r-- | usr/iscsi_sysfs.h | 2 | ||||
-rw-r--r-- | usr/iscsiadm.c | 11 |
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); |