On 07/11/2013 07:40 AM, Saggi Mizrahi wrote:
> 
> 
> ----- Original Message -----
>> From: "Mike Christie" <micha...@cs.wisc.edu>
>> To: open-iscsi@googlegroups.com
>> Cc: "Saggi Mizrahi" <smizr...@redhat.com>
>> Sent: Tuesday, July 9, 2013 6:55:17 PM
>> Subject: Re: [PATCH] Make rescan run in parallel
>>
>> On 07/02/2013 08:30 AM, Saggi Mizrahi wrote:
>>> +                   if (wait(&chldrc) < 0) {
>>> +                           // ECHILD means no more children which is
>>> +                           // expected to happen sooner or later.
>>> +                           if (errno != ECHILD) {
>>> +                                   rc = errno;
>>> +                           }
>>> +                           break;
>>> +                   }
>>> +
>>> +                   if ((chldrc > 0) && (rc == 0)) {
>>> +                           // The non-parallel code path returns the first
>>> +                           // error so this keeps the same semantics.
>>> +                           rc = chldrc;
>>> +                   } else if (chldrc == 0) {
>>> +                           (*nr_found)++;
>>> +                   }
>>> +           }
>>>     }
>>
>> Thanks for the patch. It looks ok. When I merge I am going to fix up the
>> comments above for you. We use C /* */ style comments. You used them in
>> part of the patch but mixed it with the // style above.
>>
>> Just one questions. Does your app run the iscsiadm rescan command or is
>> this a result of users running it? It does not matter. I am just wondering.
> Our app runs it. I know we could just go poke sysfs ourselves but we figure
> that you guys will do a way better job with it.
> 
> No problem about the comment style. C99 is for weaklings anyway :).
> 
> What do I need to do to get this in to RHEL6.X?

I merged it in the upstream tree here. I do not know how to get it into
RHEL 6. I do not work at red hat anymore. You should talk to Chris Leech
or Andy Grover at red hat.

I attached the patch I ended up merging. It has the comment fix up and I
ported some of the other code that was missed in the original patch. I
think we could also enable parallel for the sync_session path which
would speed up boot, but I do not have time to test. Will leave that for
the distros/vendors supporting boot until I get time.

Thanks.

-- 
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 http://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/groups/opt_out.


diff --git a/usr/host.c b/usr/host.c
index b03e50f..1fcb350 100644
--- a/usr/host.c
+++ b/usr/host.c
@@ -242,7 +242,7 @@ static int host_info_print_tree(void *data, struct 
host_info *hinfo)
        link_info.data = &hinfo->host_no;
 
        err = iscsi_sysfs_for_each_session(&link_info, &num_found,
-                                          session_info_create_list);
+                                          session_info_create_list, 0);
        if (err || !num_found)
                return 0;
 
diff --git a/usr/initiator.c b/usr/initiator.c
index 86df222..a3b24b7 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
@@ -1855,7 +1855,8 @@ static int session_is_running(node_rec_t *rec)
        if (session_find_by_rec(rec))
                return 1;
 
-       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_session))
+       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_session,
+                                        0))
                return 1;
 
        return 0;
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
index 64a4ce7..aed10a3 100644
--- a/usr/iscsi_sysfs.c
+++ b/usr/iscsi_sysfs.c
@@ -24,6 +24,7 @@
 #include <dirent.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 
 #include "log.h"
 #include "initiator.h"
@@ -1167,11 +1168,13 @@ int iscsi_sysfs_get_sessioninfo_by_id(struct 
session_info *info, char *session)
 }
 
 int iscsi_sysfs_for_each_session(void *data, int *nr_found,
-                                iscsi_sysfs_session_op_fn *fn)
+                                iscsi_sysfs_session_op_fn *fn,
+                                int in_parallel)
 {
        struct dirent **namelist;
-       int rc = 0, n, i;
+       int rc = 0, n, i, chldrc = 0;
        struct session_info *info;
+       pid_t pid = 0;
 
        info = calloc(1, sizeof(*info));
        if (!info)
@@ -1193,14 +1196,52 @@ int iscsi_sysfs_for_each_session(void *data, int 
*nr_found,
                        continue;
                }
 
-               rc = fn(data, info);
-               if (rc > 0)
-                       break;
-               else if (rc == 0)
-                       (*nr_found)++;
-               else
-                       /* if less than zero it means it was not a match */
-                       rc = 0;
+               if (in_parallel) {
+                       pid = fork();
+               }
+               if (pid == 0) {
+                       rc = fn(data, info);
+                       if (in_parallel) {
+                               exit(rc);
+                       } else {
+                               if (rc > 0) {
+                                       break;
+                               } else if (rc == 0) {
+                                       (*nr_found)++;
+                               } else {
+                                       /* if less than zero it means it was 
not a match */
+                                       rc = 0;
+                               }
+                       }
+               } else if (pid < 0) {
+                       log_error("could not fork() for session %s, err %d",
+                                  namelist[i]->d_name, errno);
+               }
+       }
+
+       if (in_parallel) {
+               while (1) {
+                       if (wait(&chldrc) < 0) {
+                               /*
+                                * ECHILD means no more children which is
+                                * expected to happen sooner or later.
+                                */
+                               if (errno != ECHILD) {
+                                       rc = errno;
+                               }
+                               break;
+                       }
+
+                       if ((chldrc > 0) && (rc == 0)) {
+                               /*
+                                * The non-parallel code path returns the first
+                                * error so this keeps the same semantics.
+                                */
+                               rc = chldrc;
+                       } else if (chldrc == 0) {
+                               (*nr_found)++;
+                       }
+               }
        }
 
        for (i = 0; i < n; i++)
diff --git a/usr/iscsi_sysfs.h b/usr/iscsi_sysfs.h
index d130d36..9a56105 100644
--- a/usr/iscsi_sysfs.h
+++ b/usr/iscsi_sysfs.h
@@ -51,7 +51,8 @@ extern int iscsi_sysfs_for_each_iface_on_host(void *data, 
uint32_t host_no,
                                              int *nr_found,
                                              iscsi_sysfs_iface_op_fn *fn);
 extern int iscsi_sysfs_for_each_session(void *data, int *nr_found,
-                                       iscsi_sysfs_session_op_fn *fn);
+                                       iscsi_sysfs_session_op_fn *fn,
+                                       int in_parallel);
 extern int iscsi_sysfs_for_each_host(void *data, int *nr_found,
                                     iscsi_sysfs_host_op_fn *fn);
 extern uint32_t iscsi_sysfs_get_host_no_from_sid(uint32_t sid, int *err);
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 5030894..da0a3ec 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -347,7 +347,8 @@ match_startup_mode(node_rec_t *rec, char *mode)
 }
 
 static int
-for_each_session(struct node_rec *rec, iscsi_sysfs_session_op_fn *fn)
+for_each_session(struct node_rec *rec, iscsi_sysfs_session_op_fn *fn,
+                int in_parallel)
 {
        int err, num_found = 0;
 
@@ -355,7 +356,8 @@ for_each_session(struct node_rec *rec, 
iscsi_sysfs_session_op_fn *fn)
                num_found = 1;
                err = fn(rec, rec->session.info);
        } else {
-               err = iscsi_sysfs_for_each_session(rec, &num_found, fn);
+               err = iscsi_sysfs_for_each_session(rec, &num_found, fn,
+                                                  in_parallel);
        }
        if (err)
                log_error("Could not execute operation on all sessions: %s",
@@ -435,7 +437,7 @@ logout_by_startup(char *mode)
        rc = iscsi_logout_portals(mode, &nr_found, 1, __logout_by_startup);
        if (rc == ISCSI_ERR_NO_OBJS_FOUND)
                log_error("No matching sessions found");
-       return rc; 
+       return rc;
 }
 
 struct startup_data {
@@ -479,7 +481,7 @@ __do_leading_login(void *data, struct list_head *list, 
struct node_rec *rec)
         * If there is an existing session that matcthes the target,
         * the leading login is complete.
         */
-       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_target)) {
+       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_target, 
0)) {
                log_debug(1, "Skipping %s: Already a session for that target",
                          rec->name);
                return -1;
@@ -579,7 +581,7 @@ login_by_startup(char *mode)
                list_for_each_entry_safe(rec, tmp_rec, &startup.leading_logins,
                                         list) {
                        if (!iscsi_sysfs_for_each_session(rec, &nr_found,
-                                                         iscsi_match_target))
+                                                         iscsi_match_target, 
0))
                                missed_leading_login++;
                        /*
                         * Cleanup the list, since 'iscsi_login_portals_safe'
@@ -1210,7 +1212,7 @@ do_target_discovery(discovery_rec_t *drec, struct 
list_head *ifaces,
                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 "
-                                 "host.", iface_str(iface)); 
+                                 "host.", iface_str(iface));
                        /* try software iscsi */
                        continue;
                }
@@ -2116,12 +2118,12 @@ static int exec_node_op(int op, int do_login, int 
do_logout,
        }
 
        if (do_rescan) {
-               rc = for_each_session(rec, rescan_portal);
+               rc = for_each_session(rec, rescan_portal, 1);
                goto out;
        }
 
        if (do_stats) {
-               rc = for_each_session(rec, session_stats);
+               rc = for_each_session(rec, session_stats, 0);
                goto out;
        }
 
diff --git a/usr/iscsid.c b/usr/iscsid.c
index b4bb65b..8f19220 100644
--- a/usr/iscsid.c
+++ b/usr/iscsid.c
@@ -511,7 +511,8 @@ int main(int argc, char *argv[])
        if (pid == 0) {
                int nr_found = 0;
                /* child */
-               iscsi_sysfs_for_each_session(NULL, &nr_found, sync_session);
+               /* TODO - test with async support enabled */
+               iscsi_sysfs_for_each_session(NULL, &nr_found, sync_session, 0);
                exit(0);
        } else if (pid < 0) {
                log_error("Fork failed error %d: existing sessions"
diff --git a/usr/session_info.c b/usr/session_info.c
index 1f84c49..de156c6 100644
--- a/usr/session_info.c
+++ b/usr/session_info.c
@@ -368,7 +368,7 @@ int session_info_print(int info_level, struct session_info 
*info, int do_show)
                        num_found = 1;
                } else
                        err = iscsi_sysfs_for_each_session(info, &num_found,
-                                                  session_info_print_flat);
+                                                  session_info_print_flat, 0);
                break;
        case 3:
                version = iscsi_sysfs_get_iscsi_kernel_version();
@@ -403,7 +403,7 @@ int session_info_print(int info_level, struct session_info 
*info, int do_show)
                link_info.match_fn = NULL;
 
                err = iscsi_sysfs_for_each_session(&link_info, &num_found,
-                                                  session_info_create_list);
+                                                  session_info_create_list, 0);
                if (err || !num_found)
                        break;
 
diff --git a/usr/session_mgmt.c b/usr/session_mgmt.c
index 0b7373f..87b8e00 100644
--- a/usr/session_mgmt.c
+++ b/usr/session_mgmt.c
@@ -172,7 +172,7 @@ int iscsi_login_portal(void *data, struct list_head *list, 
struct node_rec *rec)
         * that are missing.
         */
        rc = iscsi_sysfs_for_each_session(rec, &session_count,
-                                         iscsi_match_session_count);
+                                         iscsi_match_session_count, 0);
        if (rc) {
                log_error("Could not count current number of sessions");
                goto done;
@@ -421,7 +421,7 @@ int iscsi_logout_portals(void *data, int *nr_found, int 
wait,
        *nr_found = 0;
 
        err = iscsi_sysfs_for_each_session(&link_info, nr_found,
-                                          session_info_create_list);
+                                          session_info_create_list, 0);
        if (err && !list_empty(&session_list))
                log_error("Could not read in all sessions: %s",
                          iscsi_err_to_str(err));
@@ -466,7 +466,8 @@ free_list:
 int iscsi_check_for_running_session(struct node_rec *rec)
 {
        int nr_found = 0;
-       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_session))
+       if (iscsi_sysfs_for_each_session(rec, &nr_found, iscsi_match_session,
+                                        0))
                return 1;
        return 0;
 }

Reply via email to