[build] legacy files update
[platform/upstream/multipath-tools.git] / multipathd / main.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Kiyoshi Ueda, NEC
4  * Copyright (c) 2005 Benjamin Marzinski, Redhat
5  * Copyright (c) 2005 Edward Goggin, EMC
6  */
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #include <libdevmapper.h>
10 #include <wait.h>
11 #include <sys/mman.h>
12 #include <sys/types.h>
13 #include <fcntl.h>
14 #include <errno.h>
15
16 /*
17  * libsysfs
18  */
19 #include <sysfs/libsysfs.h>
20 #include <sysfs/dlist.h>
21
22 /*
23  * libcheckers
24  */
25 #include <checkers.h>
26 #include <path_state.h>
27
28 /*
29  * libmultipath
30  */
31 #include <parser.h>
32 #include <vector.h>
33 #include <memory.h>
34 #include <config.h>
35 #include <callout.h>
36 #include <util.h>
37 #include <blacklist.h>
38 #include <hwtable.h>
39 #include <defaults.h>
40 #include <structs.h>
41 #include <structs_vec.h>
42 #include <dmparser.h>
43 #include <devmapper.h>
44 #include <dict.h>
45 #include <discovery.h>
46 #include <debug.h>
47 #include <propsel.h>
48 #include <uevent.h>
49 #include <switchgroup.h>
50 #include <path_state.h>
51 #include <print.h>
52 #include <configure.h>
53
54 #include "main.h"
55 #include "pidfile.h"
56 #include "uxlsnr.h"
57 #include "uxclnt.h"
58 #include "cli.h"
59 #include "cli_handlers.h"
60
61 #define FILE_NAME_SIZE 256
62 #define CMDSIZE 160
63
64 #define LOG_MSG(a,b) \
65         if (strlen(b)) { \
66                 condlog(a, "%s: %s", pp->dev_t, b); \
67                 memset(b, 0, MAX_CHECKER_MSG_SIZE); \
68         }
69
70 #ifdef LCKDBG
71 #define lock(a) \
72         fprintf(stderr, "%s:%s(%i) lock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
73         pthread_mutex_lock(a)
74 #define unlock(a) \
75         fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
76         pthread_mutex_unlock(a)
77 #define lock_cleanup_pop(a) \
78         fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
79         pthread_cleanup_pop(1);
80 #else
81 #define lock(a) pthread_mutex_lock(a)
82 #define unlock(a) pthread_mutex_unlock(a)
83 #define lock_cleanup_pop(a) pthread_cleanup_pop(1);
84 #endif
85
86 pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
87 pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
88
89 /*
90  * structs
91  */
92 struct vectors * gvecs; /* global copy of vecs for use in sig handlers */
93
94 struct event_thread {
95         struct dm_task *dmt;
96         pthread_t thread;
97         int event_nr;
98         char mapname[WWID_SIZE];
99         struct vectors *vecs;
100 };
101
102 static struct event_thread *
103 alloc_waiter (void)
104 {
105
106         struct event_thread * wp;
107
108         wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
109
110         return wp;
111 }
112
113 static void
114 free_waiter (void * data)
115 {
116         struct event_thread * wp = (struct event_thread *)data;
117
118         if (wp->dmt)
119                 dm_task_destroy(wp->dmt);
120         FREE(wp);
121 }
122
123 static void
124 stop_waiter_thread (struct multipath * mpp, struct vectors * vecs)
125 {
126         struct event_thread * wp = (struct event_thread *)mpp->waiter;
127         
128         if (!wp) {
129                 condlog(3, "%s: no waiter thread", mpp->alias);
130                 return;
131         }
132         condlog(2, "%s: stop event checker thread", wp->mapname);
133         pthread_kill((pthread_t)wp->thread, SIGUSR1);
134 }
135
136 static void
137 cleanup_lock (void * data)
138 {
139         pthread_mutex_unlock((pthread_mutex_t *)data);
140 }
141
142 /*
143  * mpp->no_path_retry:
144  *   -2 (QUEUE) : queue_if_no_path enabled, never turned off
145  *   -1 (FAIL)  : fail_if_no_path
146  *    0 (UNDEF) : nothing
147  *   >0         : queue_if_no_path enabled, turned off after polling n times
148  */
149 static void
150 update_queue_mode_del_path(struct multipath *mpp)
151 {
152         if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
153                 /*
154                  * Enter retry mode.
155                  * meaning of +1: retry_tick may be decremented in
156                  *                checkerloop before starting retry.
157                  */
158                 mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
159                 condlog(1, "%s: Entering recovery mode: max_retries=%d",
160                         mpp->alias, mpp->no_path_retry);
161         }
162         condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
163 }
164
165 static void
166 update_queue_mode_add_path(struct multipath *mpp)
167 {
168         if (mpp->nr_active++ == 0 && mpp->no_path_retry > 0) {
169                 /* come back to normal mode from retry mode */
170                 mpp->retry_tick = 0;
171                 dm_queue_if_no_path(mpp->alias, 1);
172                 condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
173                 condlog(1, "%s: Recovered to normal mode", mpp->alias);
174         }
175         condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
176 }
177
178 static int
179 need_switch_pathgroup (struct multipath * mpp, int refresh)
180 {
181         struct pathgroup * pgp;
182         struct path * pp;
183         int i, j;
184
185         if (!mpp || mpp->pgfailback == -FAILBACK_MANUAL)
186                 return 0;
187
188         /*
189          * Refresh path priority values
190          */
191         if (refresh)
192                 vector_foreach_slot (mpp->pg, pgp, i)
193                         vector_foreach_slot (pgp->paths, pp, j)
194                                 pathinfo(pp, conf->hwtable, DI_PRIO);
195
196         mpp->bestpg = select_path_group(mpp);
197
198         if (mpp->bestpg != mpp->nextpg)
199                 return 1;
200
201         return 0;
202 }
203
204 static void
205 switch_pathgroup (struct multipath * mpp)
206 {
207         dm_switchgroup(mpp->alias, mpp->bestpg);
208         condlog(2, "%s: switch to path group #%i",
209                  mpp->alias, mpp->bestpg);
210 }
211
212 static int
213 coalesce_maps(struct vectors *vecs, vector nmpv)
214 {
215         struct multipath * ompp;
216         vector ompv = vecs->mpvec;
217         int i, j;
218
219         condlog(3, "coalesce_maps vs = %u", VECTOR_SIZE(ompv));
220         condlog(3, "coalesce_maps vs = %u", VECTOR_SIZE(nmpv));
221
222         vector_foreach_slot (ompv, ompp, i) {
223                 if (!find_mp_by_wwid(nmpv, ompp->wwid)) {
224                         /*
225                          * remove all current maps not allowed by the
226                          * current configuration
227                          */
228                         if (dm_flush_map(ompp->alias, DEFAULT_TARGET)) {
229                                 condlog(0, "%s: unable to flush devmap",
230                                         ompp->alias);
231                                 /*
232                                  * may be just because the device is open
233                                  */
234                                 if (!vector_alloc_slot(nmpv))
235                                         return 1;
236
237                                 vector_set_slot(nmpv, ompp);
238                                 setup_multipath(vecs, ompp);
239
240                                 if ((j = find_slot(ompv, (void *)ompp)) != -1)
241                                         vector_del_slot(ompv, j);
242
243                                 continue;
244                         }
245                         else
246                                 condlog(3, "%s devmap removed", ompp->alias);
247                 }
248         }
249         return 0;
250 }
251
252 static int
253 update_multipath (struct vectors *vecs, char *mapname)
254 {
255         struct multipath *mpp;
256         struct pathgroup  *pgp;
257         struct path *pp;
258         int i, j;
259         int r = 1;
260
261         mpp = find_mp_by_alias(vecs->mpvec, mapname);
262
263         if (!mpp)
264                 goto out;
265
266         free_pgvec(mpp->pg, KEEP_PATHS);
267         mpp->pg = NULL;
268
269         if (setup_multipath(vecs, mpp))
270                 goto out; /* mpp freed in setup_multipath */
271
272         /*
273          * compare checkers states with DM states
274          */
275         vector_foreach_slot (mpp->pg, pgp, i) {
276                 vector_foreach_slot (pgp->paths, pp, j) {
277                         if (pp->dmstate != PSTATE_FAILED)
278                                 continue;
279
280                         if (pp->state != PATH_DOWN) {
281                                 condlog(2, "%s: mark as failed", pp->dev_t);
282                                 pp->state = PATH_DOWN;
283                                 update_queue_mode_del_path(mpp);
284
285                                 /*
286                                  * if opportune,
287                                  * schedule the next check earlier
288                                  */
289                                 if (pp->tick > conf->checkint)
290                                         pp->tick = conf->checkint;
291                         }
292                 }
293         }
294         r = 0;
295 out:
296         if (r)
297                 condlog(0, "failed to update multipath");
298
299         return r;
300 }
301
302 static sigset_t unblock_signals(void)
303 {
304         sigset_t set, old;
305
306         sigemptyset(&set);
307         sigaddset(&set, SIGHUP);
308         sigaddset(&set, SIGUSR1);
309         pthread_sigmask(SIG_UNBLOCK, &set, &old);
310         return old;
311 }
312
313 /*
314  * returns the reschedule delay
315  * negative means *stop*
316  */
317 static int
318 waiteventloop (struct event_thread * waiter)
319 {
320         sigset_t set;
321         int event_nr;
322         int r;
323
324         if (!waiter->event_nr)
325                 waiter->event_nr = dm_geteventnr(waiter->mapname);
326
327         if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) {
328                 condlog(0, "%s: devmap event #%i dm_task_create error",
329                                 waiter->mapname, waiter->event_nr);
330                 return 1;
331         }
332
333         if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
334                 condlog(0, "%s: devmap event #%i dm_task_set_name error",
335                                 waiter->mapname, waiter->event_nr);
336                 dm_task_destroy(waiter->dmt);
337                 return 1;
338         }
339
340         if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
341                                                       waiter->event_nr)) {
342                 condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
343                                 waiter->mapname, waiter->event_nr);
344                 dm_task_destroy(waiter->dmt);
345                 return 1;
346         }
347
348         dm_task_no_open_count(waiter->dmt);
349         
350         /* accept wait interruption */
351         set = unblock_signals();
352
353         /* interruption spits messages */
354         dm_shut_log();
355
356         /* wait */
357         r = dm_task_run(waiter->dmt);
358
359         /* wait is over : event or interrupt */
360         pthread_sigmask(SIG_SETMASK, &set, NULL);
361         //dm_restore_log();
362
363         if (!r) /* wait interrupted by signal */
364                 return -1;
365
366         dm_task_destroy(waiter->dmt);
367         waiter->dmt = NULL;
368         waiter->event_nr++;
369
370         /*
371          * upon event ...
372          */
373         while (1) {
374                 condlog(3, "%s: devmap event #%i",
375                                 waiter->mapname, waiter->event_nr);
376
377                 /*
378                  * event might be :
379                  *
380                  * 1) a table reload, which means our mpp structure is
381                  *    obsolete : refresh it through update_multipath()
382                  * 2) a path failed by DM : mark as such through
383                  *    update_multipath()
384                  * 3) map has gone away : stop the thread.
385                  * 4) a path reinstate : nothing to do
386                  * 5) a switch group : nothing to do
387                  */
388                 pthread_cleanup_push(cleanup_lock, waiter->vecs->lock);
389                 lock(waiter->vecs->lock);
390                 r = update_multipath(waiter->vecs, waiter->mapname);
391                 lock_cleanup_pop(waiter->vecs->lock);
392
393                 if (r)
394                         return -1; /* stop the thread */
395
396                 event_nr = dm_geteventnr(waiter->mapname);
397
398                 if (waiter->event_nr == event_nr)
399                         return 1; /* upon problem reschedule 1s later */
400
401                 waiter->event_nr = event_nr;
402         }
403         return -1; /* never reach there */
404 }
405
406 static void *
407 waitevent (void * et)
408 {
409         int r;
410         struct event_thread *waiter;
411
412         mlockall(MCL_CURRENT | MCL_FUTURE);
413
414         waiter = (struct event_thread *)et;
415         pthread_cleanup_push(free_waiter, et);
416
417         while (1) {
418                 r = waiteventloop(waiter);
419
420                 if (r < 0)
421                         break;
422
423                 sleep(r);
424         }
425
426         pthread_cleanup_pop(1);
427         return NULL;
428 }
429
430 static int
431 start_waiter_thread (struct multipath * mpp, struct vectors * vecs)
432 {
433         pthread_attr_t attr;
434         struct event_thread * wp;
435
436         if (!mpp)
437                 return 0;
438
439         if (pthread_attr_init(&attr))
440                 goto out;
441
442         pthread_attr_setstacksize(&attr, 32 * 1024);
443         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
444
445         wp = alloc_waiter();
446
447         if (!wp)
448                 goto out;
449
450         mpp->waiter = (void *)wp;
451         strncpy(wp->mapname, mpp->alias, WWID_SIZE);
452         wp->vecs = vecs;
453
454         if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
455                 condlog(0, "%s: cannot create event checker", wp->mapname);
456                 goto out1;
457         }
458         condlog(2, "%s: event checker started", wp->mapname);
459
460         return 0;
461 out1:
462         free_waiter(wp);
463         mpp->waiter = NULL;
464 out:
465         condlog(0, "failed to start waiter thread");
466         return 1;
467 }
468
469 static int
470 flush_map(struct multipath * mpp, char * devname, struct vectors * vecs)
471 {
472         /*
473          * clear references to this map before flushing so we can ignore
474          * the spurious uevent we may generate with the dm_flush_map call below
475          */
476         if (dm_flush_map(mpp->alias, DEFAULT_TARGET)) {
477                 /*
478                  * May not really be an error -- if the map was already flushed
479                  * from the device mapper by dmsetup(8) for instance.
480                  */
481                 condlog(0, "%s: can't flush", devname);
482                 return 1;
483         }
484         else
485                 condlog(3, "%s: devmap %s removed", devname, mpp->alias);
486
487         orphan_paths(vecs->pathvec, mpp);
488         remove_map(mpp, vecs, stop_waiter_thread, 1);
489
490         return 0;
491 }
492
493 int
494 uev_add_map (char * devname, struct vectors * vecs)
495 {
496         int major, minor;
497         char dev_t[BLK_DEV_SIZE];
498         char * alias;
499         struct multipath * mpp;
500
501         if (sscanf(devname, "dm-%d", &minor) == 1 &&
502             !sysfs_get_dev(sysfs_path, devname, dev_t, BLK_DEV_SIZE) &&
503             sscanf(dev_t, "%d:%d", &major, &minor) == 2)
504                 alias = dm_mapname(major, minor);
505         else
506                 alias = STRDUP(devname);
507                 
508         if (!alias)
509                 return 1;
510         
511         if (!dm_type(alias, DEFAULT_TARGET)) {
512                 condlog(4, "%s: not a multipath map", alias);
513                 FREE(alias);
514                 return 0;
515         }
516
517         mpp = find_mp_by_alias(vecs->mpvec, alias);
518
519         if (mpp) {
520                 /*
521                  * Not really an error -- we generate our own uevent
522                  * if we create a multipath mapped device as a result
523                  * of uev_add_path
524                  */
525                 condlog(0, "%s: spurious uevent, devmap already registered",
526                         devname);
527                 FREE(alias);
528                 return 0;
529         }
530
531         /*
532          * now we can register the map
533          */
534         if ((mpp = add_map_without_path(vecs, minor, alias,
535                                         start_waiter_thread))) {
536                 condlog(3, "%s devmap %s added", devname, alias);
537                 return 0;
538         }
539
540         condlog(0, "%s: uev_add_map failed", alias);
541         return 1;
542 }
543
544 int
545 uev_remove_map (char * devname, struct vectors * vecs)
546 {
547         int minor;
548         struct multipath * mpp;
549
550         if (sscanf(devname, "dm-%d", &minor) == 1)
551                 mpp = find_mp_by_minor(vecs->mpvec, minor);
552         else
553                 mpp = find_mp_by_alias(vecs->mpvec, devname);
554
555         if (!mpp) {
556                 condlog(3, "%s: devmap not registered, can't remove",
557                         devname);
558                 return 0;
559         }
560
561         condlog(2, "remove %s devmap", mpp->alias);
562         remove_map(mpp, vecs, stop_waiter_thread, 1);
563
564         return 0;
565 }
566
567 int
568 uev_add_path (char * devname, struct vectors * vecs)
569 {
570         struct multipath * mpp;
571         struct path * pp;
572         char empty_buff[WWID_SIZE] = {0};
573
574         condlog(3, "%s: uev_add_path", devname);
575
576         pp = find_path_by_dev(vecs->pathvec, devname);
577         if (pp) {
578                 condlog(0, "%s: spurious uevent, path already in pathvec, %p",
579                         devname, pp->mpp);
580                 /*
581                  * allow reconfig of orphaned path here
582                  */
583                 if (pp->mpp) return 1;
584         }
585         else {
586                 /*
587                  * get path vital state
588                  */
589                 if (!(pp = store_pathinfo(vecs->pathvec, conf->hwtable,
590                       devname, DI_ALL))) {
591                         condlog(0, "%s: failed to store path info", devname);
592                         return 1;
593                 }
594                 pp->checkint = conf->checkint;
595         }
596
597         /*
598          * need path UID to go any further
599          */
600         if (memcmp(empty_buff, pp->wwid, WWID_SIZE) == 0) {
601                 condlog(0, "%s: failed to get path uid", devname);
602                 return 1; /* leave path added to pathvec */
603         }
604
605         mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
606 rescan:
607         if (mpp) {
608                 if (adopt_paths(vecs->pathvec, mpp))
609                         return 1; /* leave path added to pathvec */
610
611                 verify_paths(mpp, vecs, NULL);
612                 condlog(0, "%s: ownership set to %s", pp->dev_t, mpp->alias);
613                 mpp->action = ACT_RELOAD;
614         }
615         else {
616                 if ((mpp = add_map_with_path(vecs, pp, 1)))
617                         mpp->action = ACT_CREATE;
618                 else
619                         return 1; /* leave path added to pathvec */
620         }
621
622         /*
623          * push the map to the device-mapper
624          */
625         if (setup_map(mpp)) {
626                 condlog(0, "%s: failed to setup map for addition of new "
627                         "path %s", mpp->alias, devname);
628                 goto out;
629         }
630         /*
631          * reload the map for the multipath mapped device
632          */
633         if (domap(mpp) <= 0) {
634                 condlog(0, "%s: failed in domap for addition of new "
635                         "path %s", mpp->alias, devname);
636                 /*
637                  * deal with asynchronous uevents :((
638                  */
639                 if (mpp->action == ACT_RELOAD) {
640                         condlog(0, "%s: uev_add_path sleep", mpp->alias);
641                         sleep(1);
642                         update_mpp_paths(mpp);
643                         goto rescan;
644                 }
645                 else
646                         goto out;
647         }
648
649         /*
650          * update our state from kernel regardless of create or reload
651          */
652         if (setup_multipath(vecs, mpp))
653                 goto out;
654
655         if (mpp->action == ACT_CREATE &&
656             start_waiter_thread(mpp, vecs))
657                         goto out;
658
659         condlog(3, "%s path added to devmap %s", devname, mpp->alias);
660         return 0;
661
662 out:
663         remove_map(mpp, vecs, NULL, 1);
664         return 1;
665 }
666
667 int
668 uev_remove_path (char * devname, struct vectors * vecs)
669 {
670         struct multipath * mpp;
671         struct path * pp;
672         int redo, i;
673         int rm_path = 1;
674
675         condlog(3, "%s: uev_remove_path", devname);
676
677         pp = find_path_by_dev(vecs->pathvec, devname);
678         if (!pp) {
679                 condlog(0, "%s: spurious uevent, path not in pathvec", devname);
680                 return 1;
681         }
682
683         /*
684          * avoid referring to the map of an orphanned path
685          */
686         if ((mpp = pp->mpp)) {
687
688                 /*
689                  * remove the map IFF removing the last path
690                  */
691                 if (pathcount(mpp, PATH_WILD) > 1) {
692                         vector rpvec = vector_alloc();
693                         struct path * mypp;
694                         int j;
695
696                         /*
697                          * transform the mp->pg vector of vectors of paths
698                          * into a mp->params string to feed the device-mapper
699                          */
700                         update_mpp_paths(mpp);
701                         if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
702                                 vector_del_slot(mpp->paths, i);
703
704 rescan:
705                         redo = verify_paths(mpp, vecs, rpvec);
706                         if (VECTOR_SIZE(mpp->paths) == 0) {
707                                 char alias[WWID_SIZE];
708
709                                 /*
710                                  * flush_map will fail if the device is open
711                                  */
712                                 strncpy(alias, mpp->alias, WWID_SIZE);
713                                 if (flush_map(mpp, devname, vecs)) {
714                                         rm_path = 0;
715                                         vector_foreach_slot(rpvec, mypp, i)
716                                                 if (store_path(mpp->paths, mypp))
717                                                         goto out;       
718                                 }
719                                 else {
720                                         vector_foreach_slot(rpvec, mypp, i) {
721                                                 if ((j = find_slot(vecs->pathvec,
722                                                                    (void *)mypp)) != -1) {
723                                                         vector_del_slot(vecs->pathvec, j);
724                                                         free_path(mypp);
725                                                 }
726                                         }
727                                         condlog(3, "%s: removed map after removing"
728                                                 " multiple paths", alias);
729                                 }
730                         }
731                         else {
732                                 vector_foreach_slot(rpvec, mypp, i) {
733                                         if ((j = find_slot(vecs->pathvec,
734                                                                    (void *)mypp)) != -1) {
735                                                 vector_del_slot(vecs->pathvec, j);
736                                                 free_path(mypp);
737                                         }
738                                 }
739                                         
740                                 if (setup_map(mpp)) {
741                                         condlog(0, "%s: failed to setup map for"
742                                                 " removal of path %s", mpp->alias, devname);
743                                         free_pathvec(rpvec, KEEP_PATHS);
744                                         goto out;
745                                 }
746                                 /*
747                                  * reload the map
748                                  */
749                                 mpp->action = ACT_RELOAD;
750                                 if (domap(mpp) <= 0) {
751                                         condlog(0, "%s: failed in domap for "
752                                                 "removal of path %s",
753                                                 mpp->alias, devname);
754                                         /*
755                                          * deal with asynchronous uevents :((
756                                          */
757                                         if (!redo) {
758                                                 condlog(3, "%s: uev_remove_path sleep",
759                                                         mpp->alias);
760                                                 sleep(1);
761                                         }
762                                         update_mpp_paths(mpp);
763                                         free_pathvec(rpvec, KEEP_PATHS);
764                                         rpvec = vector_alloc();
765                                         goto rescan;
766                                 }
767                                 /*
768                                  * update our state from kernel
769                                  */
770                                 if (setup_multipath(vecs, mpp)) {
771                                         free_pathvec(rpvec, KEEP_PATHS);
772                                         goto out;
773                                 }
774
775                                 condlog(3, "%s path removed from devmap %s",
776                                         devname, mpp->alias);
777                         }
778                         free_pathvec(rpvec, KEEP_PATHS);
779                 }
780                 else {
781                         char alias[WWID_SIZE];
782
783                         /*
784                          * flush_map will fail if the device is open
785                          */
786                         strncpy(alias, mpp->alias, WWID_SIZE);
787                         if (flush_map(mpp, devname, vecs)) {
788                                 rm_path = 0;
789                         }
790                         else
791                                 condlog(3, "%s: removed map", alias);
792                 }
793         }
794
795         if (rm_path) {
796                 if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
797                         vector_del_slot(vecs->pathvec, i);
798                 free_path(pp);
799         }
800
801         return 0;
802
803 out:
804         remove_map(mpp, vecs, stop_waiter_thread, 1);
805         return 1;
806 }
807
808 int
809 show_paths (char ** r, int * len, struct vectors * vecs)
810 {
811         int i;
812         struct path * pp;
813         char * c;
814         char * reply;
815         int maxlen = INITIAL_REPLY_LEN;
816         int again = 1;
817
818         get_path_layout(vecs->pathvec);
819         reply = MALLOC(maxlen);
820
821         while (again) {
822                 if (!reply)
823                         return 1;
824
825                 c = reply;
826
827                 if (VECTOR_SIZE(vecs->pathvec) > 0)
828                         c += snprint_path_header(c, reply + maxlen - c,
829                                                  PRINT_PATH_CHECKER);
830
831                 vector_foreach_slot(vecs->pathvec, pp, i)
832                         c += snprint_path(c, reply + maxlen - c,
833                                           PRINT_PATH_CHECKER, pp);
834
835                 again = ((c - reply) == (maxlen - 1));
836
837                 if (again)
838                         reply = REALLOC(reply, maxlen *= 2);
839
840         }
841         *r = reply;
842         *len = (int)(c - reply + 1);
843         return 0;
844 }
845
846 int
847 show_maps (char ** r, int *len, struct vectors * vecs)
848 {
849         int i;
850         struct multipath * mpp;
851         char * c;
852         char * reply;
853         int maxlen = INITIAL_REPLY_LEN;
854         int again = 1;
855
856         get_map_layout(vecs->mpvec);
857         reply = MALLOC(maxlen);
858
859         while (again) {
860                 if (!reply)
861                         return 1;
862
863                 c = reply;
864                 if (VECTOR_SIZE(vecs->mpvec) > 0)
865                         c += snprint_map_header(c, reply + maxlen - c,
866                                                 PRINT_MAP_FAILBACK);
867
868                 vector_foreach_slot(vecs->mpvec, mpp, i)
869                         c += snprint_map(c, reply + maxlen - c,
870                                          PRINT_MAP_FAILBACK, mpp);
871
872                 again = ((c - reply) == (maxlen - 1));
873
874                 if (again)
875                         reply = REALLOC(reply, maxlen *= 2);
876         }
877         *r = reply;
878         *len = (int)(c - reply + 1);
879         return 0;
880 }
881
882 int
883 dump_pathvec (char ** r, int * len, struct vectors * vecs)
884 {
885         int i;
886         struct path * pp;
887         char * reply;
888         char * p;
889
890         *len = VECTOR_SIZE(vecs->pathvec) * sizeof(struct path);
891         reply = (char *)MALLOC(*len);
892         *r = reply;
893
894         if (!reply)
895                 return 1;
896
897         p = reply;
898
899         vector_foreach_slot (vecs->pathvec, pp, i) {
900                 memcpy((void *)p, pp, sizeof(struct path));
901                 p += sizeof(struct path);
902         }
903
904         /* return negative to hint caller not to add "ok" to the dump */
905         return -1;
906 }
907
908 static int
909 map_discovery (struct vectors * vecs)
910 {
911         int i;
912         struct multipath * mpp;
913
914         if (dm_get_maps(vecs->mpvec, "multipath"))
915                 return 1;
916
917         vector_foreach_slot (vecs->mpvec, mpp, i) {
918                 if (setup_multipath(vecs, mpp))
919                         return 1;
920                 if (start_waiter_thread(mpp, vecs))
921                         return 1;
922         }
923
924         return 0;
925 }
926
927 int
928 uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
929 {
930         struct vectors * vecs;
931         int r;
932         
933         *reply = NULL;
934         *len = 0;
935         vecs = (struct vectors *)trigger_data;
936
937         pthread_cleanup_push(cleanup_lock, vecs->lock);
938         lock(vecs->lock);
939
940         r = parse_cmd(str, reply, len, vecs);
941
942         if (r > 0) {
943                 *reply = STRDUP("fail\n");
944                 *len = strlen(*reply) + 1;
945                 r = 1;
946         }
947         else if (!r && *len == 0) {
948                 *reply = STRDUP("ok\n");
949                 *len = strlen(*reply) + 1;
950                 r = 0;
951         }
952         /* else if (r < 0) leave *reply alone */
953
954         lock_cleanup_pop(vecs->lock);
955         return r;
956 }
957
958 static int
959 uev_discard(char * devpath)
960 {
961         char a[10], b[10];
962
963         /*
964          * keep only block devices, discard partitions
965          */
966         if (sscanf(devpath, "/block/%10s", a) != 1 ||
967             sscanf(devpath, "/block/%10[^/]/%10s", a, b) == 2) {
968                 condlog(4, "discard event on %s", devpath);
969                 return 1;
970         }
971         return 0;
972 }
973
974 int 
975 uev_trigger (struct uevent * uev, void * trigger_data)
976 {
977         int r = 0;
978         char devname[32];
979         struct vectors * vecs;
980
981         vecs = (struct vectors *)trigger_data;
982
983         if (uev_discard(uev->devpath))
984                 return 1;
985
986         basename(uev->devpath, devname);
987         lock(vecs->lock);
988
989         /*
990          * device map add/remove event
991          */
992         if (!strncmp(devname, "dm-", 3)) {
993                 if (!strncmp(uev->action, "add", 3)) {
994                         r = uev_add_map(devname, vecs);
995                         goto out;
996                 }
997 #if 0
998                 if (!strncmp(uev->action, "remove", 6)) {
999                         r = uev_remove_map(devname, vecs);
1000                         goto out;
1001                 }
1002 #endif
1003                 goto out;
1004         }
1005         
1006         /*
1007          * path add/remove event
1008          */
1009         if (blacklist(conf->blist, devname))
1010                 goto out;
1011
1012         if (!strncmp(uev->action, "add", 3)) {
1013                 r = uev_add_path(devname, vecs);
1014                 goto out;
1015         }
1016         if (!strncmp(uev->action, "remove", 6)) {
1017                 r = uev_remove_path(devname, vecs);
1018                 goto out;
1019         }
1020
1021 out:
1022         unlock(vecs->lock);
1023         return r;
1024 }
1025
1026 static void *
1027 ueventloop (void * ap)
1028 {
1029         if (uevent_listen(&uev_trigger, ap))
1030                 fprintf(stderr, "error starting uevent listener");
1031                 
1032         return NULL;
1033 }
1034
1035 static void *
1036 uxlsnrloop (void * ap)
1037 {
1038         if (load_keys())
1039                 return NULL;
1040         
1041         if (alloc_handlers())
1042                 return NULL;
1043
1044         add_handler(LIST+PATHS, cli_list_paths);
1045         add_handler(LIST+MAPS, cli_list_maps);
1046         add_handler(ADD+PATH, cli_add_path);
1047         add_handler(DEL+PATH, cli_del_path);
1048         add_handler(ADD+MAP, cli_add_map);
1049         add_handler(DEL+MAP, cli_del_map);
1050         add_handler(SWITCH+MAP+GROUP, cli_switch_group);
1051         add_handler(DUMP+PATHVEC, cli_dump_pathvec);
1052         add_handler(RECONFIGURE, cli_reconfigure);
1053         add_handler(SUSPEND+MAP, cli_suspend);
1054         add_handler(RESUME+MAP, cli_resume);
1055         add_handler(REINSTATE+PATH, cli_reinstate);
1056         add_handler(FAIL+PATH, cli_fail);
1057
1058         uxsock_listen(&uxsock_trigger, ap);
1059
1060         return NULL;
1061 }
1062
1063 static int
1064 exit_daemon (int status)
1065 {
1066         if (status != 0)
1067                 fprintf(stderr, "bad exit status. see daemon.log\n");
1068
1069         condlog(3, "unlink pidfile");
1070         unlink(DEFAULT_PIDFILE);
1071
1072         lock(&exit_mutex);
1073         pthread_cond_signal(&exit_cond);
1074         unlock(&exit_mutex);
1075
1076         return status;
1077 }
1078
1079 static void
1080 fail_path (struct path * pp)
1081 {
1082         if (!pp->mpp)
1083                 return;
1084
1085         condlog(2, "checker failed path %s in map %s",
1086                  pp->dev_t, pp->mpp->alias);
1087
1088         dm_fail_path(pp->mpp->alias, pp->dev_t);
1089         update_queue_mode_del_path(pp->mpp);
1090 }
1091
1092 /*
1093  * caller must have locked the path list before calling that function
1094  */
1095 static void
1096 reinstate_path (struct path * pp)
1097 {
1098         if (!pp->mpp)
1099                 return;
1100
1101         if (dm_reinstate_path(pp->mpp->alias, pp->dev_t))
1102                 condlog(0, "%s: reinstate failed", pp->dev_t);
1103         else {
1104                 condlog(2, "%s: reinstated", pp->dev_t);
1105                 update_queue_mode_add_path(pp->mpp);
1106         }
1107 }
1108
1109 static void
1110 enable_group(struct path * pp)
1111 {
1112         struct pathgroup * pgp;
1113
1114         /*
1115          * if path is added through uev_add_path, pgindex can be unset.
1116          * next update_strings() will set it, upon map reload event.
1117          *
1118          * we can safely return here, because upon map reload, all
1119          * PG will be enabled.
1120          */
1121         if (!pp->mpp->pg || !pp->pgindex)
1122                 return;
1123
1124         pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
1125         
1126         if (pgp->status == PGSTATE_DISABLED) {
1127                 condlog(2, "%s: enable group #%i", pp->mpp->alias, pp->pgindex);
1128                 dm_enablegroup(pp->mpp->alias, pp->pgindex);
1129         }
1130 }
1131
1132 static void
1133 mpvec_garbage_collector (struct vectors * vecs)
1134 {
1135         struct multipath * mpp;
1136         int i;
1137
1138         vector_foreach_slot (vecs->mpvec, mpp, i) {
1139                 if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
1140                         condlog(2, "%s: remove dead map", mpp->alias);
1141                         remove_map(mpp, vecs, stop_waiter_thread, 1);
1142                         i--;
1143                 }
1144         }
1145 }
1146
1147 static void
1148 defered_failback_tick (vector mpvec)
1149 {
1150         struct multipath * mpp;
1151         int i;
1152
1153         vector_foreach_slot (mpvec, mpp, i) {
1154                 /*
1155                  * defered failback getting sooner
1156                  */
1157                 if (mpp->pgfailback > 0 && mpp->failback_tick > 0) {
1158                         mpp->failback_tick--;
1159
1160                         if (!mpp->failback_tick && need_switch_pathgroup(mpp, 1))
1161                                 switch_pathgroup(mpp);
1162                 }
1163         }
1164 }
1165
1166 static void
1167 retry_count_tick(vector mpvec)
1168 {
1169         struct multipath *mpp;
1170         int i;
1171
1172         vector_foreach_slot (mpvec, mpp, i) {
1173                 if (mpp->retry_tick) {
1174                         condlog(4, "%s: Retrying.. No active path", mpp->alias);
1175                         if(--mpp->retry_tick == 0) {
1176                                 dm_queue_if_no_path(mpp->alias, 0);
1177                                 condlog(2, "%s: Disable queueing", mpp->alias);
1178                         }
1179                 }
1180         }
1181 }
1182
1183 static void *
1184 checkerloop (void *ap)
1185 {
1186         struct vectors *vecs;
1187         struct path *pp;
1188         int i, count = 0;
1189         int newstate;
1190         char checker_msg[MAX_CHECKER_MSG_SIZE];
1191
1192         mlockall(MCL_CURRENT | MCL_FUTURE);
1193
1194         memset(checker_msg, 0, MAX_CHECKER_MSG_SIZE);
1195         vecs = (struct vectors *)ap;
1196
1197         condlog(2, "path checkers start up");
1198
1199         /*
1200          * init the path check interval
1201          */
1202         vector_foreach_slot (vecs->pathvec, pp, i) {
1203                 pp->checkint = conf->checkint;
1204         }
1205
1206         while (1) {
1207                 pthread_cleanup_push(cleanup_lock, vecs->lock);
1208                 lock(vecs->lock);
1209                 condlog(4, "tick");
1210
1211                 vector_foreach_slot (vecs->pathvec, pp, i) {
1212                         if (!pp->mpp)
1213                                 continue;
1214
1215                         if (pp->tick && --pp->tick)
1216                                 continue; /* don't check this path yet */
1217
1218                         /*
1219                          * provision a next check soonest,
1220                          * in case we exit abnormaly from here
1221                          */
1222                         pp->tick = conf->checkint;
1223                         
1224                         if (!pp->checkfn) {
1225                                 pathinfo(pp, conf->hwtable, DI_SYSFS);
1226                                 select_checkfn(pp);
1227                         }
1228
1229                         if (!pp->checkfn) {
1230                                 condlog(0, "%s: checkfn is void", pp->dev);
1231                                 continue;
1232                         }
1233                         newstate = pp->checkfn(pp->fd, checker_msg,
1234                                                &pp->checker_context);
1235                         
1236                         if (newstate < 0) {
1237                                 condlog(2, "%s: unusable path", pp->dev);
1238                                 pathinfo(pp, conf->hwtable, 0);
1239                                 continue;
1240                         }
1241
1242                         if (newstate != pp->state) {
1243                                 pp->state = newstate;
1244                                 LOG_MSG(1, checker_msg);
1245
1246                                 /*
1247                                  * upon state change, reset the checkint
1248                                  * to the shortest delay
1249                                  */
1250                                 pp->checkint = conf->checkint;
1251
1252                                 if (newstate == PATH_DOWN ||
1253                                     newstate == PATH_SHAKY ||
1254                                     update_multipath_strings(pp->mpp,
1255                                                              vecs->pathvec)) {
1256                                         /*
1257                                          * proactively fail path in the DM
1258                                          */
1259                                         fail_path(pp);
1260
1261                                         /*
1262                                          * cancel scheduled failback
1263                                          */
1264                                         pp->mpp->failback_tick = 0;
1265
1266                                         continue;
1267                                 }
1268
1269                                 /*
1270                                  * reinstate this path
1271                                  */
1272                                 reinstate_path(pp);
1273
1274                                 /*
1275                                  * schedule [defered] failback
1276                                  */
1277                                 if (pp->mpp->pgfailback > 0)
1278                                         pp->mpp->failback_tick =
1279                                                 pp->mpp->pgfailback + 1;
1280                                 else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE &&
1281                                     need_switch_pathgroup(pp->mpp, 1))
1282                                         switch_pathgroup(pp->mpp);
1283
1284                                 /*
1285                                  * if at least one path is up in a group, and
1286                                  * the group is disabled, re-enable it
1287                                  */
1288                                 if (newstate == PATH_UP)
1289                                         enable_group(pp);
1290                         }
1291                         else if (newstate == PATH_UP || newstate == PATH_GHOST) {
1292                                 LOG_MSG(4, checker_msg);
1293                                 /*
1294                                  * double the next check delay.
1295                                  * max at conf->max_checkint
1296                                  */
1297                                 if (pp->checkint < (conf->max_checkint / 2))
1298                                         pp->checkint = 2 * pp->checkint;
1299                                 else
1300                                         pp->checkint = conf->max_checkint;
1301
1302                                 pp->tick = pp->checkint;
1303                                 condlog(4, "%s: delay next check %is",
1304                                                 pp->dev_t, pp->tick);
1305
1306                         }
1307                         pp->state = newstate;
1308
1309                         /*
1310                          * path prio refreshing
1311                          */
1312                         condlog(4, "path prio refresh");
1313                         pathinfo(pp, conf->hwtable, DI_PRIO);
1314
1315                         if (need_switch_pathgroup(pp->mpp, 0)) {
1316                                 if (pp->mpp->pgfailback > 0)
1317                                         pp->mpp->failback_tick =
1318                                                 pp->mpp->pgfailback + 1;
1319                                 else if (pp->mpp->pgfailback ==
1320                                                 -FAILBACK_IMMEDIATE)
1321                                         switch_pathgroup(pp->mpp);
1322                         }
1323                 }
1324                 defered_failback_tick(vecs->mpvec);
1325                 retry_count_tick(vecs->mpvec);
1326
1327                 if (count)
1328                         count--;
1329                 else {
1330                         condlog(4, "map garbage collection");
1331                         mpvec_garbage_collector(vecs);
1332                         count = MAPGCINT;
1333                 }
1334                 
1335                 lock_cleanup_pop(vecs->lock);
1336                 sleep(1);
1337         }
1338         return NULL;
1339 }
1340
1341 int
1342 configure (struct vectors * vecs, int start_waiters)
1343 {
1344         struct multipath * mpp;
1345         struct path * pp;
1346         vector mpvec;
1347         int i;
1348
1349         if (!(vecs->pathvec = vector_alloc()))
1350                 return 1;
1351         
1352         if (!(vecs->mpvec = vector_alloc()))
1353                 return 1;
1354         
1355         if (!(mpvec = vector_alloc()))
1356                 return 1;
1357
1358         /*
1359          * probe for current path (from sysfs) and map (from dm) sets
1360          */
1361         path_discovery(vecs->pathvec, conf, DI_ALL);
1362
1363         vector_foreach_slot (vecs->pathvec, pp, i)
1364                 pp->checkint = conf->checkint;
1365
1366         if (map_discovery(vecs))
1367                 return 1;
1368
1369         /*
1370          * create new set of maps & push changed ones into dm
1371          */
1372         if (coalesce_paths(vecs, mpvec))
1373                 return 1;
1374
1375         /*
1376          * may need to remove some maps which are no longer relevant
1377          * e.g., due to blacklist changes in conf file
1378          */
1379         if (coalesce_maps(vecs, mpvec))
1380                 return 1;
1381
1382         if (conf->verbosity > 2)
1383                 vector_foreach_slot(mpvec, mpp, i)
1384                         print_map(mpp);
1385
1386         /*
1387          * purge dm of old maps
1388          */
1389         remove_maps(vecs, NULL);
1390
1391         /*
1392          * save new set of maps formed by considering current path state
1393          */
1394         vecs->mpvec = mpvec;
1395
1396         /*
1397          * start dm event waiter threads for these new maps
1398          */
1399         vector_foreach_slot(vecs->mpvec, mpp, i) {
1400                 if (setup_multipath(vecs, mpp))
1401                         return 1;
1402                 if (start_waiters)
1403                         if (start_waiter_thread(mpp, vecs))
1404                                 return 1;
1405         }
1406         return 0;
1407 }
1408
1409 int
1410 reconfigure (struct vectors * vecs)
1411 {
1412         struct config * old = conf;
1413
1414         condlog(0, "reconfigure");
1415
1416         /*
1417          * free old map and path vectors ... they use old conf state
1418          */
1419         if (VECTOR_SIZE(vecs->mpvec))
1420                 remove_maps(vecs, stop_waiter_thread);
1421
1422         if (VECTOR_SIZE(vecs->pathvec))
1423                 free_pathvec(vecs->pathvec, FREE_PATHS);
1424
1425         conf = NULL;
1426
1427         if (load_config(DEFAULT_CONFIGFILE))
1428                 return 1;
1429
1430         conf->verbosity = old->verbosity;
1431
1432         if (!conf->checkint) {
1433                 conf->checkint = CHECKINT;
1434                 conf->max_checkint = MAX_CHECKINT;
1435         }
1436         configure(vecs, 1);
1437         free_config(old);
1438         return 0;
1439 }
1440
1441 static struct vectors *
1442 init_vecs (void)
1443 {
1444         struct vectors * vecs;
1445
1446         vecs = (struct vectors *)MALLOC(sizeof(struct vectors));
1447
1448         if (!vecs)
1449                 return NULL;
1450
1451         vecs->lock = 
1452                 (pthread_mutex_t *)MALLOC(sizeof(pthread_mutex_t));
1453
1454         if (!vecs->lock)
1455                 goto out;
1456
1457         vecs->pathvec = vector_alloc();
1458
1459         if (!vecs->pathvec)
1460                 goto out1;
1461                 
1462         vecs->mpvec = vector_alloc();
1463
1464         if (!vecs->mpvec)
1465                 goto out2;
1466         
1467         pthread_mutex_init(vecs->lock, NULL);
1468
1469         return vecs;
1470
1471 out2:
1472         vector_free(vecs->pathvec);
1473 out1:
1474         FREE(vecs->lock);
1475 out:
1476         FREE(vecs);
1477         condlog(0, "failed to init paths");
1478         return NULL;
1479 }
1480
1481 static void *
1482 signal_set(int signo, void (*func) (int))
1483 {
1484         int r;
1485         struct sigaction sig;
1486         struct sigaction osig;
1487
1488         sig.sa_handler = func;
1489         sigemptyset(&sig.sa_mask);
1490         sig.sa_flags = 0;
1491
1492         r = sigaction(signo, &sig, &osig);
1493
1494         if (r < 0)
1495                 return (SIG_ERR);
1496         else
1497                 return (osig.sa_handler);
1498 }
1499
1500 static void
1501 sighup (int sig)
1502 {
1503         condlog(3, "SIGHUP received");
1504
1505         lock(gvecs->lock);
1506         reconfigure(gvecs);
1507         unlock(gvecs->lock);
1508
1509 #ifdef _DEBUG_
1510         dbg_free_final(NULL);
1511 #endif
1512 }
1513
1514 static void
1515 sigend (int sig)
1516 {
1517         exit_daemon(0);
1518 }
1519
1520 static void
1521 sigusr1 (int sig)
1522 {
1523         condlog(3, "SIGUSR1 received");
1524 }
1525
1526 static void
1527 signal_init(void)
1528 {
1529         signal_set(SIGHUP, sighup);
1530         signal_set(SIGUSR1, sigusr1);
1531         signal_set(SIGINT, sigend);
1532         signal_set(SIGTERM, sigend);
1533         signal_set(SIGKILL, sigend);
1534 }
1535
1536 static void
1537 setscheduler (void)
1538 {
1539         int res;
1540         static struct sched_param sched_param = {
1541                 sched_priority: 99
1542         };
1543
1544         res = sched_setscheduler (0, SCHED_RR, &sched_param);
1545
1546         if (res == -1)
1547                 condlog(LOG_WARNING, "Could not set SCHED_RR at priority 99");
1548         return;
1549 }
1550
1551 static void
1552 set_oom_adj (int val)
1553 {
1554         FILE *fp;
1555
1556         fp = fopen("/proc/self/oom_adj", "w");
1557
1558         if (!fp)
1559                 return;
1560
1561         fprintf(fp, "%i", val);
1562         fclose(fp);
1563 }
1564         
1565 static int
1566 child (void * param)
1567 {
1568         pthread_t check_thr, uevent_thr, uxlsnr_thr;
1569         pthread_attr_t attr;
1570         struct vectors * vecs;
1571
1572         mlockall(MCL_CURRENT | MCL_FUTURE);
1573
1574         if (logsink)
1575                 log_thread_start();
1576
1577         condlog(2, "--------start up--------");
1578         condlog(2, "read " DEFAULT_CONFIGFILE);
1579
1580         if (load_config(DEFAULT_CONFIGFILE))
1581                 exit(1);
1582
1583         setlogmask(LOG_UPTO(conf->verbosity + 3));
1584
1585         /*
1586          * fill the voids left in the config file
1587          */
1588         if (!conf->checkint) {
1589                 conf->checkint = CHECKINT;
1590                 conf->max_checkint = MAX_CHECKINT;
1591         }
1592
1593         if (pidfile_create(DEFAULT_PIDFILE, getpid())) {
1594                 if (logsink)
1595                         log_thread_stop();
1596
1597                 exit(1);
1598         }
1599         signal_init();
1600         setscheduler();
1601         set_oom_adj(-17);
1602         vecs = gvecs = init_vecs();
1603
1604         if (!vecs)
1605                 exit(1);
1606
1607         if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
1608                 condlog(0, "can not find sysfs mount point");
1609                 exit(1);
1610         }
1611
1612         /*
1613          * fetch and configure both paths and multipaths
1614          */
1615         if (configure(vecs, 1)) {
1616                 condlog(0, "failure during configuration");
1617                 exit(1);
1618         }
1619
1620         /*
1621          * start threads
1622          */
1623         pthread_attr_init(&attr);
1624         pthread_attr_setstacksize(&attr, 64 * 1024);
1625         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1626         
1627         pthread_create(&check_thr, &attr, checkerloop, vecs);
1628         pthread_create(&uevent_thr, &attr, ueventloop, vecs);
1629         pthread_create(&uxlsnr_thr, &attr, uxlsnrloop, vecs);
1630
1631         pthread_cond_wait(&exit_cond, &exit_mutex);
1632
1633         /*
1634          * exit path
1635          */
1636         lock(vecs->lock);
1637         remove_maps(vecs, stop_waiter_thread);
1638         free_pathvec(vecs->pathvec, FREE_PATHS);
1639
1640         pthread_cancel(check_thr);
1641         pthread_cancel(uevent_thr);
1642         pthread_cancel(uxlsnr_thr);
1643
1644         free_keys(keys);
1645         keys = NULL;
1646         free_handlers(handlers);
1647         handlers = NULL;
1648         free_polls();
1649
1650         unlock(vecs->lock);
1651         pthread_mutex_destroy(vecs->lock);
1652         FREE(vecs->lock);
1653         vecs->lock = NULL;
1654         FREE(vecs);
1655         vecs = NULL;
1656         free_config(conf);
1657         conf = NULL;
1658
1659         condlog(2, "--------shut down-------");
1660         
1661         if (logsink)
1662                 log_thread_stop();
1663
1664         dm_lib_release();
1665         dm_lib_exit();
1666
1667 #ifdef _DEBUG_
1668         dbg_free_final(NULL);
1669 #endif
1670
1671         exit(0);
1672 }
1673
1674 static int
1675 daemonize(void)
1676 {
1677         int pid;
1678         int in_fd, out_fd;
1679
1680         if( (pid = fork()) < 0){
1681                 fprintf(stderr, "Failed first fork : %s\n", strerror(errno));
1682                 return -1;
1683         }
1684         else if (pid != 0)
1685                 return pid;
1686
1687         setsid();
1688
1689         if ( (pid = fork()) < 0)
1690                 fprintf(stderr, "Failed second fork : %s\n", strerror(errno));
1691         else if (pid != 0)
1692                 _exit(0);
1693
1694         in_fd = open("/dev/null", O_RDONLY);
1695         if (in_fd < 0){
1696                 fprintf(stderr, "cannot open /dev/null for input : %s\n",
1697                         strerror(errno));
1698                 _exit(0);
1699         }
1700         out_fd = open("/dev/console", O_WRONLY);
1701         if (out_fd < 0){
1702                 fprintf(stderr, "cannot open /dev/console for output : %s\n",
1703                         strerror(errno));
1704                 _exit(0);
1705         }
1706
1707         close(STDIN_FILENO);
1708         dup(in_fd);
1709         close(STDOUT_FILENO);
1710         dup(out_fd);
1711         close(STDERR_FILENO);
1712         dup(out_fd);
1713
1714         close(in_fd);
1715         close(out_fd);
1716         chdir("/");
1717         umask(0);
1718         return 0;
1719 }
1720
1721 int
1722 main (int argc, char *argv[])
1723 {
1724         extern char *optarg;
1725         extern int optind;
1726         int arg;
1727         int err;
1728         
1729         logsink = 1;
1730
1731         if (getuid() != 0) {
1732                 fprintf(stderr, "need to be root\n");
1733                 exit(1);
1734         }
1735
1736         /* make sure we don't lock any path */
1737         chdir("/");
1738         umask(umask(077) | 022);
1739
1740         conf = alloc_config();
1741
1742         if (!conf)
1743                 exit(1);
1744
1745         while ((arg = getopt(argc, argv, ":dv:k::")) != EOF ) {
1746         switch(arg) {
1747                 case 'd':
1748                         logsink = 0;
1749                         //debug=1; /* ### comment me out ### */
1750                         break;
1751                 case 'v':
1752                         if (sizeof(optarg) > sizeof(char *) ||
1753                             !isdigit(optarg[0]))
1754                                 exit(1);
1755
1756                         conf->verbosity = atoi(optarg);
1757                         break;
1758                 case 'k':
1759                         uxclnt(optarg);
1760                         exit(0);
1761                 default:
1762                         ;
1763                 }
1764         }
1765
1766         if (!logsink)
1767                 err = 0;
1768         else
1769                 err = daemonize();
1770         
1771         if (err < 0)
1772                 /* error */
1773                 exit(1);
1774         else if (err > 0)
1775                 /* parent dies */
1776                 exit(0);
1777         else
1778                 /* child lives */
1779                 return (child(NULL));
1780 }
1781