Both be2iscsi and qla4xxx export multiple iface ojbects in sysfs per
host to represent the number of network configurations (ipv4/ipv6) that
can be supported. Fix the libopeniscsiusr code to create and manage
multiple offload iface records per host, as the old code did.
---
 libopeniscsiusr/iface.c   | 84 ++++++++++++++++++++++++++++++++++++++---------
 libopeniscsiusr/iface.h   |  1 +
 libopeniscsiusr/session.c |  3 +-
 libopeniscsiusr/sysfs.c   | 36 ++++++++++++--------
 libopeniscsiusr/sysfs.h   | 10 +++---
 5 files changed, 101 insertions(+), 33 deletions(-)

diff --git a/libopeniscsiusr/iface.c b/libopeniscsiusr/iface.c
index 955395d08a29..963e3b12e364 100644
--- a/libopeniscsiusr/iface.c
+++ b/libopeniscsiusr/iface.c
@@ -89,14 +89,14 @@ _iscsi_getter_func_gen(iscsi_iface, port_speed, const char 
*);
 _iscsi_getter_func_gen(iscsi_iface, name, const char *);
 
 int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
-                               uint32_t sid, struct iscsi_iface **iface)
+                               uint32_t sid, char *iface_kern_id,
+                               struct iscsi_iface **iface)
 {
        int rc = LIBISCSI_OK;
        char *sysfs_se_dir_path = NULL;
        char *sysfs_sh_dir_path = NULL;
        char *sysfs_scsi_host_dir_path = NULL;
        char *sysfs_iface_dir_path = NULL;
-       char iface_kern_id[PATH_MAX];
        char proc_name[ISCSI_TRANSPORT_NAME_MAXLEN];
        struct iscsi_iface **ifaces = NULL;
        uint32_t iface_count = 0;
@@ -195,8 +195,7 @@ int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, 
uint32_t host_id,
                                (*iface)->name,
                                sizeof((*iface)->name)/sizeof(char), "");
 
-       rc = _iscsi_iface_kern_id_of_host_id(ctx, host_id, iface_kern_id);
-       if (rc == LIBISCSI_OK) {
+       if (iface_kern_id != NULL) {
                _good(_fill_hw_iface_from_sys(ctx, *iface, iface_kern_id),
                      rc, out);
        } else {
@@ -268,6 +267,52 @@ out:
        return rc;
 }
 
+/* create all ifaces for a host from sysfs */
+int _iscsi_ifaces_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
+                                struct iscsi_iface ***ifaces, uint32_t 
*iface_count)
+{
+       int rc = LIBISCSI_OK;
+       char **iface_kern_ids = NULL;
+
+       assert(ctx != NULL);
+       assert(ifaces != NULL);
+
+       *ifaces = NULL;
+       *iface_count = 0;
+
+       _good(_iscsi_iface_kern_ids_of_host_id(ctx, host_id, &iface_kern_ids, 
iface_count),
+             rc, out);
+       if (*iface_count > 0) {
+               *ifaces = (struct iscsi_iface **) calloc(*iface_count,
+                                                        sizeof(struct 
iscsi_iface *));
+               _alloc_null_check(ctx, *ifaces, rc, out);
+               for (uint32_t i = 0; i < *iface_count; i++) {
+                       _good(_iscsi_iface_get_from_sysfs(ctx, host_id, 0,
+                                       iface_kern_ids[i], &(*ifaces)[i]), rc, 
out);
+               }
+       } else {
+               /* if there's no iface exported in sysfs,
+                * we should still be able to create one record per host */
+               *ifaces = (struct iscsi_iface **) calloc(1, sizeof(struct 
iscsi_iface *));
+               _alloc_null_check(ctx, *ifaces, rc, out);
+               _good(_iscsi_iface_get_from_sysfs(ctx, host_id, 0, NULL, 
&(*ifaces)[0]), rc, out);
+               *iface_count = 1;
+       }
+out:
+       if (iface_kern_ids != NULL) {
+               for (uint32_t i = 0; i < *iface_count; i++) {
+                       free(iface_kern_ids[i]);
+               }
+               free(iface_kern_ids);
+       }
+       if (rc != LIBISCSI_OK) {
+               iscsi_ifaces_free(*ifaces, *iface_count);
+               *ifaces = NULL;
+               *iface_count = 0;
+       }
+       return rc;
+}
+
 int iscsi_default_iface_setup(struct iscsi_context *ctx)
 {
        int rc = LIBISCSI_OK;
@@ -280,7 +325,8 @@ int iscsi_default_iface_setup(struct iscsi_context *ctx)
        struct _iscsi_net_drv *ind = NULL;
        uint32_t *hids = NULL;
        uint32_t hid_count = 0;
-       struct iscsi_iface *iface = NULL;
+       struct iscsi_iface **ifaces = NULL;
+       uint32_t iface_count = 0;
        char path[PATH_MAX];
 
        assert(ctx != NULL);
@@ -345,20 +391,28 @@ int iscsi_default_iface_setup(struct iscsi_context *ctx)
        for (i = 0; i < hid_count; ++i) {
                /* Create /etc/iscsi/ifaces/<iface_name> file if not found
                 */
-               _good(_iscsi_iface_get_from_sysfs(ctx, hids[i], 0, &iface),
-                     rc, out);
-               if ( ! iscsi_is_default_iface(iface)) {
-                       snprintf(path, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR,
-                                iface->name);
-                       if (access(path, F_OK) != 0)
-                               rc = _iface_conf_write(ctx, iface);
+               _good(_iscsi_ifaces_get_from_sysfs(ctx, hids[i], &ifaces, 
&iface_count),
+                       rc, out);
+               for (uint32_t i = 0; i < iface_count; i++) {
+                       if ( ! iscsi_is_default_iface(ifaces[i])) {
+                               snprintf(path, PATH_MAX, "%s/%s", 
IFACE_CONFIG_DIR,
+                                        ifaces[i]->name);
+                               if (access(path, F_OK) != 0)
+                                       rc = _iface_conf_write(ctx, ifaces[i]);
+                       }
+                       iscsi_iface_free(ifaces[i]);
+                       ifaces[i] = NULL;
+                       if (rc != LIBISCSI_OK)
+                               goto out;
                }
-               iscsi_iface_free(iface);
-               if (rc != LIBISCSI_OK)
-                       goto out;
        }
 
 out:
+       if (ifaces != NULL) {
+               for (uint32_t i = 0; i < iface_count; i++)
+                       free(ifaces[i]);
+               free(ifaces);
+       }
        _eth_ifs_free(eifs, eif_count);
        free(hids);
        return rc;
diff --git a/libopeniscsiusr/iface.h b/libopeniscsiusr/iface.h
index eaf1832ec4c3..f20ea1365bbd 100644
--- a/libopeniscsiusr/iface.h
+++ b/libopeniscsiusr/iface.h
@@ -139,6 +139,7 @@ struct iscsi_iface {
 
 __DLL_LOCAL int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx,
                                            uint32_t host_id, uint32_t sid,
+                                           char *iface_kern_id,
                                            struct iscsi_iface **iface);
 
 __DLL_LOCAL bool _iface_is_valid(struct iscsi_iface *iface);
diff --git a/libopeniscsiusr/session.c b/libopeniscsiusr/session.c
index 4d9c57c8a158..7056c36ee49d 100644
--- a/libopeniscsiusr/session.c
+++ b/libopeniscsiusr/session.c
@@ -229,7 +229,8 @@ int iscsi_session_get(struct iscsi_context *ctx, uint32_t 
sid,
 
        _good(_iscsi_host_id_of_session(ctx, sid, &host_id), rc, out);
 
-       _good(_iscsi_iface_get_from_sysfs(ctx, host_id, sid, &((*se)->iface)),
+       /* does this need to the correct iface_kern_id for the session? */
+       _good(_iscsi_iface_get_from_sysfs(ctx, host_id, sid, NULL, 
&((*se)->iface)),
              rc, out);
 
 out:
diff --git a/libopeniscsiusr/sysfs.c b/libopeniscsiusr/sysfs.c
index 22eaf447e489..6f295b702821 100644
--- a/libopeniscsiusr/sysfs.c
+++ b/libopeniscsiusr/sysfs.c
@@ -454,8 +454,10 @@ bool _iscsi_transport_is_loaded(const char *transport_name)
        return false;
 }
 
-int _iscsi_iface_kern_id_of_host_id(struct iscsi_context *ctx,
-                                   uint32_t host_id, char *iface_kern_id)
+int _iscsi_iface_kern_ids_of_host_id(struct iscsi_context *ctx,
+                                   uint32_t host_id,
+                                   char ***iface_kern_ids,
+                                   uint32_t *iface_count)
 {
        char *sysfs_sh_path = NULL;
        char *dev_path = NULL;
@@ -485,24 +487,32 @@ int _iscsi_iface_kern_id_of_host_id(struct iscsi_context 
*ctx,
        _good(_scandir(ctx, sysfs_iface_path, &namelist, &n), rc, out);
 
        if (n == 0) {
-               rc = LIBISCSI_ERR_SYSFS_LOOKUP;
+               /* this is OK, and needed for transport drivers like 
+                * bnx2i and qedi */
+               rc = LIBISCSI_OK;
                _debug(ctx, "No iSCSI interface for iSCSI host %" PRIu32,
                       host_id);
                goto out;
        }
 
-       if (n != 1) {
-               rc = LIBISCSI_ERR_SYSFS_LOOKUP;
-               _debug(ctx, "Got unexpected(got %d, should be 1) file in "
-                      "folder %s", n, sysfs_iface_path);
-               goto out;
+       *iface_count = n;
+       *iface_kern_ids = calloc(*iface_count, sizeof(char *));
+       _alloc_null_check(ctx, *iface_kern_ids, rc, out);
+       for (uint32_t i = 0; i < *iface_count; i++) {
+               (*iface_kern_ids)[i] = strdup(namelist[i]->d_name);
+               _alloc_null_check(ctx, (*iface_kern_ids)[i], rc, out);
+               _debug(ctx, "Found iSCSI iface '%s' for iSCSI host %" PRIu32,
+               iface_kern_ids[i], host_id);
        }
-
-       snprintf(iface_kern_id, PATH_MAX, "%s", namelist[0]->d_name);
-       _debug(ctx, "Found iSCSI iface '%s' for iSCSI host %" PRIu32,
-              iface_kern_id, host_id);
-
 out:
+       if (rc != LIBISCSI_OK) {
+               for (uint32_t i = 0; i < *iface_count; i++ ) {
+                       free((*iface_kern_ids)[i]);
+               }
+               free(*iface_kern_ids);
+               *iface_kern_ids = NULL;
+               *iface_count = 0;
+       }
        _scandir_free(namelist, n);
        free(sysfs_sh_path);
        free(dev_path);
diff --git a/libopeniscsiusr/sysfs.h b/libopeniscsiusr/sysfs.h
index e285537655d7..768b98918544 100644
--- a/libopeniscsiusr/sysfs.h
+++ b/libopeniscsiusr/sysfs.h
@@ -67,11 +67,13 @@ __DLL_LOCAL int _iscsi_host_id_of_session(struct 
iscsi_context *ctx,
                                          uint32_t sid, uint32_t *host_id);
 
 /*
- * iface_kern_id should be char[PATH_MAX]
+ * iface_kern_id returns an allocated (char *)[iface_count]
+ * that needs to be freed by the caller
  */
-__DLL_LOCAL int _iscsi_iface_kern_id_of_host_id(struct iscsi_context *ctx,
-                                               uint32_t host_id,
-                                               char *iface_kern_id);
+__DLL_LOCAL int _iscsi_iface_kern_ids_of_host_id(struct iscsi_context *ctx,
+                                                uint32_t host_id,
+                                                char ***iface_kern_ids,
+                                                uint32_t *iface_count);
 
 /*
  * The memory of (uint32_t *sids) should be freed by free().
-- 
2.14.4

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to open-iscsi+unsubscr...@googlegroups.com.
To post to this group, send email to open-iscsi@googlegroups.com.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to