device-mapper-multipath/0019-multipathd-generalize-and-fix-wait_for_state_change_.patch
DistroBaker 28d3ae407e Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/device-mapper-multipath.git#26a2cd7a3e189bf91263d17bc8a8c449cc043fb0
2021-01-21 16:56:27 +00:00

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