while uevent_listen() was grabbing new uevents, "multipathd show status" would still show show busy as "False". Add a check there, to make catch multipathd's uevent processing earlier. Also, access servicing_uev (as well as the new variable, adding_uev) atomically, just to make sure that the compiler doesn't do stupid things trying to optimize them.
Signed-off-by: Benjamin Marzinski <[email protected]> --- libmultipath/uevent.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c index be199af0..7eae2859 100644 --- a/libmultipath/uevent.c +++ b/libmultipath/uevent.c @@ -51,7 +51,8 @@ static pthread_cond_t uev_cond = PTHREAD_COND_INITIALIZER; static pthread_cond_t *uev_condp = &uev_cond; static uev_trigger *my_uev_trigger; static void *my_trigger_data; -static int servicing_uev; +static int servicing_uev; /* uatomic access only */ +static int adding_uev; /* uatomic access only */ struct uevent_filter_state { struct list_head uevq; @@ -70,13 +71,14 @@ static void reset_filter_state(struct uevent_filter_state *st) int is_uevent_busy(void) { - int empty, servicing; + int empty, servicing, adding; pthread_mutex_lock(uevq_lockp); empty = list_empty(&uevq); - servicing = servicing_uev; + servicing = uatomic_read(&servicing_uev); + adding = uatomic_read(&adding_uev); pthread_mutex_unlock(uevq_lockp); - return (!empty || servicing); + return (!empty || servicing || adding); } struct uevent * alloc_uevent (void) @@ -536,7 +538,7 @@ int uevent_dispatch(int (*uev_trigger)(struct uevent *, void * trigger_data), pthread_cleanup_push(cleanup_mutex, uevq_lockp); pthread_mutex_lock(uevq_lockp); - servicing_uev = !list_empty(&filter_state.uevq); + uatomic_set(&servicing_uev, !list_empty(&filter_state.uevq)); while (list_empty(&filter_state.uevq) && list_empty(&uevq)) { condlog(4, "%s: waiting for events", __func__); @@ -544,7 +546,7 @@ int uevent_dispatch(int (*uev_trigger)(struct uevent *, void * trigger_data), condlog(4, "%s: waking up", __func__); } - servicing_uev = 1; + uatomic_set(&servicing_uev, 1); /* * "old_tail" is the list element towards which merge_uevq() * will iterate: the last element of uevq before @@ -730,6 +732,7 @@ int uevent_listen(struct udev *udev) int fdcount, events; struct pollfd ev_poll = { .fd = fd, .events = POLLIN, }; + uatomic_set(&adding_uev, 0); fdcount = poll(&ev_poll, 1, -1); if (fdcount < 0) { if (errno == EINTR) @@ -739,6 +742,8 @@ int uevent_listen(struct udev *udev) err = -errno; break; } + uatomic_set(&adding_uev, 1); + events = uevent_receive_events(fd, &uevlisten_tmp, monitor); if (events <= 0) continue; -- 2.50.1
