[PATCH v4 21/22] multipathd: wait for checkers to complete

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Multipath again waits for running checkers to complete. In pathinfo(),
mutipath will just wait 1ms if the checker is running. In checkerloop(),
if there are running checkers, multipathd will drop the vecs lock and
wait for 5ms. The difference it wait times is because multipathd cannot
drop the vecs lock in pathinfo.

Reviewed-by: Martin Wilck <mwilck@xxxxxxxx>
Signed-off-by: Benjamin Marzinski <bmarzins@xxxxxxxxxx>
---
 libmultipath/discovery.c          |  9 ++++++++-
 libmultipath/libmultipath.version |  1 +
 multipathd/main.c                 | 12 +++++++++++-
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 6ccdfa0b..1d48c30a 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -2467,8 +2467,15 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
 	if (mask & DI_CHECKER) {
 		if (path_state == PATH_UP) {
 			int newstate = PATH_UNCHECKED;
-			if (start_checker(pp, conf, 0, path_state) == 0)
+			if (start_checker(pp, conf, 0, path_state) == 0) {
+				if (checker_need_wait(&pp->checker)) {
+					struct timespec wait = {
+						.tv_nsec = 1000 * 1000,
+					};
+					nanosleep(&wait, NULL);
+				}
 				newstate = get_state(pp);
+			}
 			if (newstate != PATH_PENDING ||
 			    pp->state == PATH_UNCHECKED ||
 			    pp->state == PATH_WILD)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 6439d3a7..c2e5f552 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -62,6 +62,7 @@ global:
 	checker_enable;
 	checker_message;
 	checker_name;
+	checker_need_wait;
 	checker_state_name;
 	check_foreign;
 	cleanup_bindings;
diff --git a/multipathd/main.c b/multipathd/main.c
index 846be5a9..e92f3ebd 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -2850,6 +2850,7 @@ update_uninitialized_path(struct vectors * vecs, struct path * pp)
 enum checker_state {
 	CHECKER_STARTING,
 	CHECKER_CHECKING_PATHS,
+	CHECKER_WAITING_FOR_PATHS,
 	CHECKER_UPDATING_PATHS,
 	CHECKER_FINISHED,
 };
@@ -2861,6 +2862,7 @@ check_paths(struct vectors *vecs, unsigned int ticks)
 	struct timespec diff_time, start_time, end_time;
 	struct path *pp;
 	int i;
+	bool need_wait = false;
 
 	get_monotonic_time(&start_time);
 
@@ -2871,6 +2873,9 @@ check_paths(struct vectors *vecs, unsigned int ticks)
 			pp->is_checked = check_path(pp, ticks);
 		else
 			pp->is_checked = check_uninitialized_path(pp, ticks);
+		if (pp->is_checked == CHECK_PATH_STARTED &&
+		    checker_need_wait(&pp->checker))
+			need_wait = true;
 		if (++paths_checked % 128 == 0 &&
 		    (lock_has_waiters(&vecs->lock) || waiting_clients())) {
 			get_monotonic_time(&end_time);
@@ -2879,7 +2884,7 @@ check_paths(struct vectors *vecs, unsigned int ticks)
 				return CHECKER_CHECKING_PATHS;
 		}
 	}
-	return CHECKER_UPDATING_PATHS;
+	return need_wait ? CHECKER_WAITING_FOR_PATHS : CHECKER_UPDATING_PATHS;
 }
 
 static enum checker_state
@@ -3001,6 +3006,11 @@ checkerloop (void *ap)
 			if (checker_state != CHECKER_FINISHED) {
 				/* Yield to waiters */
 				struct timespec wait = { .tv_nsec = 10000, };
+				if (checker_state == CHECKER_WAITING_FOR_PATHS) {
+					/* wait 5ms */
+					wait.tv_nsec = 5 * 1000 * 1000;
+					checker_state = CHECKER_UPDATING_PATHS;
+				}
 				nanosleep(&wait, NULL);
 			}
 		}
-- 
2.45.0





[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux