From 8012828d2aeccc469af32b26f06cd40d59cbfbee Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 22 Mar 2012 04:28:19 -0500 Subject: [PATCH] Resolves: #739843 #796574 --- iscsi-initiator-utils-add-rh-ver.patch | 2 +- ...tiator-utils-mod-iface-andport-fixes.patch | 1629 +++++++++++++++++ iscsi-initiator-utils.spec | 14 +- 3 files changed, 1641 insertions(+), 4 deletions(-) create mode 100644 iscsi-initiator-utils-mod-iface-andport-fixes.patch diff --git a/iscsi-initiator-utils-add-rh-ver.patch b/iscsi-initiator-utils-add-rh-ver.patch index 4d12de6..eb04ce7 100644 --- a/iscsi-initiator-utils-add-rh-ver.patch +++ b/iscsi-initiator-utils-add-rh-ver.patch @@ -5,7 +5,7 @@ * some other maintainer could merge a patch without going through us */ -#define ISCSI_VERSION_STR "2.0-872" -+#define ISCSI_VERSION_STR "2.0-872.34.el6" ++#define ISCSI_VERSION_STR "2.0-872.37.el6" #define ISCSI_VERSION_FILE "/sys/module/scsi_transport_iscsi/version" #endif diff --git a/iscsi-initiator-utils-mod-iface-andport-fixes.patch b/iscsi-initiator-utils-mod-iface-andport-fixes.patch new file mode 100644 index 0000000..99294fc --- /dev/null +++ b/iscsi-initiator-utils-mod-iface-andport-fixes.patch @@ -0,0 +1,1629 @@ +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h +--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h 2012-03-22 03:20:29.000000000 -0500 +@@ -270,7 +270,8 @@ struct iscsi_uevent { + } host_event; + struct msg_ping_comp { + uint32_t host_no; +- uint32_t status; ++ uint32_t status; /* enum ++ * iscsi_ping_status_code */ + uint32_t pid; /* unique ping id associated + with each ping request */ + uint32_t data_size; +@@ -515,6 +516,20 @@ enum iscsi_host_param { + #define ISCSI_HOST_NETDEV_NAME (1ULL << ISCSI_HOST_PARAM_NETDEV_NAME) + #define ISCSI_HOST_IPADDRESS (1ULL << ISCSI_HOST_PARAM_IPADDRESS) + ++/* iSCSI PING status/error code */ ++enum iscsi_ping_status_code { ++ ISCSI_PING_SUCCESS = 0, ++ ISCSI_PING_FW_DISABLED = 0x1, ++ ISCSI_PING_IPADDR_INVALID = 0x2, ++ ISCSI_PING_LINKLOCAL_IPV6_ADDR_INVALID = 0x3, ++ ISCSI_PING_TIMEOUT = 0x4, ++ ISCSI_PING_INVALID_DEST_ADDR = 0x5, ++ ISCSI_PING_OVERSIZE_PACKET = 0x6, ++ ISCSI_PING_ICMP_ERROR = 0x7, ++ ISCSI_PING_MAX_REQ_EXCEEDED = 0x8, ++ ISCSI_PING_NO_ARP_RECEIVED = 0x9, ++}; ++ + #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) + #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) + +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_net_util.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_net_util.h +--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_net_util.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_net_util.h 2012-03-22 03:29:53.000000000 -0500 +@@ -7,5 +7,6 @@ extern int net_get_transport_name_from_n + extern int net_get_netdev_from_hwaddress(char *hwaddress, char *netdev); + extern int net_setup_netdev(char *netdev, char *local_ip, char *mask, + char *gateway, char *remote_ip, int needs_bringup); ++extern int net_ifup_netdev(char *netdev); + + #endif +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/iscsiuio/include/config.h open-iscsi-2.0-872-rc4-bnx2i.work/iscsiuio/include/config.h +--- open-iscsi-2.0-872-rc4-bnx2i/iscsiuio/include/config.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/iscsiuio/include/config.h 2012-03-22 04:03:27.000000000 -0500 +@@ -59,6 +59,9 @@ typedef struct iface_rec { + * 1 = enable */ + uint16_t mtu; + uint16_t port; ++ char port_state[ISCSI_MAX_STR_LEN]; ++ char port_speed[ISCSI_MAX_STR_LEN]; ++ + /* + * TODO: we may have to make this bigger and interconnect + * specific for infinniband +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/libiscsi/libiscsi.c open-iscsi-2.0-872-rc4-bnx2i.work/libiscsi/libiscsi.c +--- open-iscsi-2.0-872-rc4-bnx2i/libiscsi/libiscsi.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/libiscsi/libiscsi.c 2012-03-22 03:49:55.000000000 -0500 +@@ -626,12 +626,15 @@ int libiscsi_node_set_parameter(struct l + const char *parameter, const char *value) + { + int nr_found = 0, rc; +- struct db_set_param set_param = { +- .name = (char *)parameter, +- .value = (char *)value, +- }; ++ LIST_HEAD(param_list); ++ struct user_param param; + +- CHECK(idbm_for_each_iface(&nr_found, &set_param, idbm_node_set_param, ++ INIT_LIST_HEAD(¶m.list); ++ param.name = (char *)parameter; ++ param.value = (char *)value; ++ list_add_tail(¶m.list, ¶m_list); ++ ++ CHECK(idbm_for_each_iface(&nr_found, ¶m_list, idbm_node_set_param, + (char *)node->name, node->tpgt, + (char *)node->address, node->port)) + if (nr_found == 0) { +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/config.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/config.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/config.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/config.h 2012-03-22 03:26:57.000000000 -0500 +@@ -229,6 +229,8 @@ typedef struct iface_rec { + * 1 = enable */ + uint16_t mtu; + uint16_t port; ++ char port_state[ISCSI_MAX_STR_LEN]; ++ char port_speed[ISCSI_MAX_STR_LEN]; + /* + * TODO: we may have to make this bigger and interconnect + * specific for infinniband +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/host.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/host.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.c 2012-03-22 03:29:48.000000000 -0500 +@@ -174,6 +174,16 @@ static int print_host_iface(void *data, + iface->ipv6_router); + } + ++ if (!strlen(iface->port_state)) ++ printf("%sPort State: %s\n", prefix, UNKNOWN_VALUE); ++ else ++ printf("%sPort State: %s\n", prefix, iface->port_state); ++ ++ if (!strlen(iface->port_speed)) ++ printf("%sPort Speed: %s\n", prefix, UNKNOWN_VALUE); ++ else ++ printf("%sPort Speed: %s\n", prefix, iface->port_speed); ++ + if (!iface->port) + printf("%sPort: %s\n", prefix, UNKNOWN_VALUE); + else +@@ -285,6 +295,7 @@ int host_info_print(int info_level, uint + break; + } + ++ transport_probe_for_offload(); + err = iscsi_sysfs_for_each_host(&flags, &num_found, + host_info_print_tree); + break; +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c 2012-03-22 03:27:12.000000000 -0500 +@@ -2358,70 +2358,83 @@ idbm_slp_defaults(struct iscsi_slp_confi + sizeof(struct iscsi_slp_config)); + } + +-int idbm_parse_param(char *param, struct node_rec *rec) ++struct user_param *idbm_alloc_user_param(char *name, char *value) + { +- char *name, *value; +- recinfo_t *info; +- int rc; ++ struct user_param *param; + +- name = param; ++ param = calloc(1, sizeof(*param)); ++ if (!param) ++ return NULL; + +- value = strchr(param, '='); +- if (!value) { +- log_error("Invalid --param %s. Missing setting.\n", param); +- return ISCSI_ERR_INVAL; +- } +- *value = '\0'; +- value++; ++ INIT_LIST_HEAD(¶m->list); + +- info = idbm_recinfo_alloc(MAX_KEYS); +- if (!info) { +- log_error("Could not allocate memory to setup params.\n"); +- return ISCSI_ERR_NOMEM; +- } ++ param->name = strdup(name); ++ if (!param->name) ++ goto free_param; + +- idbm_recinfo_node(rec, info); ++ param->value = strdup(value); ++ if (!param->value) ++ goto free_name; + +- rc = idbm_rec_update_param(info, name, value, 0); +- if (rc) +- log_error("Could not set %s to %s. Check that %s is a " +- "valid parameter.\n", name, value, name); +- free(info); +- return rc; ++ return param; ++ ++free_name: ++ free(param->name); ++free_param: ++ free(param); ++ return NULL; + } + +-int idbm_node_set_param(void *data, node_rec_t *rec) ++int idbm_node_set_rec_from_param(struct list_head *params, node_rec_t *rec, ++ int verify) + { +- struct db_set_param *param = data; ++ struct user_param *param; + recinfo_t *info; + int rc = 0; + ++ if (list_empty(params)) ++ return 0; ++ + info = idbm_recinfo_alloc(MAX_KEYS); + if (!info) + return ISCSI_ERR_NOMEM; + + idbm_recinfo_node(rec, info); + +- rc = idbm_verify_param(info, param->name); +- if (rc) +- goto free_info; +- +- rc = idbm_rec_update_param(info, param->name, param->value, 0); +- if (rc) +- goto free_info; ++ if (verify) { ++ list_for_each_entry(param, params, list) { ++ rc = idbm_verify_param(info, param->name); ++ if (rc) ++ goto free_info; ++ } ++ } + +- rc = idbm_rec_write(rec); +- if (rc) +- goto free_info; ++ list_for_each_entry(param, params, list) { ++ rc = idbm_rec_update_param(info, param->name, param->value, 0); ++ if (rc) ++ goto free_info; ++ } + + free_info: + free(info); + return rc; + } + ++int idbm_node_set_param(void *data, node_rec_t *rec) ++{ ++ int rc; ++ ++ rc = idbm_node_set_rec_from_param(data, rec, 1); ++ if (rc) ++ return rc; ++ ++ return idbm_rec_write(rec); ++} ++ + int idbm_discovery_set_param(void *data, discovery_rec_t *rec) + { +- struct db_set_param *param = data; ++ struct list_head *params = data; ++ struct user_param *param; + recinfo_t *info; + int rc = 0; + +@@ -2431,13 +2444,17 @@ int idbm_discovery_set_param(void *data, + + idbm_recinfo_discovery((discovery_rec_t *)rec, info); + +- rc = idbm_verify_param(info, param->name); +- if (rc) +- goto free_info; ++ list_for_each_entry(param, params, list) { ++ rc = idbm_verify_param(info, param->name); ++ if (rc) ++ goto free_info; ++ } + +- rc = idbm_rec_update_param(info, param->name, param->value, 0); +- if (rc) +- goto free_info; ++ list_for_each_entry(param, params, list) { ++ rc = idbm_rec_update_param(info, param->name, param->value, 0); ++ if (rc) ++ goto free_info; ++ } + + rc = idbm_discovery_write((discovery_rec_t *)rec); + if (rc) +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h 2012-03-22 03:48:10.000000000 -0500 +@@ -26,6 +26,7 @@ + #include + #include "initiator.h" + #include "config.h" ++#include "list.h" + + #define ISCSIVAR "/var/lib/iscsi/" + +@@ -82,7 +83,9 @@ typedef struct idbm { + discovery_rec_t drec_isns; + recinfo_t dinfo_isns[MAX_KEYS]; + } idbm_t; +-struct db_set_param { ++ ++struct user_param { ++ struct list_head list; + char *name; + char *value; + }; +@@ -145,9 +148,11 @@ extern int idbm_discovery_read(discovery + extern int idbm_rec_read(node_rec_t *out_rec, char *target_name, + int tpgt, char *addr, int port, + struct iface_rec *iface); +-extern int idbm_parse_param(char *param, struct node_rec *rec); ++extern int idbm_node_set_rec_from_param(struct list_head *params, ++ node_rec_t *rec, int verify); + extern int idbm_node_set_param(void *data, node_rec_t *rec); + extern int idbm_discovery_set_param(void *data, discovery_rec_t *rec); ++struct user_param *idbm_alloc_user_param(char *name, char *value); + extern void idbm_node_setup_defaults(node_rec_t *rec); + extern struct node_rec *idbm_find_rec_in_list(struct list_head *rec_list, + char *targetname, char *addr, +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c 2012-03-22 03:28:52.000000000 -0500 +@@ -169,7 +169,7 @@ free_conf: + int iface_conf_read(struct iface_rec *iface) + { + struct iface_rec *def_iface; +- int rc; ++ int rc, retry = 0; + + def_iface = iface_match_default(iface); + if (def_iface) { +@@ -197,12 +197,24 @@ int iface_conf_read(struct iface_rec *if + return 0; + } + ++retry_read: + rc = idbm_lock(); + if (rc) + return rc; + + rc = __iface_conf_read(iface); + idbm_unlock(); ++ ++ /* ++ * cmd was run before running -m iface, so force def bindings ++ * creation to see if that was the one requested ++ */ ++ if (retry < 1 && rc == ISCSI_ERR_IDBM) { ++ iface_setup_host_bindings(); ++ retry++; ++ goto retry_read; ++ } ++ + return rc; + } + +@@ -277,11 +289,11 @@ free_conf: + return rc; + } + +-int iface_conf_update(struct db_set_param *param, +- struct iface_rec *iface) ++int iface_conf_update(struct list_head *params, struct iface_rec *iface) + { + struct iface_rec *def_iface; + recinfo_t *info; ++ struct user_param *param; + int rc = 0; + + def_iface = iface_match_default(iface); +@@ -296,13 +308,18 @@ int iface_conf_update(struct db_set_para + return ISCSI_ERR_NOMEM; + + idbm_recinfo_iface(iface, info); +- rc = idbm_verify_param(info, param->name); +- if (rc) +- goto free_info; + +- rc = idbm_rec_update_param(info, param->name, param->value, 0); +- if (rc) +- goto free_info; ++ list_for_each_entry(param, params, list) { ++ rc = idbm_verify_param(info, param->name); ++ if (rc) ++ goto free_info; ++ } ++ ++ list_for_each_entry(param, params, list) { ++ rc = idbm_rec_update_param(info, param->name, param->value, 0); ++ if (rc) ++ goto free_info; ++ } + + rc = iface_conf_write(iface); + free_info: +@@ -449,6 +466,7 @@ static int iface_setup_binding_from_kern + { + struct host_info *hinfo = data; + struct iface_rec iface; ++ char iface_path[PATH_MAX]; + + if (!strlen(hinfo->iface.hwaddress)) { + log_error("Invalid offload iSCSI host %u. Missing " +@@ -474,7 +492,11 @@ static int iface_setup_binding_from_kern + hinfo->iface.transport_name, hinfo->iface.hwaddress); + } + +- if (iface_conf_read(&iface)) { ++ memset(iface_path, 0, sizeof(iface_path)); ++ snprintf(iface_path, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR, ++ iface.name); ++ ++ if (access(iface_path, F_OK) != 0) { + /* not found so create it */ + if (iface_conf_write(&iface)) { + log_error("Could not create default iface conf %s.", +@@ -532,6 +554,8 @@ void iface_setup_host_bindings(void) + } + idbm_unlock(); + ++ transport_probe_for_offload(); ++ + if (iscsi_sysfs_for_each_host(NULL, &nr_found, + __iface_setup_host_bindings)) + log_error("Could not scan scsi hosts. HW/OFFLOAD iscsi " +@@ -869,7 +893,8 @@ void iface_link_ifaces(struct list_head + int iface_setup_from_boot_context(struct iface_rec *iface, + struct boot_context *context) + { +- struct iscsi_transport *t; ++ struct iscsi_transport *t = NULL; ++ char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN]; + uint32_t hostno; + int rc; + +@@ -884,6 +909,12 @@ int iface_setup_from_boot_context(struct + return 0; + } + } else if (strlen(context->iface)) { ++ memset(transport_name, 0, ISCSI_TRANSPORT_NAME_MAXLEN); ++ /* make sure offload driver is loaded */ ++ if (!net_get_transport_name_from_netdev(context->iface, ++ transport_name)) ++ t = iscsi_sysfs_get_transport_by_name(transport_name); ++ + hostno = iscsi_sysfs_get_host_no_from_hwaddress(context->mac, + &rc); + if (rc) { +@@ -904,7 +935,8 @@ int iface_setup_from_boot_context(struct + /* + * set up for access through a offload card. + */ +- t = iscsi_sysfs_get_transport_by_hba(hostno); ++ if (!t) ++ t = iscsi_sysfs_get_transport_by_hba(hostno); + if (!t) { + log_error("Could not get transport for host%u. " + "Make sure the iSCSI driver is loaded.", +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iface.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iface.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.h 2012-03-22 03:25:44.000000000 -0500 +@@ -26,7 +26,6 @@ + + struct iface_rec; + struct list_head; +-struct db_set_param; + struct boot_context; + + extern void iface_copy(struct iface_rec *dst, struct iface_rec *src); +@@ -46,7 +45,7 @@ extern int iface_print_tree(void *data, + extern void iface_setup_host_bindings(void); + extern int iface_get_by_net_binding(struct iface_rec *pattern, + struct iface_rec *out_rec); +-extern int iface_conf_update(struct db_set_param *set_param, ++extern int iface_conf_update(struct list_head *params, + struct iface_rec *iface); + extern int iface_conf_write(struct iface_rec *iface); + extern int iface_conf_delete(struct iface_rec *iface); +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/initiator_common.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator_common.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/initiator_common.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator_common.c 2012-03-22 03:30:25.000000000 -0500 +@@ -35,6 +35,7 @@ + #include "host.h" + #include "sysdeps.h" + #include "iscsi_err.h" ++#include "iscsi_net_util.h" + + struct iscsi_session *session_find_by_sid(uint32_t sid) + { +@@ -596,6 +597,8 @@ int iscsi_host_set_net_params(struct ifa + { + struct iscsi_transport *t = session->t; + int rc = 0; ++ char *netdev; ++ struct host_info hinfo; + + log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, " + "transport %s.\n", +@@ -612,6 +615,21 @@ int iscsi_host_set_net_params(struct ifa + return EINVAL; + } + ++ /* these type of drivers need the netdev upd */ ++ if (strlen(iface->netdev)) ++ netdev = iface->netdev; ++ else { ++ memset(&hinfo, 0, sizeof(hinfo)); ++ hinfo.host_no = session->hostno; ++ iscsi_sysfs_get_hostinfo_by_host_no(&hinfo); ++ ++ netdev = hinfo.iface.netdev; ++ } ++ ++ if (net_ifup_netdev(netdev)) ++ log_warning("Could not brining up netdev %s. Try running " ++ "'ifup %s' first if login fails.", netdev, netdev); ++ + rc = iscsi_set_net_config(t, session, iface); + if (rc != 0) + return rc; +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c 2012-03-22 03:29:48.000000000 -0500 +@@ -1116,6 +1116,17 @@ do_sendtargets(discovery_rec_t *drec, st + free(iface); + continue; + } ++ /* check for transport name first to make sure it is loaded */ ++ t = iscsi_sysfs_get_transport_by_name(iface->transport_name); ++ if (!t) { ++ log_error("Could not load transport %s." ++ "Dropping interface %s.", ++ iface->transport_name, iface->name); ++ list_del(&iface->list); ++ free(iface); ++ continue; ++ } ++ + host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc); + if (rc || host_no == -1) { + log_debug(1, "Could not match iface" iface_fmt " to " +@@ -1124,18 +1135,6 @@ do_sendtargets(discovery_rec_t *drec, st + continue; + } + +- t = iscsi_sysfs_get_transport_by_hba(host_no); +- if (!t) { +- log_error("Could not match hostno %d to " +- "transport. Dropping interface %s," +- iface_fmt " ,%s.", +- host_no, iface->transport_name, +- iface_str(iface), iface->ipaddress); +- list_del(&iface->list); +- free(iface); +- continue; +- } +- + if (t->caps & CAP_SENDTARGETS_OFFLOAD) { + do_offload_sendtargets(drec, host_no, do_login); + list_del(&iface->list); +@@ -1346,8 +1345,6 @@ get_chap: + goto exit_chap_info; + } + +- log_info("Valid CHAP Entries = %d\n", valid_chap_entries); +- + crec = (struct iscsi_chap_rec *) (req_buf + + sizeof(struct iscsi_uevent)); + +@@ -1440,13 +1437,45 @@ static int exec_host_chap_op(int op, int + return rc; + } + ++static int verify_iface_params(struct list_head *params, struct node_rec *rec) ++{ ++ struct user_param *param; ++ ++ list_for_each_entry(param, params, list) { ++ if (!strcmp(param->name, IFACE_ISCSINAME)) { ++ log_error("Can not update " ++ "iface.iscsi_ifacename. Delete it, " ++ "and then create a new one."); ++ return ISCSI_ERR_INVAL; ++ } ++ ++ if (iface_is_bound_by_hwaddr(&rec->iface) && ++ !strcmp(param->name, IFACE_NETNAME)) { ++ log_error("Can not update interface binding " ++ "from hwaddress to net_ifacename. " ++ "You must delete the interface and " ++ "create a new one"); ++ return ISCSI_ERR_INVAL; ++ } ++ ++ if (iface_is_bound_by_netdev(&rec->iface) && ++ !strcmp(param->name, IFACE_HWADDR)) { ++ log_error("Can not update interface binding " ++ "from net_ifacename to hwaddress. " ++ "You must delete the interface and " ++ "create a new one"); ++ return ISCSI_ERR_INVAL; ++ } ++ } ++ return 0; ++} ++ + /* TODO: merge iter helpers and clean them up, so we can use them here */ + static int exec_iface_op(int op, int do_show, int info_level, + struct iface_rec *iface, uint32_t host_no, +- char *name, char *value) ++ struct list_head *params) + { + struct host_info hinfo; +- struct db_set_param set_param; + struct node_rec *rec = NULL; + int rc = 0; + +@@ -1502,7 +1531,7 @@ delete_fail: + iscsi_err_to_str(rc)); + break; + case OP_UPDATE: +- if (!iface || !name || !value) { ++ if (!iface || list_empty(params)) { + log_error("Update requires name, value, and iface."); + rc = ISCSI_ERR_INVAL; + break; +@@ -1520,42 +1549,16 @@ delete_fail: + "sessions then log back in for the " + "new settings to take affect."); + +- if (!strcmp(name, IFACE_ISCSINAME)) { +- log_error("Can not update " +- "iface.iscsi_ifacename. Delete it, " +- "and then create a new one."); +- rc = ISCSI_ERR_INVAL; +- break; +- } +- +- if (iface_is_bound_by_hwaddr(&rec->iface) && +- !strcmp(name, IFACE_NETNAME)) { +- log_error("Can not update interface binding " +- "from hwaddress to net_ifacename. "); +- log_error("You must delete the interface and " +- "create a new one"); +- rc = ISCSI_ERR_INVAL; +- break; +- } +- +- if (iface_is_bound_by_netdev(&rec->iface) && +- !strcmp(name, IFACE_HWADDR)) { +- log_error("Can not update interface binding " +- "from net_ifacename to hwaddress. "); +- log_error("You must delete the interface and " +- "create a new one"); +- rc = ISCSI_ERR_INVAL; ++ rc = verify_iface_params(params, rec); ++ if (rc) + break; +- } +- set_param.name = name; +- set_param.value = value; + + /* pass rec's iface because it has the db values */ +- rc = iface_conf_update(&set_param, &rec->iface); ++ rc = iface_conf_update(params, &rec->iface); + if (rc) + goto update_fail; + +- rc = __for_each_matched_rec(0, rec, &set_param, ++ rc = __for_each_matched_rec(0, rec, params, + idbm_node_set_param); + if (rc == ISCSI_ERR_NO_OBJS_FOUND) + rc = 0; +@@ -1638,14 +1641,62 @@ update_fail: + return rc; + } + ++static int verify_node_params(struct list_head *params, struct node_rec *rec) ++{ ++ struct user_param *param; ++ ++ if (list_empty(params)) { ++ log_error("update requires name and value"); ++ return ISCSI_ERR_INVAL; ++ } ++ ++ list_for_each_entry(param, params, list) { ++ /* compat - old tools used node and iface transport name */ ++ if (!strncmp(param->name, "iface.", 6) && ++ strcmp(param->name, "iface.transport_name")) { ++ log_error("Cannot modify %s. Use iface mode to update " ++ "this value.", param->name); ++ return ISCSI_ERR_INVAL; ++ } ++ ++ if (!strcmp(param->name, "node.transport_name")) { ++ free(param->name); ++ param->name = strdup("iface.transport_name"); ++ if (!param->name) { ++ log_error("Could not allocate memory for " ++ "param."); ++ return ISCSI_ERR_NOMEM; ++ } ++ } ++ /* ++ * tmp hack - we added compat crap above for the transport, ++ * but want to fix Doran's issue in this release too. However ++ * his patch is too harsh on many settings and we do not have ++ * time to update apps so we have this tmp hack until we ++ * can settle on a good interface that distros can use ++ * and we can mark stable. ++ */ ++ if (!strcmp(param->name, "iface.transport_name")) { ++ if (iscsi_check_for_running_session(rec)) { ++ log_warning("Cannot modify node/iface " ++ "transport name while a session " ++ "is using it. Log out the session " ++ "then update record."); ++ return ISCSI_ERR_SESS_EXISTS; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + /* TODO cleanup arguments */ + static int exec_node_op(int op, int do_login, int do_logout, + int do_show, int do_rescan, int do_stats, + int info_level, struct node_rec *rec, +- char *name, char *value) ++ struct list_head *params) + { + int rc = 0; +- struct db_set_param set_param; + + if (rec) + log_debug(2, "%s: %s:%s node [%s,%s,%d] sid %u", __FUNCTION__, +@@ -1708,46 +1759,11 @@ static int exec_node_op(int op, int do_l + } + + if (op == OP_UPDATE) { +- if (!name || !value) { +- log_error("update requires name and value"); +- rc = ISCSI_ERR_INVAL; +- goto out; +- } +- +- /* compat - old tools used node and iface transport name */ +- if (!strncmp(name, "iface.", 6) && +- strcmp(name, "iface.transport_name")) { +- log_error("Cannot modify %s. Use iface mode to update " +- "this value.", name); +- rc = ISCSI_ERR_INVAL; ++ rc = verify_node_params(params, rec); ++ if (rc) + goto out; +- } + +- if (!strcmp(name, "node.transport_name")) +- name = "iface.transport_name"; +- /* +- * tmp hack - we added compat crap above for the transport, +- * but want to fix Doran's issue in this release too. However +- * his patch is too harsh on many settings and we do not have +- * time to update apps so we have this tmp hack until we +- * can settle on a good interface that distros can use +- * and we can mark stable. +- */ +- if (!strcmp(name, "iface.transport_name")) { +- if (iscsi_check_for_running_session(rec)) { +- log_warning("Cannot modify node/iface " +- "transport name while a session " +- "is using it. Log out the session " +- "then update record."); +- rc = ISCSI_ERR_SESS_EXISTS; +- goto out; +- } +- } +- +- set_param.name = name; +- set_param.value = value; +- +- rc = for_each_matched_rec(rec, &set_param, idbm_node_set_param); ++ rc = for_each_matched_rec(rec, params, idbm_node_set_param); + goto out; + } else if (op == OP_DELETE) { + rc = for_each_matched_rec(rec, NULL, delete_node); +@@ -2002,7 +2018,7 @@ static int exec_discover(int disc_type, + + static int exec_disc2_op(int disc_type, char *ip, int port, + struct list_head *ifaces, int info_level, int do_login, +- int do_discover, int op, char *name, char *value, ++ int do_discover, int op, struct list_head *params, + int do_show) + { + struct discovery_rec drec; +@@ -2081,16 +2097,12 @@ do_db_op: + if (rc) + log_error("Unable to delete record!"); + } else if (op == OP_UPDATE) { +- struct db_set_param set_param; +- +- if (!name || !value) { ++ if (list_empty(params)) { + log_error("Update requires name and value."); + rc = ISCSI_ERR_INVAL; + goto done; + } +- set_param.name = name; +- set_param.value = value; +- rc = idbm_discovery_set_param(&set_param, &drec); ++ rc = idbm_discovery_set_param(params, &drec); + } else { + log_error("Operation is not supported."); + rc = ISCSI_ERR_INVAL; +@@ -2102,7 +2114,7 @@ done: + + static int exec_disc_op(int disc_type, char *ip, int port, + struct list_head *ifaces, int info_level, int do_login, +- int do_discover, int op, char *name, char *value, ++ int do_discover, int op, struct list_head *params, + int do_show) + { + struct discovery_rec drec; +@@ -2228,6 +2240,8 @@ static uint32_t parse_host_info(char *op + + *rc = 0; + if (strstr(optarg, ":")) { ++ transport_probe_for_offload(); ++ + host_no = iscsi_sysfs_get_host_no_from_hwaddress(optarg, + &err); + if (err) { +@@ -2245,13 +2259,46 @@ static uint32_t parse_host_info(char *op + return host_no; + } + ++static char *iscsi_ping_stat_strs[] = { ++ /* ISCSI_PING_SUCCESS */ ++ "success", ++ /* ISCSI_PING_FW_DISABLED */ ++ "firmware disabled", ++ /* ISCSI_PING_IPADDR_INVALID */ ++ "invalid IP address", ++ /* ISCSI_PING_LINKLOCAL_IPV6_ADDR_INVALID */ ++ "invalid link local IPv6 address", ++ /* ISCSI_PING_TIMEOUT */ ++ "timed out", ++ /* ISCSI_PING_INVALID_DEST_ADDR */ ++ "invalid destination address", ++ /* ISCSI_PING_OVERSIZE_PACKET */ ++ "oversized packet", ++ /* ISCSI_PING_ICMP_ERROR */ ++ "ICMP error", ++ /* ISCSI_PING_MAX_REQ_EXCEEDED */ ++ "Max request exceeded", ++ /* ISCSI_PING_NO_ARP_RECEIVED */ ++ "No ARP response received", ++}; ++ ++static char *iscsi_ping_stat_to_str(uint32_t status) ++{ ++ if (status < 0 || status > ISCSI_PING_NO_ARP_RECEIVED) { ++ log_error("Invalid ping status %u\n", status); ++ return NULL; ++ } ++ ++ return iscsi_ping_stat_strs[status]; ++} ++ + static int exec_ping_op(struct iface_rec *iface, char *ip, int size, int count, + int interval) + { + int rc = ISCSI_ERR; + uint32_t iface_type = ISCSI_IFACE_TYPE_IPV4; + struct iscsi_transport *t = NULL; +- uint32_t host_no; ++ uint32_t host_no, status = 0; + struct sockaddr_storage addr; + int i; + +@@ -2324,11 +2371,15 @@ static int exec_ping_op(struct iface_rec + * the iscsi if to send a ping, we can add a transport + * callout here. + */ ++ status = 0; + rc = ipc->exec_ping(t->handle, host_no, + (struct sockaddr *)&addr, iface->iface_num, +- iface_type, size); +- if (!rc) ++ iface_type, size, &status); ++ if (!rc && !status) + printf("Ping %d completed\n", i); ++ else if (status) ++ printf("Ping %d failed: %s\n", i, ++ iscsi_ping_stat_to_str(status)); + else + printf("Ping %d failed: %s\n", i, iscsi_err_to_str(rc)); + +@@ -2357,7 +2408,10 @@ main(int argc, char **argv) + struct iface_rec *iface = NULL, *tmp; + struct node_rec *rec = NULL; + uint32_t host_no = -1; ++ struct user_param *param; ++ struct list_head params; + ++ INIT_LIST_HEAD(¶ms); + INIT_LIST_HEAD(&ifaces); + /* do not allow ctrl-c for now... */ + memset(&sa_old, 0, sizeof(struct sigaction)); +@@ -2499,6 +2553,18 @@ main(int argc, char **argv) + case 'h': + usage(0); + } ++ ++ if (name && value) { ++ param = idbm_alloc_user_param(name, value); ++ if (!param) { ++ log_error("Cannot allocate memory for params."); ++ rc = ISCSI_ERR_NOMEM; ++ goto free_ifaces; ++ } ++ list_add_tail(¶m->list, ¶ms); ++ name = NULL; ++ value = NULL; ++ } + } + + if (optopt) { +@@ -2585,7 +2651,7 @@ main(int argc, char **argv) + ping_interval); + else + rc = exec_iface_op(op, do_show, info_level, iface, +- host_no, name, value); ++ host_no, ¶ms); + + break; + case MODE_DISCOVERYDB: +@@ -2597,7 +2663,7 @@ main(int argc, char **argv) + } + + rc = exec_disc2_op(type, ip, port, &ifaces, info_level, +- do_login, do_discover, op, name, value, ++ do_login, do_discover, op, ¶ms, + do_show); + break; + case MODE_DISCOVERY: +@@ -2609,7 +2675,7 @@ main(int argc, char **argv) + } + + rc = exec_disc_op(type, ip, port, &ifaces, info_level, +- do_login, do_discover, op, name, value, ++ do_login, do_discover, op, ¶ms, + do_show); + break; + case MODE_NODE: +@@ -2653,7 +2719,7 @@ main(int argc, char **argv) + + rc = exec_node_op(op, do_login, do_logout, do_show, + do_rescan, do_stats, info_level, rec, +- name, value); ++ ¶ms); + break; + case MODE_SESSION: + if ((rc = verify_mode_params(argc, argv, +@@ -2723,7 +2789,7 @@ main(int argc, char **argv) + /* drop down to node ops */ + rc = exec_node_op(op, do_login, do_logout, do_show, + do_rescan, do_stats, info_level, +- rec, name, value); ++ rec, ¶ms); + free_info: + free(info); + goto out; +@@ -2737,7 +2803,7 @@ free_info: + if (do_logout || do_rescan || do_stats) { + rc = exec_node_op(op, do_login, do_logout, + do_show, do_rescan, do_stats, +- info_level, NULL, name, value); ++ info_level, NULL, ¶ms); + goto out; + } + +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.c 2012-03-22 03:25:35.000000000 -0500 +@@ -409,11 +409,6 @@ int main(int argc, char *argv[]) + exit(ISCSI_ERR); + } + +- if (iscsi_sysfs_check_class_version()) { +- log_close(log_pid); +- exit(ISCSI_ERR); +- } +- + umask(0177); + + mgmt_ipc_fd = -1; +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h 2012-03-22 03:20:29.000000000 -0500 +@@ -137,7 +137,7 @@ struct iscsi_ipc { + + int (*exec_ping) (uint64_t transport_handle, uint32_t host_no, + struct sockaddr *addr, uint32_t iface_num, +- uint32_t iface_type, uint32_t size); ++ uint32_t iface_type, uint32_t size, uint32_t *status); + + int (*get_chap) (uint64_t transport_handle, uint32_t host_no, + uint16_t chap_tbl_idx, uint32_t num_entries, +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_net_util.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_net_util.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_net_util.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_net_util.c 2012-03-22 03:29:53.000000000 -0500 +@@ -72,7 +72,7 @@ int net_get_transport_name_from_netdev(c + ifr.ifr_data = (caddr_t)&drvinfo; + err = ioctl(fd, SIOCETHTOOL, &ifr); + if (err < 0) { +- log_error("Could not get driver."); ++ log_error("Could not get driver %s.", netdev); + err = errno; + goto close_sock; + } +@@ -304,6 +304,59 @@ int net_setup_netdev(char *netdev, char + done: + close(sock); + return ret; ++} ++ ++/** ++ * net_ifup_netdev - bring up network interface ++ * @netdev: netdevice to bring up. ++ */ ++int net_ifup_netdev(char *netdev) ++{ ++ struct ifreq ifr; ++ int sock; ++ int ret = 0; ++ ++ if (!strlen(netdev)) { ++ log_error("No netdev name in fw entry.\n"); ++ return EINVAL; ++ } ++ ++ /* Create socket for making networking changes */ ++ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { ++ log_error("Could not open socket to manage network " ++ "(err %d - %s)", errno, strerror(errno)); ++ return errno; ++ } ++ ++ memset(&ifr, 0, sizeof(ifr)); ++ strncpy(ifr.ifr_name, netdev, IFNAMSIZ); ++ if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { ++ log_error("Could not bring up netdev %s (err %d - %s)", ++ netdev, errno, strerror(errno)); ++ ret = errno; ++ goto done; ++ } ++ ++ if (ifr.ifr_flags & IFF_UP) { ++ log_debug(3, "%s up\n", netdev); ++ goto done; ++ } ++ ++ log_debug(3, "bringing %s up\n", netdev); ++ ++ /* Bring up interface */ ++ memset(&ifr, 0, sizeof(ifr)); ++ strncpy(ifr.ifr_name, netdev, IFNAMSIZ); ++ ifr.ifr_flags = IFF_UP; ++ if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { ++ log_error("Could not bring up netdev %s (err %d - %s)", ++ netdev, errno, strerror(errno)); ++ ret = errno; ++ goto done; ++ } ++done: ++ close(sock); ++ return ret; + } + + +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsistart.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsistart.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsistart.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsistart.c 2012-03-22 03:29:42.000000000 -0500 +@@ -40,6 +40,7 @@ + #include "log.h" + #include "iscsi_util.h" + #include "idbm.h" ++#include "idbm_fields.h" + #include "version.h" + #include "iscsi_sysfs.h" + #include "iscsi_settings.h" +@@ -48,6 +49,7 @@ + #include "sysdeps.h" + #include "iscsid_req.h" + #include "iscsi_err.h" ++#include "iface.h" + + /* global config info */ + /* initiator needs initiator name/alias */ +@@ -58,11 +60,6 @@ static node_rec_t config_rec; + static LIST_HEAD(targets); + static LIST_HEAD(user_params); + +-struct user_param { +- struct list_head list; +- char *param_string; +-}; +- + static char program_name[] = "iscsistart"; + + /* used by initiator */ +@@ -145,11 +142,34 @@ static int apply_params(struct node_rec + rec->conn[0].timeo.noop_out_timeout = -1; + + list_for_each_entry(param, &user_params, list) { +- rc = idbm_parse_param(param->param_string, rec); +- if (rc) +- return rc; ++ /* ++ * user may not have passed in all params that were set by ++ * ibft/iscsi_boot, so clear out values that might conflict ++ * with user overrides ++ */ ++ if (!strcmp(param->name, IFACE_NETNAME)) { ++ /* overriding netname so MAC will be for old netdev */ ++ memset(rec->iface.hwaddress, 0, ++ sizeof(rec->iface.hwaddress)); ++ } else if (!strcmp(param->name, IFACE_HWADDR)) { ++ /* overriding MAC so netdev will be for old MAC */ ++ memset(rec->iface.netdev, 0, sizeof(rec->iface.netdev)); ++ } else if (!strcmp(param->name, IFACE_TRANSPORTNAME)) { ++ /* ++ * switching drivers so all old binding info is no ++ * longer valid. Old values were either for offload ++ * and we are switching to software or the reverse, ++ * or switching types of cards (bnx2i to cxgb3i). ++ */ ++ memset(&rec->iface, 0, sizeof(rec->iface)); ++ iface_setup_defaults(&rec->iface); ++ } + } + ++ rc = idbm_node_set_rec_from_param(&user_params, rec, 0); ++ if (rc) ++ return rc; ++ + /* + * For root boot we could not change this in older versions so + * if user did not override then use the defaults. +@@ -167,23 +187,32 @@ static int apply_params(struct node_rec + return 0; + } + +-static int alloc_param(char *param_string) ++static int parse_param(char *param_str) + { + struct user_param *param; ++ char *name, *value; + +- param = calloc(1, sizeof(*param)); +- if (!param) { +- printf("Could not allocate for param.\n"); +- return ISCSI_ERR_NOMEM; ++ name = param_str; ++ ++ value = strchr(param_str, '='); ++ if (!value) { ++ log_error("Invalid --param %s. Missing value.", param_str); ++ return ISCSI_ERR_INVAL; ++ } ++ *value = '\0'; ++ ++ value++; ++ if (!strlen(value)) { ++ log_error("Invalid --param %s. Missing value.", param_str); ++ return ISCSI_ERR_INVAL; + } + +- INIT_LIST_HEAD(¶m->list); +- param->param_string = strdup(param_string); +- if (!param->param_string) { +- printf("Could not allocate for param.\n"); +- free(param); ++ param = idbm_alloc_user_param(name, value); ++ if (!param) { ++ log_error("Could not allocate memory for param."); + return ISCSI_ERR_NOMEM; + } ++ + list_add(¶m->list, &user_params); + return 0; + } +@@ -316,8 +345,6 @@ int main(int argc, char *argv[]) + log_init(program_name, DEFAULT_AREA_SIZE, log_do_log_std, NULL); + + sysfs_init(); +- if (iscsi_sysfs_check_class_version()) +- exit(ISCSI_ERR_SYSFS_LOOKUP); + + while ((ch = getopt_long(argc, argv, "P:i:t:g:a:p:d:u:w:U:W:bNfvh", + long_options, &longindex)) >= 0) { +@@ -399,7 +426,7 @@ int main(int argc, char *argv[]) + fw_free_targets(&targets); + exit(0); + case 'P': +- err = alloc_param(optarg); ++ err = parse_param(optarg); + if (err) + exit(err); + break; +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.c 2012-03-22 03:27:02.000000000 -0500 +@@ -532,6 +532,12 @@ static int iscsi_sysfs_read_iface(struct + ret = 0; + } + ++ sysfs_get_str(host_id, ISCSI_HOST_SUBSYS, "port_state", ++ iface->port_state, sizeof(iface->port_state)); ++ ++ sysfs_get_str(host_id, ISCSI_HOST_SUBSYS, "port_speed", ++ iface->port_speed, sizeof(iface->port_speed)); ++ + /* + * this is on the session, because we support multiple bindings + * per device. +@@ -1144,13 +1150,31 @@ static uint32_t get_target_no_from_sid(u + + } + ++int iscsi_sysfs_is_transport_loaded(char *transport_name) ++{ ++ struct iscsi_transport *t; ++ ++ /* sync up kernel and userspace */ ++ read_transports(); ++ ++ /* check if the transport is loaded and matches */ ++ list_for_each_entry(t, &transports, list) { ++ if (t->handle && !strncmp(t->name, transport_name, ++ ISCSI_TRANSPORT_NAME_MAXLEN)) ++ return 1; ++ } ++ ++ return 0; ++} ++ + struct iscsi_transport *iscsi_sysfs_get_transport_by_name(char *transport_name) + { + struct iscsi_transport *t; ++ int retry = 0; + ++retry: + /* sync up kernel and userspace */ +- if (read_transports()) +- return NULL; ++ read_transports(); + + /* check if the transport is loaded and matches */ + list_for_each_entry(t, &transports, list) { +@@ -1158,6 +1182,13 @@ struct iscsi_transport *iscsi_sysfs_get_ + ISCSI_TRANSPORT_NAME_MAXLEN)) + return t; + } ++ ++ if (retry < 1) { ++ retry++; ++ if (!transport_load_kmod(transport_name)) ++ goto retry; ++ } ++ + return NULL; + } + +@@ -1366,40 +1397,3 @@ char *iscsi_sysfs_get_iscsi_kernel_versi + { + return sysfs_attr_get_value("/module/scsi_transport_iscsi", "version"); + } +- +-int iscsi_sysfs_check_class_version(void) +-{ +- char *version; +- int i; +- +- version = iscsi_sysfs_get_iscsi_kernel_version(); +- if (!version) +- goto fail; +- +- log_warning("transport class version %s. iscsid version %s", +- version, ISCSI_VERSION_STR); +- +- for (i = 0; i < strlen(version); i++) { +- if (version[i] == '-') +- break; +- } +- +- if (i == strlen(version)) +- goto fail; +- +- /* +- * We want to make sure the release and interface are the same. +- * It is ok for the svn versions to be different. +- */ +- if (!strncmp(version, ISCSI_VERSION_STR, i) || +- /* support 2.6.18 */ +- !strncmp(version, "1.1", 3)) +- return 0; +- +-fail: +- log_error( "Missing or Invalid version from %s. Make sure a up " +- "to date scsi_transport_iscsi module is loaded and a up to" +- "date version of iscsid is running. Exiting...", +- ISCSI_VERSION_FILE); +- return -1; +-} +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.h 2012-03-22 03:27:02.000000000 -0500 +@@ -36,7 +36,6 @@ struct iscsi_auth_config; + + extern void free_transports(void); + extern char *iscsi_sysfs_get_iscsi_kernel_version(void); +-extern int iscsi_sysfs_check_class_version(void); + extern int iscsi_sysfs_get_sessioninfo_by_id(struct session_info *info, + char *sys_session); + extern int iscsi_sysfs_session_has_leadconn(uint32_t sid); +@@ -89,6 +88,7 @@ extern struct iscsi_transport *iscsi_sys + extern struct iscsi_transport *iscsi_sysfs_get_transport_by_session(char *sys_session); + extern struct iscsi_transport *iscsi_sysfs_get_transport_by_sid(uint32_t sid); + extern struct iscsi_transport *iscsi_sysfs_get_transport_by_name(char *transport_name); ++extern int iscsi_sysfs_is_transport_loaded(char *transport_name); + extern int iscsi_sysfs_session_supports_nop(int sid); + extern int iscsi_sysfs_session_user_created(int sid); + +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_util.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_util.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_util.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_util.c 2012-03-22 03:25:40.000000000 -0500 +@@ -90,13 +90,16 @@ str_to_ipport(char *str, int *port, int + + if (!strchr(ip, '.')) { + if (*ip == '[') { ++ /* IPv6 with [] */ + if (!(sport = strchr(ip, ']'))) + return NULL; + *sport++ = '\0'; + ip++; + str = sport; +- } else ++ } else if (!strchr(ip, ':')) ++ /* IPv6 no brackets and no port */ + sport = NULL; ++ /* else hostname with domain info */ + } + + if (sport && (sport = strchr(str, ':'))) { +@@ -178,7 +181,6 @@ char *strstrip(char *s) + char *cfg_get_string_param(char *pathname, const char *key) + { + FILE *f = NULL; +- int len; + char *line, buffer[1024]; + char *value = NULL, *param, *comment; + +@@ -187,7 +189,6 @@ char *cfg_get_string_param(char *pathnam + return NULL; + } + +- len = strlen(key); + if ((f = fopen(pathname, "r"))) { + while ((line = fgets(buffer, sizeof (buffer), f))) { + param = strstr(line, key); +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/Makefile open-iscsi-2.0-872-rc4-bnx2i.work/usr/Makefile +--- open-iscsi-2.0-872-rc4-bnx2i/usr/Makefile 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/Makefile 2012-03-22 03:25:15.000000000 -0500 +@@ -33,7 +33,7 @@ endif + OPTFLAGS ?= -O2 -g + WARNFLAGS ?= -Wall -Wstrict-prototypes + CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -I../include -I. -I../utils/open-isns \ +- -D$(OSNAME) $(IPC_CFLAGS) -DISNS_ENABLE ++ -D$(OSNAME) $(IPC_CFLAGS) -DISNS_ENABLE + PROGRAMS = iscsid iscsiadm iscsistart + + # libc compat files +@@ -57,7 +57,7 @@ all: $(PROGRAMS) + + iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \ + iscsid.o session_mgmt.o discoveryd.o +- $(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns ++ $(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns + + iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o + $(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c 2012-03-22 03:20:29.000000000 -0500 +@@ -1085,13 +1085,15 @@ ksend_ping(uint64_t transport_handle, ui + + static int kexec_ping(uint64_t transport_handle, uint32_t host_no, + struct sockaddr *addr, uint32_t iface_num, +- uint32_t iface_type, uint32_t size) ++ uint32_t iface_type, uint32_t size, uint32_t *status) + { + struct pollfd pfd; + struct timeval ping_timer; + int timeout, fd, rc; + uint32_t pid; + ++ *status = 0; ++ + fd = ipc->ctldev_open(); + if (fd < 0) { + log_error("Could not open netlink socket."); +@@ -1151,10 +1153,8 @@ static int kexec_ping(uint64_t transport + if (pid != ping_event.pid) + continue; + +- if (ping_event.status == 0) +- rc = 0; +- else +- rc = ISCSI_ERR; ++ rc = 0; ++ *status = ping_event.status; + break; + } + +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/transport.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.c +--- open-iscsi-2.0-872-rc4-bnx2i/usr/transport.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.c 2012-03-22 03:27:02.000000000 -0500 +@@ -19,7 +19,17 @@ + #include + #include + #include ++#ifdef USE_KMOD ++#include ++#endif ++#include ++#include ++#include ++#include ++#include + ++#include "sysdeps.h" ++#include "iscsi_err.h" + #include "initiator.h" + #include "transport.h" + #include "log.h" +@@ -100,6 +110,151 @@ static struct iscsi_transport_template * + NULL + }; + ++int transport_probe_for_offload(void) ++{ ++ struct if_nameindex *ifni; ++ char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN]; ++ int i, sockfd; ++ struct ifreq if_hwaddr; ++ ++ ifni = if_nameindex(); ++ if (!ifni) { ++ log_error("Could not search for transport modules: %s", ++ strerror(errno)); ++ return ISCSI_ERR_TRANS_NOT_FOUND; ++ } ++ ++ sockfd = socket(AF_INET, SOCK_DGRAM, 0); ++ if (sockfd < 0) { ++ log_error("Could not open socket for ioctl: %s", ++ strerror(errno)); ++ goto free_ifni; ++ } ++ ++ for (i = 0; ifni[i].if_index && ifni[i].if_name; i++) { ++ struct if_nameindex *n = &ifni[i]; ++ ++ log_debug(6, "kmod probe found %s\n", n->if_name); ++ ++ strlcpy(if_hwaddr.ifr_name, n->if_name, IFNAMSIZ); ++ if (ioctl(sockfd, SIOCGIFHWADDR, &if_hwaddr) < 0) ++ continue; ++ ++ /* check for ARPHRD_ETHER (ethernet) */ ++ if (if_hwaddr.ifr_hwaddr.sa_family != 1) ++ continue; ++ ++ if (net_get_transport_name_from_netdev(n->if_name, ++ transport_name)) ++ continue; ++ ++ transport_load_kmod(transport_name); ++ } ++ ++free_ifni: ++ if_freenameindex(ifni); ++ return 0; ++} ++ ++/* ++ * Most distros still do not have wide libkmod use, so ++ * use modprobe for now ++ */ ++#ifdef USE_KMOD ++int transport_load_kmod(char *transport_name) ++{ ++ struct kmod_ctx *ctx; ++ struct kmod_module *mod; ++ int rc; ++ ++ ctx = kmod_new(NULL, NULL); ++ if (!ctx) { ++ log_error("Could not load transport module %s. Out of " ++ "memory.", transport_name); ++ return ISCSI_ERR_NOMEM; ++ } ++ ++ kmod_load_resources(ctx); ++ ++ /* ++ * dumb dumb dumb - named iscsi_tcp and ib_iser differently from ++ * transport name ++ */ ++ if (!strcmp(transport_name, "tcp")) ++ rc = kmod_module_new_from_name(ctx, "iscsi_tcp", &mod); ++ else if (!strcmp(transport_name, "iser")) ++ rc = kmod_module_new_from_name(ctx, "ib_iser", &mod); ++ else ++ rc = kmod_module_new_from_name(ctx, transport_name, &mod); ++ if (rc) { ++ log_error("Failed to load module %s.", transport_name); ++ rc = ISCSI_ERR_TRANS_NOT_FOUND; ++ goto unref_mod; ++ } ++ ++ rc = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, ++ NULL, NULL, NULL, NULL); ++ if (rc) { ++ log_error("Could not insert module %s. Kmod error %d", ++ transport_name, rc); ++ rc = ISCSI_ERR_TRANS_NOT_FOUND; ++ } ++ kmod_module_unref(mod); ++ ++unref_mod: ++ kmod_unref(ctx); ++ return rc; ++} ++ ++#else ++ ++int transport_load_kmod(char *transport_name) ++{ ++ char *cmdline[4]; ++ pid_t pid; ++ ++ cmdline[0] = "/sbin/modprobe"; ++ cmdline[1] = "-qb"; ++ cmdline[3] = NULL; ++ ++ /* ++ * dumb dumb mistake - named iscsi_tcp and ib_iser differently from ++ * transport name ++ */ ++ if (!strcmp(transport_name, "tcp")) ++ cmdline[2] = "iscsi_tcp"; ++ else if (!strcmp(transport_name, "iser")) ++ cmdline[2] = "ib_iser"; ++ else ++ cmdline[2] = transport_name; ++ ++ if (iscsi_sysfs_is_transport_loaded(cmdline[2])) ++ return 0; ++ ++ pid = fork(); ++ if (pid == 0) { ++ if (execv("/sbin/modprobe", cmdline) < 0) { ++ log_error("Failed to load module %s: %s", ++ transport_name, strerror(errno)); ++ exit(-errno); ++ } ++ exit(0); ++ } else if (pid < 0) { ++ log_error("Failed to fork process to load module %s: %s", ++ transport_name, strerror(errno)); ++ return ISCSI_ERR_TRANS_NOT_FOUND; ++ } ++ ++ if (waitpid(pid, NULL, 0) < 0) { ++ log_error("Failed to load module %s", transport_name); ++ return ISCSI_ERR_TRANS_NOT_FOUND; ++ } ++ ++ return 0; ++} ++ ++#endif ++ + int set_transport_template(struct iscsi_transport *t) + { + struct iscsi_transport_template *tmpl; +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/transport.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.h +--- open-iscsi-2.0-872-rc4-bnx2i/usr/transport.h 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.h 2012-03-22 03:21:42.000000000 -0500 +@@ -51,5 +51,7 @@ struct iscsi_transport { + }; + + extern int set_transport_template(struct iscsi_transport *t); ++extern int transport_load_kmod(char *transport_name); ++extern int transport_probe_for_offload(void); + + #endif +diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fw_entry.c open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fw_entry.c +--- open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fw_entry.c 2012-03-22 03:20:09.000000000 -0500 ++++ open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fw_entry.c 2012-03-22 03:27:49.000000000 -0500 +@@ -35,6 +35,8 @@ + #include "idbm_fields.h" + #include "iscsi_net_util.h" + #include "iscsi_err.h" ++#include "config.h" ++#include "iface.h" + + /** + * fw_setup_nics - setup nics (ethXs) based on ibft net info +@@ -146,11 +148,19 @@ void fw_free_targets(struct list_head *l + + static void dump_initiator(struct boot_context *context) + { ++ struct iface_rec iface; ++ ++ memset(&iface, 0, sizeof(iface)); ++ iface_setup_defaults(&iface); ++ iface_setup_from_boot_context(&iface, context); ++ + if (strlen(context->initiatorname)) + printf("%s = %s\n", IFACE_INAME, context->initiatorname); + + if (strlen(context->isid)) + printf("%s = %s\n", IFACE_ISID, context->isid); ++ ++ printf("%s = %s\n", IFACE_TRANSPORTNAME, iface.transport_name); + } + + static void dump_target(struct boot_context *context) diff --git a/iscsi-initiator-utils.spec b/iscsi-initiator-utils.spec index 523c79c..844a080 100644 --- a/iscsi-initiator-utils.spec +++ b/iscsi-initiator-utils.spec @@ -3,7 +3,7 @@ Summary: iSCSI daemon and utility programs Name: iscsi-initiator-utils Version: 6.2.0.872 -Release: 36%{?dist} +Release: 37%{?dist} Source0: http://people.redhat.com/mchristi/iscsi/rhel6.0/source/open-iscsi-2.0-872-rc4-bnx2i.tar.gz Source1: iscsid.init Source2: iscsidevs.init @@ -37,8 +37,10 @@ Patch11: iscsi-initiator-utils-libiscsi-to-support-offload.patch # sync to upstream commit f9f627fbf0fc96545931ae65aa2b6214841bfd4e to # add iscsiadm ping and host chap support and fix default iface handling Patch12: iscsi-initiator-utils-ping-and-chap.patch +# sync to upstream 04b4a6699f63c4f0bab9523aae3efb8c909d6587 +Patch13: iscsi-initiator-utils-mod-iface-andport-fixes.patch # add rhel version info to iscsi tools -Patch13: iscsi-initiator-utils-add-rh-ver.patch +Patch14: iscsi-initiator-utils-add-rh-ver.patch Group: System Environment/Daemons License: GPLv2+ @@ -79,7 +81,8 @@ developing applications that use %{name}. %patch10 -p1 -b .Add-Netconfig-support-through-libiscsi %patch11 -p1 -b .libiscsi-to-support-offload %patch12 -p1 -b .ping-and-chap -%patch13 -p1 -b .add-rh-ver +%patch13 -p1 -b .mod-iface-andport-fixes +%patch14 -p1 -b .add-rh-ver %build cd utils/open-isns @@ -205,6 +208,11 @@ fi %{_includedir}/libiscsi.h %changelog +* Thu Mar 22 2012 Mike Christie 6.2.0.872.37 +- 805467 Have iscsistart/iscsiadm bring up offload net interface. +- 796574 Fix port handling when hostnames are used for portals. +- 739843 Fix default iface setup handling. + * Mon Mar 5 2012 Mike Christie 6.2.0.872.36 - 740054 sync iscsiuio to 0.7.2.1 - 790609 Add ping and host chap support to iscsiadm