device-mapper-multipath/0019-multipathd-generalize-and-fix-wait_for_state_change_.patch
Benjamin Marzinski b05147c356 device-mapper-multipath-0.8.5-6
Change patch format to remove Git version
  * Patches 0001-0122 only have the patch format modified
Update to the head of the upstream staging branch plus redhat patches
  * Patches 0123-0134 & 1036-0142 are from the upstream staging branch
  * Patches 0143-1046 have been submitted upstream
  * Patch 0156 is a Red Hat only patch. Red Hat udev rules set ID_SERIAL
    from 60-persistent-storage.rules instead of 55-scsi-sg3_id.rules.
    Multipath's parse_vpd_pg83() function needs to match the ID_SERIAL
    value from udev.
Rename files
  * Previous patches 0123-0132 are now patches 1035 & 0147-0155
2021-03-26 13:33:56 -05:00

70 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;
}