aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2010-03-30 10:53:05 +0200
committerHannes Reinecke <hare@suse.de>2011-05-17 11:58:19 +0200
commit6b16726c299a7adc7d0d2b9a4da001928c04c341 (patch)
treebf9b95f466a6d66d46754aac9fef6a37869ceac1
parent651847893a8efdc3ed4f24a610db4b307b0dcefd (diff)
downloadmultipath-tools-6b16726c299a7adc7d0d2b9a4da001928c04c341.tar.gz
Start uevent service handler from main thread
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>
-rw-r--r--libmultipath/uevent.c19
-rw-r--r--libmultipath/uevent.h6
-rw-r--r--multipathd/main.c45
3 files changed, 51 insertions, 19 deletions
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
index f5bc668..bd9b55e 100644
--- a/libmultipath/uevent.c
+++ b/libmultipath/uevent.c
@@ -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
diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h
index 8aa46c1..7bb6c39 100644
--- a/libmultipath/uevent.h
+++ b/libmultipath/uevent.h
@@ -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 */
diff --git a/multipathd/main.c b/multipathd/main.c
index 9de33b5..d8c6f19 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -738,13 +738,24 @@ 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)
{
block_signal(SIGUSR1, NULL);
@@ -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);
@@ -1440,18 +1452,38 @@ 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();