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 f5bc668b676e04ed0bf5e509b8af88b0c0d8fe28..bd9b55ea18ed85e0a3e6c49c953155f144faed12 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 8aa46c16ac9f48a564fa666cf3ddfb1c8613531b..7bb6c393c7e62798e6d4210f47f0daa68981ef17 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 9de33b52c8fddeaf5de7486c599a7ab14273b63c..d8c6f19d666279cf651f5a8a95960705e7d5aab0 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();