Start uevent service handler from main thread
authorHannes Reinecke <hare@suse.de>
Tue, 30 Mar 2010 08:53:05 +0000 (10:53 +0200)
committerHannes Reinecke <hare@suse.de>
Tue, 17 May 2011 09:58:19 +0000 (11:58 +0200)
We should start the uevent handler as early as possible so as
to not miss out any events. However, we cannot process these
events until after all paths have been discovered. So we
should be starting the uevent service routine only after
the discovery process.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/uevent.c
libmultipath/uevent.h
multipathd/main.c

index f5bc668..bd9b55e 100644 (file)
@@ -130,9 +130,12 @@ static void uevq_stop(void *arg)
 /*
  * Service the uevent queue.
  */
-static void *
-uevq_thread(void * et)
+int uevent_dispatch(int (*uev_trigger)(struct uevent *, void * trigger_data),
+                   void * trigger_data)
 {
+       my_uev_trigger = uev_trigger;
+       my_trigger_data = trigger_data;
+
        mlockall(MCL_CURRENT | MCL_FUTURE);
 
        while (1) {
@@ -154,11 +157,11 @@ uevq_thread(void * et)
                        break;
                service_uevq(&uevq_tmp);
        }
-       return NULL;
+       condlog(3, "Terminating uev service queue");
+       return 0;
 }
 
-int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
-                 void * trigger_data)
+int uevent_listen(void)
 {
        int sock;
        struct sockaddr_nl snl;
@@ -169,12 +172,8 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
        int rcvsz = 0;
        int rcvszsz = sizeof(rcvsz);
        unsigned int *prcvszsz = (unsigned int *)&rcvszsz;
-       pthread_attr_t attr;
        const int feature_on = 1;
 
-       my_uev_trigger = uev_trigger;
-       my_trigger_data = trigger_data;
-
        /*
         * Queue uevents for service by dedicated thread so that the uevent
         * listening thread does not block on multipathd locks (vecs->lock)
@@ -187,8 +186,6 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
        pthread_cond_init(uev_condp, NULL);
 
        pthread_cleanup_push(uevq_stop, NULL);
-       setup_thread_attr(&attr, 64 * 1024, 0);
-       pthread_create(&uevq_thr, &attr, uevq_thread, NULL);
 
        /*
         * First check whether we have a udev socket
index 8aa46c1..7bb6c39 100644 (file)
@@ -21,9 +21,11 @@ struct uevent {
        char *envp[HOTPLUG_NUM_ENVP];
 };
 
-int uevent_listen(int (*store_uev)(struct uevent *, void * trigger_data),
-                 void * trigger_data);
 int is_uevent_busy(void);
 void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
 
+int uevent_listen(void);
+int uevent_dispatch(int (*store_uev)(struct uevent *, void * trigger_data),
+                   void * trigger_data);
+
 #endif /* _UEVENT_H */
index 9de33b5..d8c6f19 100644 (file)
@@ -738,12 +738,23 @@ ueventloop (void * ap)
        block_signal(SIGUSR1, NULL);
        block_signal(SIGHUP, NULL);
 
-       if (uevent_listen(&uev_trigger, ap))
-               fprintf(stderr, "error starting uevent listener");
+       if (uevent_listen())
+               condlog(0, "error starting uevent listener");
 
        return NULL;
 }
 
+static void *
+uevqloop (void * ap)
+{
+       block_signal(SIGUSR1, NULL);
+       block_signal(SIGHUP, NULL);
+
+       if (uevent_dispatch(&uev_trigger, ap))
+               condlog(0, "error starting uevent dispatcher");
+
+       return NULL;
+}
 static void *
 uxlsnrloop (void * ap)
 {
@@ -1367,11 +1378,12 @@ set_oom_adj (int val)
 static int
 child (void * param)
 {
-       pthread_t check_thr, uevent_thr, uxlsnr_thr;
+       pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr;
        pthread_attr_t log_attr, misc_attr;
        struct vectors * vecs;
        struct multipath * mpp;
        int i;
+       int rc;
 
        mlockall(MCL_CURRENT | MCL_FUTURE);
 
@@ -1439,19 +1451,39 @@ child (void * param)
        }
        conf->daemon = 1;
        udev_set_sync_support(0);
+       /*
+        * Start uevent listener early to catch events
+        */
+       if ((rc = pthread_create(&uevent_thr, &misc_attr, ueventloop, vecs))) {
+               condlog(0, "failed to create uevent thread: %d", rc);
+               exit(1);
+       }
        /*
         * fetch and configure both paths and multipaths
         */
+       lock(vecs->lock);
        if (configure(vecs, 1)) {
+               unlock(vecs->lock);
                condlog(0, "failure during configuration");
                exit(1);
        }
+       unlock(vecs->lock);
+
        /*
         * start threads
         */
-       pthread_create(&check_thr, &misc_attr, checkerloop, vecs);
-       pthread_create(&uevent_thr, &misc_attr, ueventloop, vecs);
-       pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs);
+       if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) {
+               condlog(0,"failed to create checker loop thread: %d", rc);
+               exit(1);
+       }
+       if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) {
+               condlog(0, "failed to create cli listener: %d", rc);
+               exit(1);
+       }
+       if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) {
+               condlog(0, "failed to create uevent dispatcher: %d", rc);
+               exit(1);
+       }
        pthread_attr_destroy(&misc_attr);
 
        pthread_mutex_lock(&exit_mutex);
@@ -1471,6 +1503,7 @@ child (void * param)
        pthread_cancel(check_thr);
        pthread_cancel(uevent_thr);
        pthread_cancel(uxlsnr_thr);
+       pthread_cancel(uevq_thr);
 
        sysfs_cleanup();