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


Reply via email to