@@ -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)
@@ -62,6 +62,7 @@ global:
checker_enable;
checker_message;
checker_name;
+ checker_need_wait;
checker_state_name;
check_foreign;
cleanup_bindings;
@@ -2848,6 +2848,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,
};
@@ -2859,6 +2860,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);
@@ -2869,6 +2871,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);
@@ -2877,7 +2882,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
@@ -2999,6 +3004,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);
}
}
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. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> --- libmultipath/discovery.c | 9 ++++++++- libmultipath/libmultipath.version | 1 + multipathd/main.c | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-)