[libmultipath] comestic changes
[platform/upstream/multipath-tools.git] / multipathd / main.c
1 #include <unistd.h>
2 #include <sys/stat.h>
3 #include <libdevmapper.h>
4 #include <wait.h>
5 #include <sys/mman.h>
6
7 /*
8  * libsysfs
9  */
10 #include <sysfs/libsysfs.h>
11 #include <sysfs/dlist.h>
12
13 /*
14  * libcheckers
15  */
16 #include <checkers.h>
17 #include <path_state.h>
18
19 /*
20  * libmultipath
21  */
22 #include <parser.h>
23 #include <vector.h>
24 #include <memory.h>
25 #include <config.h>
26 #include <callout.h>
27 #include <util.h>
28 #include <blacklist.h>
29 #include <hwtable.h>
30 #include <defaults.h>
31 #include <structs.h>
32 #include <dmparser.h>
33 #include <devmapper.h>
34 #include <dict.h>
35 #include <discovery.h>
36 #include <debug.h>
37 #include <propsel.h>
38 #include <uevent.h>
39 #include <switchgroup.h>
40 #include <path_state.h>
41 #include <print.h>
42
43 #include "main.h"
44 #include "pidfile.h"
45 #include "uxlsnr.h"
46 #include "uxclnt.h"
47 #include "cli.h"
48 #include "cli_handlers.h"
49
50 #define FILE_NAME_SIZE 256
51 #define CMDSIZE 160
52
53 #define LOG_MSG(a,b) \
54         if (strlen(b)) { \
55                 condlog(a, "%s: %s", pp->dev_t, b); \
56                 memset(b, 0, MAX_CHECKER_MSG_SIZE); \
57         }
58
59 #ifdef LCKDBG
60 #define lock(a) \
61         fprintf(stderr, "%s:%s(%i) lock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
62         pthread_mutex_lock(a)
63 #define unlock(a) \
64         fprintf(stderr, "%s:%s(%i) unlock %p\n", __FILE__, __FUNCTION__, __LINE__, a); \
65         pthread_mutex_unlock(a)
66 #else
67 #define lock(a) pthread_mutex_lock(a)
68 #define unlock(a) pthread_mutex_unlock(a)
69 #endif
70
71 pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
72 pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
73
74 /*
75  * structs
76  */
77 struct event_thread {
78         struct dm_task *dmt;
79         pthread_t thread;
80         int event_nr;
81         char mapname[WWID_SIZE];
82         struct paths *allpaths;
83 };
84
85 static struct event_thread *
86 alloc_waiter (void)
87 {
88
89         struct event_thread * wp;
90
91         wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
92
93         return wp;
94 }
95
96 static void
97 cleanup_lock (void * data)
98 {
99         unlock((pthread_mutex_t *)data);
100 }
101
102 static void
103 set_paths_owner (struct paths * allpaths, struct multipath * mpp)
104 {
105         int i;
106         struct path * pp;
107
108         if (!mpp)
109                 return;
110
111         vector_foreach_slot (allpaths->pathvec, pp, i) {
112                 if (!strncmp(mpp->wwid, pp->wwid, WWID_SIZE)) {
113                         condlog(4, "%s ownership set", pp->dev_t);
114                         pp->mpp = mpp;
115                 }
116         }
117 }
118
119 static void
120 unset_paths_owner (struct paths * allpaths, struct multipath * mpp)
121 {
122         int i;
123         struct path * pp;
124
125         vector_foreach_slot (allpaths->pathvec, pp, i) {
126                 if (pp->mpp == mpp) {
127                         condlog(4, "%s is orphaned", pp->dev_t);
128                         pp->mpp = NULL;
129                 }
130         }
131 }
132
133 static int
134 update_multipath_table (struct multipath *mpp, vector pathvec)
135 {
136         if (!mpp)
137                 return 1;
138
139         if (dm_get_map(mpp->alias, &mpp->size, mpp->params))
140                 return 1;
141
142         if (disassemble_map(pathvec, mpp->params, mpp))
143                 return 1;
144
145         return 0;
146 }
147
148 static int
149 update_multipath_status (struct multipath *mpp)
150 {
151         if (!mpp)
152                 return 1;
153
154         if(dm_get_status(mpp->alias, mpp->status))
155                 return 1;
156
157         if (disassemble_status(mpp->status, mpp))
158                 return 1;
159
160         return 0;
161 }
162
163 static int
164 update_multipath_strings (struct multipath *mpp, vector pathvec)
165 {
166         if (mpp->selector) {
167                 FREE(mpp->selector);
168                 mpp->selector = NULL;
169         }
170
171         if (mpp->features) {
172                 FREE(mpp->features);
173                 mpp->features = NULL;
174         }
175
176         if (mpp->hwhandler) {
177                 FREE(mpp->hwhandler);
178                 mpp->hwhandler = NULL;
179         }
180
181         free_pgvec(mpp->pg, KEEP_PATHS);
182         mpp->pg = NULL;
183
184         if (update_multipath_table(mpp, pathvec))
185                 return 1;
186
187         if (update_multipath_status(mpp))
188                 return 1;
189
190         return 0;
191 }
192
193 static void
194 set_multipath_wwid (struct multipath * mpp)
195 {
196         char * wwid;
197
198         wwid = get_mpe_wwid(mpp->alias);
199
200         if (wwid) {
201                 strncpy(mpp->wwid, wwid, WWID_SIZE);
202                 wwid = NULL;
203         } else
204                 strncpy(mpp->wwid, mpp->alias, WWID_SIZE);
205 }
206
207 static int
208 setup_multipath (struct paths * allpaths, struct multipath * mpp)
209 {
210         int i;
211
212         set_multipath_wwid(mpp);
213         mpp->mpe = find_mpe(mpp->wwid);
214         condlog(4, "discovered map %s", mpp->alias);
215
216         if (update_multipath_strings(mpp, allpaths->pathvec))
217                 goto out;
218
219         set_paths_owner(allpaths, mpp);
220         select_pgfailback(mpp);
221
222         return 0;
223 out:
224         /*
225          * purge the multipath vector
226          */
227         if ((i = find_slot(allpaths->mpvec, (void *)mpp)) != -1)
228                 vector_del_slot(allpaths->mpvec, i);
229
230         free_multipath(mpp, KEEP_PATHS);
231         condlog(0, "failed to setup multipath");
232         return 1;
233 }
234
235 static void
236 switch_pathgroup (struct multipath * mpp)
237 {
238         struct pathgroup * pgp;
239         struct path * pp;
240         int i, j;
241         
242         if (!mpp || mpp->pgfailback == -FAILBACK_MANUAL)
243                 return;
244         /*
245          * Refresh path priority values
246          */
247         vector_foreach_slot (mpp->pg, pgp, i)
248                 vector_foreach_slot (pgp->paths, pp, j)
249                         pathinfo(pp, conf->hwtable, DI_PRIO);
250
251         select_path_group(mpp); /* sets mpp->nextpg */
252         pgp = VECTOR_SLOT(mpp->pg, mpp->nextpg - 1);
253         
254         if (pgp && pgp->status != PGSTATE_ACTIVE) {
255                 dm_switchgroup(mpp->alias, mpp->nextpg);
256                 condlog(2, "%s: switch to path group #%i",
257                          mpp->alias, mpp->nextpg);
258         }
259 }
260
261 static int
262 update_multipath (struct paths *allpaths, char *mapname)
263 {
264         struct multipath *mpp;
265         struct pathgroup  *pgp;
266         struct path *pp;
267         int i, j;
268         int r = 1;
269
270         mpp = find_mp(allpaths->mpvec, mapname);
271
272         if (!mpp)
273                 goto out;
274
275         free_pgvec(mpp->pg, KEEP_PATHS);
276         mpp->pg = NULL;
277
278         if (setup_multipath(allpaths, mpp))
279                 goto out; /* mpp freed in setup_multipath */
280
281         /*
282          * compare checkers states with DM states
283          */
284         vector_foreach_slot (mpp->pg, pgp, i) {
285                 vector_foreach_slot (pgp->paths, pp, j) {
286                         if (pp->dmstate != PSTATE_FAILED)
287                                 continue;
288
289                         if (pp->state != PATH_DOWN) {
290                                 condlog(2, "%s: mark as failed", pp->dev_t);
291                                 pp->state = PATH_DOWN;
292
293                                 /*
294                                  * if opportune,
295                                  * schedule the next check earlier
296                                  */
297                                 if (pp->tick > conf->checkint)
298                                         pp->tick = conf->checkint;
299                         }
300                 }
301         }
302         r = 0;
303 out:
304         if (r)
305                 condlog(0, "failed to update multipath");
306
307         return r;
308 }
309
310 static void
311 free_waiter (void * data)
312 {
313         struct event_thread * wp = (struct event_thread *)data;
314
315         if (wp->dmt)
316                 dm_task_destroy(wp->dmt);
317         FREE(wp);
318 }
319
320 static sigset_t unblock_sighup(void)
321 {
322         sigset_t set, old;
323
324         sigemptyset(&set);
325         sigaddset(&set, SIGHUP);
326         pthread_sigmask(SIG_UNBLOCK, &set, &old);
327         return old;
328 }
329
330 /*
331  * returns the reschedule delay
332  * negative means *stop*
333  */
334 static int
335 waiteventloop (struct event_thread * waiter)
336 {
337         sigset_t set;
338         int event_nr;
339         int r;
340
341         if (!waiter->event_nr)
342                 waiter->event_nr = dm_geteventnr(waiter->mapname);
343
344         if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT)))
345                 return 1;
346
347         if (!dm_task_set_name(waiter->dmt, waiter->mapname))
348                 return 1;
349
350         if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
351                                                       waiter->event_nr))
352                 return 1;
353
354         dm_task_no_open_count(waiter->dmt);
355
356         set = unblock_sighup();
357         dm_task_run(waiter->dmt);
358         pthread_sigmask(SIG_SETMASK, &set, NULL);
359         pthread_testcancel();
360         dm_task_destroy(waiter->dmt);
361         waiter->dmt = NULL;
362
363         waiter->event_nr++;
364
365         /*
366          * upon event ...
367          */
368         while (1) {
369                 condlog(2, "%s: devmap event #%i",
370                                 waiter->mapname, waiter->event_nr);
371
372                 /*
373                  * event might be :
374                  *
375                  * 1) a table reload, which means our mpp structure is
376                  *    obsolete : refresh it through update_multipath()
377                  * 2) a path failed by DM : mark as such through
378                  *    update_multipath()
379                  * 3) map has gone away : stop the thread.
380                  * 4) a path reinstate : nothing to do
381                  * 5) a switch group : nothing to do
382                  */
383                 pthread_cleanup_push(cleanup_lock, waiter->allpaths->lock);
384                 lock(waiter->allpaths->lock);
385
386                 r = update_multipath(waiter->allpaths, waiter->mapname);
387                 pthread_cleanup_pop(1);
388
389                 if (r)
390                         return -1; /* stop the thread */
391
392                 event_nr = dm_geteventnr(waiter->mapname);
393
394                 if (waiter->event_nr == event_nr)
395                         return 1; /* upon problem reschedule 1s later */
396
397                 waiter->event_nr = event_nr;
398         }
399         return -1; /* never reach there */
400 }
401
402 static void *
403 waitevent (void * et)
404 {
405         int r;
406         struct event_thread *waiter;
407
408         mlockall(MCL_CURRENT | MCL_FUTURE);
409
410         waiter = (struct event_thread *)et;
411         pthread_cleanup_push(free_waiter, et);
412
413         while (1) {
414                 r = waiteventloop(waiter);
415
416                 if (r < 0)
417                         break;
418
419                 pthread_testcancel();
420                 sleep(r);
421                 pthread_testcancel();
422         }
423
424         pthread_cleanup_pop(1);
425         return NULL;
426 }
427
428 static int
429 stop_waiter_thread (struct multipath * mpp, struct paths * allpaths)
430 {
431         struct event_thread * wp = (struct event_thread *)mpp->waiter;
432         pthread_t thread = wp->thread;
433         int r;
434
435         if (!wp)
436                 return 1;
437
438         condlog(2, "%s: reap event checker", wp->mapname);
439
440         if ((r = pthread_cancel(thread)))
441                 return r;
442
443         pthread_kill(thread, SIGHUP);
444         return 0;
445 }
446
447 static int
448 start_waiter_thread (struct multipath * mpp, struct paths * allpaths)
449 {
450         pthread_attr_t attr;
451         struct event_thread * wp;
452
453         if (!mpp)
454                 return 0;
455
456         if (pthread_attr_init(&attr))
457                 goto out;
458
459         pthread_attr_setstacksize(&attr, 32 * 1024);
460         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
461
462         wp = alloc_waiter();
463
464         if (!wp)
465                 goto out;
466
467         mpp->waiter = (void *)wp;
468         strncpy(wp->mapname, mpp->alias, WWID_SIZE);
469         wp->allpaths = allpaths;
470
471         if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
472                 condlog(0, "%s: cannot create event checker", wp->mapname);
473                 goto out1;
474         }
475         condlog(2, "%s: event checker started", wp->mapname);
476
477         return 0;
478 out1:
479         free_waiter(wp);
480         mpp->waiter = NULL;
481 out:
482         condlog(0, "failed to start waiter thread");
483         return 1;
484 }
485
486 static void
487 remove_map (struct multipath * mpp, struct paths * allpaths)
488 {
489         int i;
490
491         /*
492          * stop the DM event waiter thread
493          */
494         if (stop_waiter_thread(mpp, allpaths)) {
495                 condlog(0, "%s: error canceling waiter thread", mpp->alias);
496                 /*
497                  * warrior mode
498                  */
499                 free_waiter(mpp->waiter);
500         }
501
502         /*
503          * clear references to this map
504          */
505         unset_paths_owner(allpaths, mpp);
506
507         /*
508          * purge the multipath vector
509          */
510         i = find_slot(allpaths->mpvec, (void *)mpp);
511         vector_del_slot(allpaths->mpvec, i);
512
513         /*
514          * final free
515          */
516         free_multipath(mpp, KEEP_PATHS);
517         mpp = NULL;
518 }
519
520 static void
521 remove_maps (struct paths * allpaths)
522 {
523         int i;
524         struct multipath * mpp;
525
526         vector_foreach_slot (allpaths->mpvec, mpp, i)
527                 remove_map(mpp, allpaths);
528
529         vector_free(allpaths->mpvec);
530         allpaths->mpvec = NULL;
531 }
532
533 int
534 uev_add_map (char * devname, struct paths * allpaths)
535 {
536         int major, minor, i;
537         char dev_t[BLK_DEV_SIZE];
538         char * alias;
539         struct multipath * mpp;
540
541         if (sysfs_get_dev(sysfs_path, devname, dev_t, BLK_DEV_SIZE))
542                 return 1;
543
544         if (sscanf(dev_t, "%d:%d", &major, &minor) != 2)
545                 return 1;
546
547         alias = dm_mapname(major, minor);
548                 
549         if (!alias)
550                 return 1;
551         
552         if (!dm_type(alias, DEFAULT_TARGET)) {
553                 condlog(4, "%s: not a multipath map", alias);
554                 FREE(alias);
555                 return 0;
556         }
557
558         mpp = find_mp(allpaths->mpvec, alias);
559
560         if (mpp) {
561                 /*
562                  * this should not happen,
563                  * we missed a remove map event (not sent ?)
564                  */
565                 condlog(2, "%s: already registered", alias);
566                 remove_map(mpp, allpaths);
567         }
568
569         /*
570          * now we can allocate
571          */
572         mpp = alloc_multipath();
573
574         if (!mpp)
575                 return 1;
576
577         mpp->minor = minor;
578         mpp->alias = alias;
579
580         if (setup_multipath(allpaths, mpp))
581                 return 1; /* mpp freed in setup_multipath */
582
583         if (!vector_alloc_slot(allpaths->mpvec))
584                 goto out;
585
586         vector_set_slot(allpaths->mpvec, mpp);
587         set_paths_owner(allpaths, mpp);
588
589         if (start_waiter_thread(mpp, allpaths))
590                 goto out;
591
592         return 0;
593 out:
594         condlog(2, "%s: add devmap failed", mpp->alias);
595         /*
596          * purge the multipath vector
597          */
598         if ((i = find_slot(allpaths->mpvec, (void *)mpp)) != -1)
599                 vector_del_slot(allpaths->mpvec, i);
600
601         free_multipath(mpp, KEEP_PATHS);
602         return 1;
603 }
604
605 int
606 uev_remove_map (char * devname, struct paths * allpaths)
607 {
608         int minor;
609         struct multipath * mpp;
610
611         if (sscanf(devname, "dm-%d", &minor) != 1)
612                 return 1;
613
614         mpp = find_mp_by_minor(allpaths->mpvec, minor);
615
616         if (!mpp) {
617                 condlog(3, "%s: devmap not registered, can't remove",
618                         devname);
619                 return 1;
620         }
621
622         condlog(2, "remove %s devmap", mpp->alias);
623         remove_map(mpp, allpaths);
624
625         return 0;
626 }
627
628 int
629 uev_add_path (char * devname, struct paths * allpaths)
630 {
631         struct path * pp;
632
633         pp = find_path_by_dev(allpaths->pathvec, devname);
634
635         if (pp) {
636                 condlog(3, "%s: already in pathvec");
637                 return 1;
638         }
639         pp = store_pathinfo(allpaths->pathvec, conf->hwtable,
640                        devname, DI_SYSFS | DI_WWID);
641
642         if (!pp) {
643                 condlog(0, "%s: failed to store path info", devname);
644                 return 1;
645         }
646
647         condlog(2, "%s: path checker registered", devname);
648         pp->mpp = find_mp_by_wwid(allpaths->mpvec, pp->wwid);
649
650         if (pp->mpp)
651                 condlog(4, "%s: ownership set to %s",
652                                 pp->dev_t, pp->mpp->alias);
653         else
654                 condlog(4, "%s: orphaned", pp->dev_t);
655
656         return 0;
657 }
658
659 int
660 uev_remove_path (char * devname, struct paths * allpaths)
661 {
662         int i;
663         struct path * pp;
664
665         pp = find_path_by_dev(allpaths->pathvec, devname);
666
667         if (!pp) {
668                 condlog(3, "%s: not in pathvec");
669                 return 1;
670         }
671         condlog(2, "remove %s path checker", devname);
672         i = find_slot(allpaths->pathvec, (void *)pp);
673         vector_del_slot(allpaths->pathvec, i);
674         free_path(pp);
675
676         return 0;
677 }
678
679 int
680 show_paths (char ** r, int * len, struct paths * allpaths)
681 {
682         int i, j, k;
683         struct path * pp;
684         char * c;
685         char * reply;
686         struct path_layout pl;
687
688         get_path_layout(&pl, allpaths->pathvec);
689         reply = MALLOC(MAX_REPLY_LEN);
690
691         if (!reply)
692                 return 1;
693
694         c = reply;
695         c += sprintf(c, "\n");
696
697         vector_foreach_slot(allpaths->pathvec, pp, i) {
698                 c += snprint_path(c, reply + MAX_REPLY_LEN - c, pp, &pl);
699
700                 if (!pp->mpp) {
701                         c += sprintf(c, "[orphan]\n");
702                         continue;
703                 }
704
705                 c += sprintf(c, " ");
706                 j = pp->tick;
707                 k = pp->checkint - pp->tick;
708
709                 while (j-- > 0)
710                         c += sprintf(c, "X");
711
712
713                 while (k-- > 0)
714                         c += sprintf(c, ".");
715
716                 c += sprintf(c, " %i/%i\n", pp->tick, pp->checkint);
717         }
718
719         *r = reply;
720         *len = (int)(c - reply + 1);
721         return 0;
722 }
723
724 int
725 show_maps (char ** r, int *len, struct paths * allpaths)
726 {
727         int i, j, k;
728         struct multipath * mpp;
729         char * c;
730         char * reply;
731         struct map_layout ml;
732
733         get_map_layout(&ml, allpaths->mpvec);
734         reply = MALLOC(MAX_REPLY_LEN);
735
736         if (!reply)
737                 return 1;
738
739         c = reply;
740         c += sprintf(c, "\n");
741
742         vector_foreach_slot(allpaths->mpvec, mpp, i) {
743                 c += snprint_map(c, reply + MAX_REPLY_LEN - c, mpp, &ml);
744
745                 if (!mpp->failback_tick) {
746                         c += sprintf(c, "[no scheduled failback]\n");
747                         continue;
748                 }
749
750                 j = mpp->failback_tick;
751                 k = mpp->pgfailback - mpp->failback_tick;
752
753                 while (j-- > 0)
754                         c += sprintf(c, "X");
755
756
757                 while (k-- > 0)
758                         c += sprintf(c, ".");
759
760                 c += sprintf(c, " %i/%i\n", mpp->failback_tick, mpp->pgfailback);
761         }
762
763         *r = reply;
764         *len = (int)(c - reply + 1);
765         return 0;
766 }
767
768 int
769 dump_pathvec (char ** r, int * len, struct paths * allpaths)
770 {
771         int i;
772         struct path * pp;
773         char * reply;
774         char * p;
775
776         *len = VECTOR_SIZE(allpaths->pathvec) * sizeof(struct path);
777         reply = (char *)MALLOC(*len);
778         *r = reply;
779
780         if (!reply)
781                 return 1;
782
783         p = reply;
784
785         vector_foreach_slot (allpaths->pathvec, pp, i) {
786                 memcpy((void *)p, pp, sizeof(struct path));
787                 p += sizeof(struct path);
788         }
789
790         return 0;
791 }
792
793 static int
794 get_dm_mpvec (struct paths * allpaths)
795 {
796         int i;
797         struct multipath * mpp;
798
799         if (dm_get_maps(allpaths->mpvec, "multipath"))
800                 return 1;
801
802         vector_foreach_slot (allpaths->mpvec, mpp, i) {
803                 if (setup_multipath(allpaths, mpp))
804                         return 1;
805                 mpp->minor = dm_get_minor(mpp->alias);
806                 start_waiter_thread(mpp, allpaths);
807         }
808
809         return 0;
810 }
811
812 int
813 reconfigure (struct paths * allpaths)
814 {
815         struct config * old = conf;
816         struct multipath * mpp;
817         int i;
818
819         conf = NULL;
820
821         if (load_config(DEFAULT_CONFIGFILE)) {
822                 conf = old;
823                 condlog(2, "reconfigure failed, continue with old config");
824                 return 1;
825         }
826         conf->verbosity = old->verbosity;
827         free_config(old);
828
829         vector_foreach_slot (allpaths->mpvec, mpp, i) {
830                 mpp->mpe = find_mpe(mpp->wwid);
831                 set_paths_owner(allpaths, mpp);
832         }
833         condlog(2, "reconfigured");
834         return 0;
835 }
836
837 int
838 uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data)
839 {
840         struct paths * allpaths;
841         int r;
842         
843         *reply = NULL;
844         *len = 0;
845         allpaths = (struct paths *)trigger_data;
846
847         pthread_cleanup_push(cleanup_lock, allpaths->lock);
848         lock(allpaths->lock);
849
850         r = parse_cmd(str, reply, len, allpaths);
851
852         if (r) {
853                 *reply = STRDUP("fail\n");
854                 *len = strlen(*reply) + 1;
855                 r = 1;
856         }
857         else if (*len == 0) {
858                 *reply = STRDUP("ok\n");
859                 *len = strlen(*reply) + 1;
860                 r = 0;
861         }
862
863         pthread_cleanup_pop(1);
864         return r;
865 }
866
867 int 
868 uev_trigger (struct uevent * uev, void * trigger_data)
869 {
870         int r = 0;
871         char devname[32];
872         struct paths * allpaths;
873
874         allpaths = (struct paths *)trigger_data;
875         pthread_cleanup_push(cleanup_lock, allpaths->lock);
876         lock(allpaths->lock);
877
878         if (strncmp(uev->devpath, "/block", 6))
879                 goto out;
880
881         basename(uev->devpath, devname);
882
883         /*
884          * device map add/remove event
885          */
886         if (!strncmp(devname, "dm-", 3)) {
887                 if (!strncmp(uev->action, "add", 3)) {
888                         r = uev_add_map(devname, allpaths);
889                         goto out;
890                 }
891 #if 0
892                 if (!strncmp(uev->action, "remove", 6)) {
893                         r = uev_remove_map(devname, allpaths);
894                         goto out;
895                 }
896 #endif
897                 goto out;
898         }
899         
900         /*
901          * path add/remove event
902          */
903         if (blacklist(conf->blist, devname))
904                 goto out;
905
906         if (!strncmp(uev->action, "add", 3)) {
907                 r = uev_add_path(devname, allpaths);
908                 goto out;
909         }
910         if (!strncmp(uev->action, "remove", 6)) {
911                 r = uev_remove_path(devname, allpaths);
912                 goto out;
913         }
914
915 out:
916         FREE(uev);
917         pthread_cleanup_pop(1);
918         return r;
919 }
920
921 static void *
922 ueventloop (void * ap)
923 {
924         uevent_listen(&uev_trigger, ap);
925
926         return NULL;
927 }
928
929 static void *
930 uxlsnrloop (void * ap)
931 {
932         if (load_keys())
933                 return NULL;
934         
935         if (alloc_handlers())
936                 return NULL;
937
938         add_handler(LIST+PATHS, cli_list_paths);
939         add_handler(LIST+MAPS, cli_list_maps);
940         add_handler(ADD+PATH, cli_add_path);
941         add_handler(DEL+PATH, cli_del_path);
942         add_handler(ADD+MAP, cli_add_map);
943         add_handler(DEL+MAP, cli_del_map);
944         add_handler(SWITCH+MAP+GROUP, cli_switch_group);
945         add_handler(DUMP+PATHVEC, cli_dump_pathvec);
946         add_handler(RECONFIGURE, cli_reconfigure);
947
948         uxsock_listen(&uxsock_trigger, ap);
949
950         return NULL;
951 }
952
953 static int
954 exit_daemon (int status)
955 {
956         if (status != 0)
957                 fprintf(stderr, "bad exit status. see daemon.log\n");
958
959         condlog(3, "unlink pidfile");
960         unlink(DEFAULT_PIDFILE);
961
962         lock(&exit_mutex);
963         pthread_cond_signal(&exit_cond);
964         unlock(&exit_mutex);
965
966         return status;
967 }
968
969 static void
970 fail_path (struct path * pp)
971 {
972         if (!pp->mpp)
973                 return;
974
975         condlog(2, "checker failed path %s in map %s",
976                  pp->dev_t, pp->mpp->alias);
977
978         dm_fail_path(pp->mpp->alias, pp->dev_t);
979 }
980
981 /*
982  * caller must have locked the path list before calling that function
983  */
984 static void
985 reinstate_path (struct path * pp)
986 {
987         if (pp->mpp) {
988                 if (dm_reinstate(pp->mpp->alias, pp->dev_t))
989                         condlog(0, "%s: reinstate failed", pp->dev_t);
990                 else
991                         condlog(2, "%s: reinstated", pp->dev_t);
992         }
993 }
994
995 static void
996 enable_group(struct path * pp)
997 {
998         struct pathgroup * pgp;
999
1000         /*
1001          * if path is added through uev_add_path, pgindex can be unset.
1002          * next update_strings() will set it, upon map reload event.
1003          *
1004          * we can safely return here, because upon map reload, all
1005          * PG will be enabled.
1006          */
1007         if (!pp->pgindex)
1008                 return;
1009
1010         pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
1011         
1012         if (pgp->status == PGSTATE_DISABLED) {
1013                 condlog(2, "%s: enable group #%i", pp->mpp->alias, pp->pgindex);
1014                 dm_enablegroup(pp->mpp->alias, pp->pgindex);
1015         }
1016 }
1017
1018 static void
1019 mpvec_garbage_collector (struct paths * allpaths)
1020 {
1021         struct multipath * mpp;
1022         int i;
1023
1024         vector_foreach_slot (allpaths->mpvec, mpp, i) {
1025                 if (!dm_map_present(mpp->alias)) {
1026                         condlog(2, "%s: remove dead map", mpp->alias);
1027                         remove_map(mpp, allpaths);
1028                 }
1029         }
1030 }
1031
1032 static void
1033 defered_failback_tick (vector mpvec)
1034 {
1035         struct multipath * mpp;
1036         int i;
1037
1038         vector_foreach_slot (mpvec, mpp, i) {
1039                 /*
1040                  * defered failback getting sooner
1041                  */
1042                 if (mpp->pgfailback > 0 && mpp->failback_tick > 0) {
1043                         mpp->failback_tick--;
1044
1045                         if (!mpp->failback_tick)
1046                                 switch_pathgroup(mpp);
1047                 }
1048         }
1049 }
1050
1051 static void *
1052 checkerloop (void *ap)
1053 {
1054         struct paths *allpaths;
1055         struct path *pp;
1056         int i, count = 0;
1057         int newstate;
1058         char checker_msg[MAX_CHECKER_MSG_SIZE];
1059
1060         mlockall(MCL_CURRENT | MCL_FUTURE);
1061
1062         memset(checker_msg, 0, MAX_CHECKER_MSG_SIZE);
1063         allpaths = (struct paths *)ap;
1064
1065         condlog(2, "path checkers start up");
1066
1067         while (1) {
1068                 pthread_cleanup_push(cleanup_lock, allpaths->lock);
1069                 lock(allpaths->lock);
1070                 condlog(4, "tick");
1071
1072                 vector_foreach_slot (allpaths->pathvec, pp, i) {
1073                         if (!pp->mpp)
1074                                 continue;
1075
1076                         if (pp->tick) {
1077                                 /*
1078                                  * don't check this path yet
1079                                  */
1080                                 pp->tick--;
1081                                 continue;
1082                         }
1083
1084                         /*
1085                          * provision a next check soonest,
1086                          * in case we exit abnormaly from here
1087                          */
1088                         pp->tick = conf->checkint;
1089                         
1090                         if (!pp->checkfn) {
1091                                 pathinfo(pp, conf->hwtable, DI_SYSFS);
1092                                 select_checkfn(pp);
1093                         }
1094
1095                         if (!pp->checkfn) {
1096                                 condlog(0, "%s: checkfn is void", pp->dev);
1097                                 continue;
1098                         }
1099                         newstate = pp->checkfn(pp->fd, checker_msg,
1100                                                &pp->checker_context);
1101                         
1102                         if (newstate != pp->state) {
1103                                 pp->state = newstate;
1104                                 LOG_MSG(1, checker_msg);
1105
1106                                 /*
1107                                  * upon state change, reset the checkint
1108                                  * to the shortest delay
1109                                  */
1110                                 pp->checkint = conf->checkint;
1111
1112                                 if (newstate == PATH_DOWN ||
1113                                     newstate == PATH_SHAKY) {
1114                                         /*
1115                                          * proactively fail path in the DM
1116                                          */
1117                                         fail_path(pp);
1118
1119                                         /*
1120                                          * cancel scheduled failback
1121                                          */
1122                                         pp->mpp->failback_tick = 0;
1123
1124                                         continue;
1125                                 }
1126
1127                                 /*
1128                                  * reinstate this path
1129                                  */
1130                                 reinstate_path(pp);
1131
1132                                 /*
1133                                  * need to switch group ?
1134                                  */
1135                                 update_multipath_strings(pp->mpp,
1136                                                          allpaths->pathvec);
1137
1138                                 /*
1139                                  * schedule defered failback
1140                                  */
1141                                 if (pp->mpp->pgfailback > 0)
1142                                         pp->mpp->failback_tick =
1143                                                 pp->mpp->pgfailback;
1144
1145                                 if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE)
1146                                         switch_pathgroup(pp->mpp);
1147
1148                                 /*
1149                                  * if at least one path is up in a group, and
1150                                  * the group is disabled, re-enable it
1151                                  */
1152                                 if (newstate == PATH_UP)
1153                                         enable_group(pp);
1154                         }
1155                         else if (newstate == PATH_UP || newstate == PATH_GHOST) {
1156                                 LOG_MSG(4, checker_msg);
1157                                 /*
1158                                  * double the next check delay.
1159                                  * max at conf->max_checkint
1160                                  */
1161                                 if (pp->checkint < (conf->max_checkint / 2))
1162                                         pp->checkint = 2 * pp->checkint;
1163                                 else
1164                                         pp->checkint = conf->max_checkint;
1165
1166                                 pp->tick = pp->checkint;
1167                                 condlog(4, "%s: delay next check %is",
1168                                                 pp->dev_t, pp->tick);
1169
1170                         }
1171                         pp->state = newstate;
1172                 }
1173                 defered_failback_tick(allpaths->mpvec);
1174
1175                 if (count)
1176                         count--;
1177                 else {
1178                         condlog(4, "map garbage collection");
1179                         mpvec_garbage_collector(allpaths);
1180                         count = MAPGCINT;
1181                 }
1182                 
1183                 pthread_cleanup_pop(1);
1184                 sleep(1);
1185         }
1186         return NULL;
1187 }
1188
1189 static struct paths *
1190 init_paths (void)
1191 {
1192         struct paths * allpaths;
1193
1194         allpaths = (struct paths *)MALLOC(sizeof(struct paths));
1195
1196         if (!allpaths)
1197                 return NULL;
1198
1199         allpaths->lock = 
1200                 (pthread_mutex_t *)MALLOC(sizeof(pthread_mutex_t));
1201
1202         if (!allpaths->lock)
1203                 goto out;
1204
1205         allpaths->pathvec = vector_alloc();
1206
1207         if (!allpaths->pathvec)
1208                 goto out1;
1209                 
1210         allpaths->mpvec = vector_alloc();
1211
1212         if (!allpaths->mpvec)
1213                 goto out2;
1214         
1215         pthread_mutex_init(allpaths->lock, NULL);
1216
1217         return allpaths;
1218
1219 out2:
1220         vector_free(allpaths->pathvec);
1221 out1:
1222         FREE(allpaths->lock);
1223 out:
1224         FREE(allpaths);
1225         condlog(0, "failed to init paths");
1226         return NULL;
1227 }
1228
1229 static void *
1230 signal_set(int signo, void (*func) (int))
1231 {
1232         int r;
1233         struct sigaction sig;
1234         struct sigaction osig;
1235
1236         sig.sa_handler = func;
1237         sigemptyset(&sig.sa_mask);
1238         sig.sa_flags = 0;
1239
1240         r = sigaction(signo, &sig, &osig);
1241
1242         if (r < 0)
1243                 return (SIG_ERR);
1244         else
1245                 return (osig.sa_handler);
1246 }
1247
1248 static void
1249 sighup (int sig)
1250 {
1251         condlog(3, "SIGHUP received");
1252
1253 #ifdef _DEBUG_
1254         dbg_free_final(NULL);
1255 #endif
1256 }
1257
1258 static void
1259 sigend (int sig)
1260 {
1261         exit_daemon(0);
1262 }
1263
1264 static void
1265 signal_init(void)
1266 {
1267         signal_set(SIGHUP, sighup);
1268         signal_set(SIGINT, sigend);
1269         signal_set(SIGTERM, sigend);
1270         signal_set(SIGKILL, sigend);
1271 }
1272
1273 static void
1274 setscheduler (void)
1275 {
1276         int res;
1277         static struct sched_param sched_param = {
1278                 sched_priority: 99
1279         };
1280
1281         res = sched_setscheduler (0, SCHED_RR, &sched_param);
1282
1283         if (res == -1)
1284                 condlog(LOG_WARNING, "Could not set SCHED_RR at priority 99");
1285         return;
1286 }
1287
1288 static void
1289 set_oom_adj (int val)
1290 {
1291         FILE *fp;
1292
1293         fp = fopen("/proc/self/oom_adj", "w");
1294
1295         if (!fp)
1296                 return;
1297
1298         fprintf(fp, "%i", val);
1299         fclose(fp);
1300 }
1301         
1302 static int
1303 child (void * param)
1304 {
1305         pthread_t check_thr, uevent_thr, uxlsnr_thr;
1306         pthread_attr_t attr;
1307         struct paths * allpaths;
1308
1309         mlockall(MCL_CURRENT | MCL_FUTURE);
1310
1311         if (logsink)
1312                 log_thread_start();
1313
1314         condlog(2, "--------start up--------");
1315         condlog(2, "read " DEFAULT_CONFIGFILE);
1316
1317         if (load_config(DEFAULT_CONFIGFILE))
1318                 exit(1);
1319
1320         setlogmask(LOG_UPTO(conf->verbosity + 3));
1321
1322         /*
1323          * fill the voids left in the config file
1324          */
1325         if (!conf->checkint) {
1326                 conf->checkint = CHECKINT;
1327                 conf->max_checkint = MAX_CHECKINT;
1328         }
1329
1330         if (pidfile_create(DEFAULT_PIDFILE, getpid())) {
1331                 if (logsink)
1332                         log_thread_stop();
1333
1334                 exit(1);
1335         }
1336         signal_init();
1337         setscheduler();
1338         set_oom_adj(-17);
1339         allpaths = init_paths();
1340
1341         if (!allpaths)
1342                 exit(1);
1343
1344         if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
1345                 condlog(0, "can not find sysfs mount point");
1346                 exit(1);
1347         }
1348
1349         /*
1350          * fetch paths and multipaths lists
1351          * no paths and/or no multipaths are valid scenarii
1352          * vectors maintenance will be driven by events
1353          */
1354         path_discovery(allpaths->pathvec, conf, DI_SYSFS | DI_WWID);
1355         get_dm_mpvec(allpaths);
1356
1357         /*
1358          * start threads
1359          */
1360         pthread_attr_init(&attr);
1361         pthread_attr_setstacksize(&attr, 64 * 1024);
1362         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1363         
1364         pthread_create(&check_thr, &attr, checkerloop, allpaths);
1365         pthread_create(&uevent_thr, &attr, ueventloop, allpaths);
1366         pthread_create(&uxlsnr_thr, &attr, uxlsnrloop, allpaths);
1367
1368         pthread_cond_wait(&exit_cond, &exit_mutex);
1369
1370         /*
1371          * exit path
1372          */
1373         lock(allpaths->lock);
1374         remove_maps(allpaths);
1375         free_pathvec(allpaths->pathvec, FREE_PATHS);
1376
1377         pthread_cancel(check_thr);
1378         pthread_cancel(uevent_thr);
1379         pthread_cancel(uxlsnr_thr);
1380
1381         free_keys(keys);
1382         free_handlers(handlers);
1383         free_polls();
1384
1385         unlock(allpaths->lock);
1386         pthread_mutex_destroy(allpaths->lock);
1387         FREE(allpaths->lock);
1388         FREE(allpaths);
1389         free_config(conf);
1390
1391         condlog(2, "--------shut down-------");
1392         
1393         if (logsink)
1394                 log_thread_stop();
1395
1396 #ifdef _DEBUG_
1397         dbg_free_final(NULL);
1398 #endif
1399
1400         exit(0);
1401 }
1402
1403 int
1404 main (int argc, char *argv[])
1405 {
1406         extern char *optarg;
1407         extern int optind;
1408         int arg;
1409         int err;
1410         
1411         logsink = 1;
1412
1413         if (getuid() != 0) {
1414                 fprintf(stderr, "need to be root\n");
1415                 exit(1);
1416         }
1417
1418         /* make sure we don't lock any path */
1419         chdir("/");
1420         umask(umask(077) | 022);
1421
1422         conf = alloc_config();
1423
1424         if (!conf)
1425                 exit(1);
1426
1427         while ((arg = getopt(argc, argv, ":dv:k::")) != EOF ) {
1428         switch(arg) {
1429                 case 'd':
1430                         logsink = 0;
1431                         //debug=1; /* ### comment me out ### */
1432                         break;
1433                 case 'v':
1434                         if (sizeof(optarg) > sizeof(char *) ||
1435                             !isdigit(optarg[0]))
1436                                 exit(1);
1437
1438                         conf->verbosity = atoi(optarg);
1439                         break;
1440                 case 'k':
1441                         uxclnt(optarg);
1442                         exit(0);
1443                 default:
1444                         ;
1445                 }
1446         }
1447
1448         if (!logsink)
1449                 err = 0;
1450         else
1451                 err = fork();
1452         
1453         if (err < 0)
1454                 /* error */
1455                 exit(1);
1456         else if (err > 0)
1457                 /* parent dies */
1458                 exit(0);
1459         else
1460                 /* child lives */
1461                 return (child(NULL));
1462 }