300 lines
8.9 KiB
Diff
300 lines
8.9 KiB
Diff
|
From 3c5ec3835d5fd57a993cb814ecd74b48419a7459 Mon Sep 17 00:00:00 2001
|
||
|
From: Mike Christie <michaelc@cs.wisc.edu>
|
||
|
Date: Mon, 29 Jul 2013 14:13:36 -0500
|
||
|
Subject: Make rescan run in parallel
|
||
|
|
||
|
Patch from Saggi Mizrahi:
|
||
|
|
||
|
This fixes a problem where a host which is inaccessible would block the
|
||
|
scan of other hosts in the system.
|
||
|
|
||
|
[compilation and minor cosmetic fixes by Mike Christie]
|
||
|
Signed-off-by: Saggi Mizrahi <smizrahi@redhat.com>
|
||
|
---
|
||
|
usr/host.c | 2 +-
|
||
|
usr/initiator.c | 3 ++-
|
||
|
usr/iscsi_sysfs.c | 61 +++++++++++++++++++++++++++++++++++++++++++++---------
|
||
|
usr/iscsi_sysfs.h | 3 ++-
|
||
|
usr/iscsiadm.c | 18 +++++++++-------
|
||
|
usr/iscsid.c | 3 ++-
|
||
|
usr/session_info.c | 4 ++--
|
||
|
usr/session_mgmt.c | 7 ++++---
|
||
|
8 files changed, 74 insertions(+), 27 deletions(-)
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
--
|
||
|
1.8.1.4
|
||
|
|