73 lines
2.2 KiB
Diff
73 lines
2.2 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Martin Wilck <mwilck@suse.com>
|
||
|
Date: Tue, 15 Sep 2020 12:46:36 +0200
|
||
|
Subject: [PATCH] multipathd: generalize and fix wait_for_state_change_if()
|
||
|
|
||
|
It's unlikely but not impossible that other threads change the state
|
||
|
while we're waiting, and if we grab the lock again, it's still not
|
||
|
what we wanted. We need to continue waiting until either the condition
|
||
|
is met, or time timeout expired.
|
||
|
|
||
|
Moreover, generalize this code so that it can also be used in
|
||
|
set_config_state().
|
||
|
|
||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||
|
---
|
||
|
multipathd/main.c | 25 ++++++++++++++++++-------
|
||
|
1 file changed, 18 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||
|
index d081b3e9..1fb0ee62 100644
|
||
|
--- a/multipathd/main.c
|
||
|
+++ b/multipathd/main.c
|
||
|
@@ -223,6 +223,23 @@ static void config_cleanup(__attribute__((unused)) void *arg)
|
||
|
pthread_mutex_unlock(&config_lock);
|
||
|
}
|
||
|
|
||
|
+#define __wait_for_state_change(condition, ms) \
|
||
|
+ ({ \
|
||
|
+ struct timespec tmo; \
|
||
|
+ int rc = 0; \
|
||
|
+ \
|
||
|
+ if (condition) { \
|
||
|
+ get_monotonic_time(&tmo); \
|
||
|
+ tmo.tv_nsec += (ms) * 1000 * 1000; \
|
||
|
+ normalize_timespec(&tmo); \
|
||
|
+ do \
|
||
|
+ rc = pthread_cond_timedwait( \
|
||
|
+ &config_cond, &config_lock, &tmo); \
|
||
|
+ while (rc == 0 && (condition)); \
|
||
|
+ } \
|
||
|
+ rc; \
|
||
|
+ })
|
||
|
+
|
||
|
/*
|
||
|
* If the current status is @oldstate, wait for at most @ms milliseconds
|
||
|
* for the state to change, and return the new state, which may still be
|
||
|
@@ -232,20 +249,14 @@ enum daemon_status wait_for_state_change_if(enum daemon_status oldstate,
|
||
|
unsigned long ms)
|
||
|
{
|
||
|
enum daemon_status st;
|
||
|
- struct timespec tmo;
|
||
|
|
||
|
if (oldstate == DAEMON_SHUTDOWN)
|
||
|
return DAEMON_SHUTDOWN;
|
||
|
|
||
|
pthread_mutex_lock(&config_lock);
|
||
|
pthread_cleanup_push(config_cleanup, NULL);
|
||
|
+ __wait_for_state_change(running_state == oldstate, ms);
|
||
|
st = running_state;
|
||
|
- if (st == oldstate && clock_gettime(CLOCK_MONOTONIC, &tmo) == 0) {
|
||
|
- tmo.tv_nsec += ms * 1000 * 1000;
|
||
|
- normalize_timespec(&tmo);
|
||
|
- (void)pthread_cond_timedwait(&config_cond, &config_lock, &tmo);
|
||
|
- st = running_state;
|
||
|
- }
|
||
|
pthread_cleanup_pop(1);
|
||
|
return st;
|
||
|
}
|
||
|
--
|
||
|
2.17.2
|
||
|
|