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