Remove DAEMON defines
[platform/upstream/multipath-tools.git] / libmultipath / configure.c
1 /*
2  * Copyright (c) 2003, 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Kiyoshi Ueda, NEC
5  * Copyright (c) 2005 Patrick Caulfield, Redhat
6  * Copyright (c) 2005 Edward Goggin, EMC
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/file.h>
14 #include <errno.h>
15 #include <libdevmapper.h>
16
17 #include "checkers.h"
18 #include "vector.h"
19 #include "memory.h"
20 #include "devmapper.h"
21 #include "defaults.h"
22 #include "structs.h"
23 #include "structs_vec.h"
24 #include "dmparser.h"
25 #include "config.h"
26 #include "blacklist.h"
27 #include "propsel.h"
28 #include "discovery.h"
29 #include "debug.h"
30 #include "switchgroup.h"
31 #include "print.h"
32 #include "configure.h"
33 #include "pgpolicies.h"
34 #include "dict.h"
35 #include "alias.h"
36 #include "prio.h"
37
38 extern int
39 setup_map (struct multipath * mpp)
40 {
41         struct pathgroup * pgp;
42         int i;
43         
44         /*
45          * don't bother if devmap size is unknown
46          */
47         if (mpp->size <= 0) {
48                 condlog(3, "%s: devmap size is unknown", mpp->alias);
49                 return 1;
50         }
51
52         /*
53          * properties selectors
54          */
55         select_pgfailback(mpp);
56         select_pgpolicy(mpp);
57         select_selector(mpp);
58         select_features(mpp);
59         select_hwhandler(mpp);
60         select_rr_weight(mpp);
61         select_minio(mpp);
62         select_no_path_retry(mpp);
63         select_pg_timeout(mpp);
64
65         /*
66          * assign paths to path groups -- start with no groups and all paths
67          * in mpp->paths
68          */
69         if (mpp->pg) {
70                 vector_foreach_slot (mpp->pg, pgp, i)
71                         free_pathgroup(pgp, KEEP_PATHS);
72
73                 vector_free(mpp->pg);
74                 mpp->pg = NULL;
75         }
76         if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
77                 return 1;
78
79         mpp->nr_active = pathcount(mpp, PATH_UP);
80
81         /*
82          * ponders each path group and determine highest prio pg
83          * to switch over (default to first)
84          */
85         mpp->bestpg = select_path_group(mpp);
86
87         /*
88          * transform the mp->pg vector of vectors of paths
89          * into a mp->params strings to feed the device-mapper
90          */
91         if (assemble_map(mpp)) {
92                 condlog(0, "%s: problem assembing map", mpp->alias);
93                 return 1;
94         }
95         return 0;
96 }
97
98 static void
99 compute_pgid(struct pathgroup * pgp)
100 {
101         struct path * pp;
102         int i;
103
104         vector_foreach_slot (pgp->paths, pp, i)
105                 pgp->id ^= (long)pp;
106 }
107
108 static int
109 pgcmp (struct multipath * mpp, struct multipath * cmpp)
110 {
111         int i, j;
112         struct pathgroup * pgp;
113         struct pathgroup * cpgp;
114         int r = 0;
115
116         vector_foreach_slot (mpp->pg, pgp, i) {
117                 compute_pgid(pgp);
118
119                 vector_foreach_slot (cmpp->pg, cpgp, j) {
120                         if (pgp->id == cpgp->id) {
121                                 r = 0;
122                                 break;
123                         }
124                         r++;
125                 }
126                 if (r)
127                         return r;
128         }
129         return r;
130 }
131
132 static void
133 select_action (struct multipath * mpp, vector curmp)
134 {
135         struct multipath * cmpp;
136
137         cmpp = find_mp_by_alias(curmp, mpp->alias);
138
139         if (!cmpp) {
140                 cmpp = find_mp_by_wwid(curmp, mpp->wwid);
141
142                 if (cmpp && !conf->dry_run) {
143                         condlog(2, "%s: rename %s to %s", mpp->wwid,
144                                 cmpp->alias, mpp->alias);
145                         strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
146                         mpp->action = ACT_RENAME;
147                         return;
148                 }
149                 mpp->action = ACT_CREATE;
150                 condlog(3, "%s: set ACT_CREATE (map does not exist)",
151                         mpp->alias);
152                 return;
153         }
154
155         if (!find_mp_by_wwid(curmp, mpp->wwid)) {
156                 condlog(2, "%s: remove (wwid changed)", cmpp->alias);
157                 dm_flush_map(mpp->alias, DEFAULT_TARGET);
158                 strncat(cmpp->wwid, mpp->wwid, WWID_SIZE);
159                 drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
160                 mpp->action = ACT_CREATE;
161                 condlog(3, "%s: set ACT_CREATE (map wwid change)",
162                         mpp->alias);
163                 return;
164         }
165                 
166         if (pathcount(mpp, PATH_UP) == 0) {
167                 mpp->action = ACT_NOTHING;
168                 condlog(3, "%s: set ACT_NOTHING (no usable path)",
169                         mpp->alias);
170                 return;
171         }
172         if (cmpp->size != mpp->size) {
173                 mpp->action = ACT_RELOAD;
174                 condlog(3, "%s: set ACT_RELOAD (size change)",
175                         mpp->alias);
176                 return;
177         }
178         if (!mpp->no_path_retry && !mpp->pg_timeout &&
179             (strlen(cmpp->features) != strlen(mpp->features) ||
180              strcmp(cmpp->features, mpp->features))) {
181                 mpp->action =  ACT_RELOAD;
182                 condlog(3, "%s: set ACT_RELOAD (features change)",
183                         mpp->alias);
184                 return;
185         }
186         if (strncmp(cmpp->hwhandler, mpp->hwhandler,
187                     strlen(mpp->hwhandler))) {
188                 mpp->action = ACT_RELOAD;
189                 condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
190                         mpp->alias);
191                 return;
192         }
193         if (strncmp(cmpp->selector, mpp->selector,
194                     strlen(mpp->selector))) {
195                 mpp->action = ACT_RELOAD;
196                 condlog(3, "%s: set ACT_RELOAD (selector change)",
197                         mpp->alias);
198                 return;
199         }
200         if (cmpp->minio != mpp->minio) {
201                 mpp->action = ACT_RELOAD;
202                 condlog(3, "%s: set ACT_RELOAD (minio change, %u->%u)",
203                         mpp->alias, cmpp->minio, mpp->minio);
204                 return;
205         }
206         if (VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) {
207                 mpp->action = ACT_RELOAD;
208                 condlog(3, "%s: set ACT_RELOAD (path group number change)",
209                         mpp->alias);
210                 return;
211         }
212         if (pgcmp(mpp, cmpp)) {
213                 mpp->action = ACT_RELOAD;
214                 condlog(3, "%s: set ACT_RELOAD (path group topology change)",
215                         mpp->alias);
216                 return;
217         }
218         if (cmpp->nextpg != mpp->bestpg) {
219                 mpp->action = ACT_SWITCHPG;
220                 condlog(3, "%s: set ACT_SWITCHPG (next path group change)",
221                         mpp->alias);
222                 return;
223         }
224         mpp->action = ACT_NOTHING;
225         condlog(3, "%s: set ACT_NOTHING (map unchanged)",
226                 mpp->alias);
227         return;
228 }
229
230 extern int
231 reinstate_paths (struct multipath * mpp)
232 {
233         int i, j;
234         struct pathgroup * pgp;
235         struct path * pp;
236
237         if (!mpp->pg)
238                 return 0;
239
240         vector_foreach_slot (mpp->pg, pgp, i) {
241                 if (!pgp->paths)
242                         continue;
243
244                 vector_foreach_slot (pgp->paths, pp, j) {
245                         if (pp->state != PATH_UP &&
246                             (pgp->status == PGSTATE_DISABLED ||
247                              pgp->status == PGSTATE_ACTIVE))
248                                 continue;
249
250                         if (pp->dmstate == PSTATE_FAILED) {
251                                 if (dm_reinstate_path(mpp->alias, pp->dev_t))
252                                         condlog(0, "%s: error reinstating",
253                                                 pp->dev);
254                         }
255                 }
256         }
257         return 0;
258 }
259
260 static int
261 lock_multipath (struct multipath * mpp, int lock)
262 {
263         struct pathgroup * pgp;
264         struct path * pp;
265         int i, j;
266
267         if (!mpp || !mpp->pg)
268                 return 0;
269         
270         vector_foreach_slot (mpp->pg, pgp, i) {
271                 if (!pgp->paths)
272                         continue;
273                 vector_foreach_slot(pgp->paths, pp, j) {
274                         if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
275                             errno == EWOULDBLOCK)
276                                 return 1;
277                         else if (!lock)
278                                 flock(pp->fd, LOCK_UN);
279                 }
280         }
281         return 0;
282 }
283
284 /*
285  * Return value:
286  */
287 #define DOMAP_RETRY     -1
288 #define DOMAP_FAIL      0
289 #define DOMAP_OK        1
290 #define DOMAP_EXIST     2
291 #define DOMAP_DRY       3
292
293 extern int
294 domap (struct multipath * mpp)
295 {
296         int r = 0;
297
298         /*
299          * last chance to quit before touching the devmaps
300          */
301         if (conf->dry_run && mpp->action != ACT_NOTHING) {
302                 print_multipath_topology(mpp, conf->verbosity);
303                 return DOMAP_DRY;
304         }
305
306         switch (mpp->action) {
307         case ACT_REJECT:
308         case ACT_NOTHING:
309                 return DOMAP_EXIST;
310
311         case ACT_SWITCHPG:
312                 dm_switchgroup(mpp->alias, mpp->bestpg);
313                 /*
314                  * we may have avoided reinstating paths because there where in
315                  * active or disabled PG. Now that the topology has changed,
316                  * retry.
317                  */
318                 reinstate_paths(mpp);
319                 return DOMAP_EXIST;
320
321         case ACT_CREATE:
322                 if (lock_multipath(mpp, 1)) {
323                         condlog(3, "%s: failed to create map (in use)",
324                                 mpp->alias);
325                         return DOMAP_RETRY;
326                 }
327
328                 if (dm_map_present(mpp->alias)) {
329                         condlog(3, "%s: map already present", mpp->alias);
330                         break;
331                 }
332
333                 r = dm_addmap(DM_DEVICE_CREATE, mpp->alias, DEFAULT_TARGET,
334                               mpp->params, mpp->size, mpp->wwid);
335
336                 /*
337                  * DM_DEVICE_CREATE is actually DM_DEV_CREATE plus
338                  * DM_TABLE_LOAD. Failing the second part leaves an
339                  * empty map. Clean it up.
340                  */
341                 if (!r && dm_map_present(mpp->alias)) {
342                         condlog(3, "%s: failed to load map "
343                                    "(a path might be in use)",
344                                    mpp->alias);
345                         dm_flush_map(mpp->alias, DEFAULT_TARGET);
346                 }
347
348                 lock_multipath(mpp, 0);
349                 break;
350
351         case ACT_RELOAD:
352                 r = (dm_addmap(DM_DEVICE_RELOAD, mpp->alias, DEFAULT_TARGET,
353                               mpp->params, mpp->size, NULL) &&
354                      dm_simplecmd(DM_DEVICE_RESUME, mpp->alias));
355                 break;
356
357         case ACT_RENAME:
358                 r = dm_rename(mpp->alias_old, mpp->alias);
359                 break;
360
361         default:
362                 break;
363         }
364
365         if (r) {
366                 /*
367                  * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
368                  * succeeded
369                  */
370                 if (!mpp->waiter) {
371                         /* multipath client mode */
372                         dm_switchgroup(mpp->alias, mpp->bestpg);
373                         if (mpp->action != ACT_NOTHING)
374                                 print_multipath_topology(mpp, conf->verbosity);
375                 } else  {
376                         /* multipath daemon mode */
377                         mpp->stat_map_loads++;
378                         condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias,
379                                 mpp->size, DEFAULT_TARGET, mpp->params);
380                         /*
381                          * Required action is over, reset for the stateful daemon
382                          */
383                         mpp->action = ACT_NOTHING;
384                 }
385                 return DOMAP_OK;
386         }
387         return DOMAP_FAIL;
388 }
389
390 static int
391 deadmap (struct multipath * mpp)
392 {
393         int i, j;
394         struct pathgroup * pgp;
395         struct path * pp;
396
397         if (!mpp->pg)
398                 return 1;
399
400         vector_foreach_slot (mpp->pg, pgp, i) {
401                 if (!pgp->paths)
402                         continue;
403
404                 vector_foreach_slot (pgp->paths, pp, j)
405                         if (strlen(pp->dev))
406                                 return 0; /* alive */
407         }
408         
409         return 1; /* dead */
410 }
411
412 extern int
413 coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid)
414 {
415         int r = 1;
416         int k, i;
417         char empty_buff[WWID_SIZE];
418         struct multipath * mpp;
419         struct path * pp1;
420         struct path * pp2;
421         vector curmp = vecs->mpvec;
422         vector pathvec = vecs->pathvec;
423
424         memset(empty_buff, 0, WWID_SIZE);
425
426         vector_foreach_slot (pathvec, pp1, k) {
427                 /* skip this path for some reason */
428
429                 /* 1. if path has no unique id or wwid blacklisted */
430                 if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
431                     filter_path(conf, pp1) > 0)
432                         continue;
433
434                 /* 2. if path already coalesced */
435                 if (pp1->mpp)
436                         continue;
437
438                 /* 3. if path has disappeared */
439                 if (!pp1->size)
440                         continue;
441
442                 /* 4. path is out of scope */
443                 if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
444                         continue;
445
446                 /*
447                  * at this point, we know we really got a new mp
448                  */
449                 if ((mpp = add_map_with_path(vecs, pp1, 0)) == NULL)
450                         return 1;
451
452                 if (pp1->priority == PRIO_UNDEF)
453                         mpp->action = ACT_REJECT;
454
455                 if (!mpp->paths) {
456                         condlog(0, "%s: skip coalesce (no paths)", mpp->alias);
457                         remove_map(mpp, vecs, 0);
458                         continue;
459                 }
460                 
461                 for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
462                         pp2 = VECTOR_SLOT(pathvec, i);
463
464                         if (strcmp(pp1->wwid, pp2->wwid))
465                                 continue;
466                         
467                         if (!pp2->size)
468                                 continue;
469
470                         if (pp2->size != mpp->size) {
471                                 /*
472                                  * ouch, avoid feeding that to the DM
473                                  */
474                                 condlog(0, "%s: size %llu, expected %llu. "
475                                         "Discard", pp2->dev_t, pp2->size,
476                                         mpp->size);
477                                 mpp->action = ACT_REJECT;
478                         }
479                         if (pp2->priority == PRIO_UNDEF)
480                                 mpp->action = ACT_REJECT;
481                 }
482                 verify_paths(mpp, vecs, NULL);
483                 
484                 if (setup_map(mpp)) {
485                         remove_map(mpp, vecs, 0);
486                         continue;
487                 }
488
489                 if (mpp->action == ACT_UNDEF)
490                         select_action(mpp, curmp);
491
492                 r = domap(mpp);
493
494                 if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
495                         condlog(3, "%s: domap (%u) failure "
496                                    "for create/reload map",
497                                 mpp->alias, r);
498                         if (r == DOMAP_FAIL) {
499                                 remove_map(mpp, vecs, 0);
500                                 continue;
501                         } else /* if (r == DOMAP_RETRY) */
502                                 return r;
503                 }
504                 if (r == DOMAP_DRY)
505                         continue;
506
507                 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
508                         if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
509                                 dm_queue_if_no_path(mpp->alias, 0);
510                         else
511                                 dm_queue_if_no_path(mpp->alias, 1);
512                 }
513                 if (mpp->pg_timeout != PGTIMEOUT_UNDEF) {
514                         if (mpp->pg_timeout == -PGTIMEOUT_NONE)
515                                 dm_set_pg_timeout(mpp->alias,  0);
516                         else
517                                 dm_set_pg_timeout(mpp->alias, mpp->pg_timeout);
518                 }
519
520                 if (newmp) {
521                         if (mpp->action != ACT_REJECT) {
522                                 if (!vector_alloc_slot(newmp))
523                                         return 1;
524                                 vector_set_slot(newmp, mpp);
525                         }
526                         else
527                                 remove_map(mpp, vecs, 0);
528                 }
529         }
530         /*
531          * Flush maps with only dead paths (ie not in sysfs)
532          * Keep maps with only failed paths
533          */
534         if (newmp) {
535                 vector_foreach_slot (newmp, mpp, i) {
536                         char alias[WWID_SIZE];
537                         int j;
538
539                         if (!deadmap(mpp))
540                                 continue;
541
542                         strncpy(alias, mpp->alias, WWID_SIZE);
543
544                         if ((j = find_slot(newmp, (void *)mpp)) != -1)
545                                 vector_del_slot(newmp, j);
546
547                         remove_map(mpp, vecs, 0);
548
549                         if (dm_flush_map(mpp->alias, DEFAULT_TARGET))
550                                 condlog(2, "%s: remove failed (dead)",
551                                         mpp->alias);
552                         else
553                                 condlog(2, "%s: remove (dead)", mpp->alias);
554                 }
555         }
556         return 0;
557 }
558
559 extern char *
560 get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
561 {
562         struct path * pp;
563         char buff[FILE_NAME_SIZE];
564         char * refwwid = NULL, tmpwwid[WWID_SIZE];
565
566         if (dev_type == DEV_NONE)
567                 return NULL;
568
569         if (dev_type == DEV_DEVNODE) {
570                 basename(dev, buff);
571                 pp = find_path_by_dev(pathvec, buff);
572                 
573                 if (!pp) {
574                         pp = alloc_path();
575
576                         if (!pp)
577                                 return NULL;
578
579                         strncpy(pp->dev, buff, FILE_NAME_SIZE);
580
581                         if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
582                                 return NULL;
583
584                         if (store_path(pathvec, pp)) {
585                                 free_path(pp);
586                                 return NULL;
587                         }
588                 }
589                 refwwid = pp->wwid;
590                 goto out;
591         }
592
593         if (dev_type == DEV_DEVT) {
594                 pp = find_path_by_devt(pathvec, dev);
595                 
596                 if (!pp) {
597                         if (devt2devname(buff, dev))
598                                 return NULL;
599
600                         pp = alloc_path();
601
602                         if (!pp)
603                                 return NULL;
604
605                         strncpy(pp->dev, buff, FILE_NAME_SIZE);
606
607                         if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
608                                 return NULL;
609                         
610                         if (store_path(pathvec, pp)) {
611                                 free_path(pp);
612                                 return NULL;
613                         }
614                 }
615                 refwwid = pp->wwid;
616                 goto out;
617         }
618         if (dev_type == DEV_DEVMAP) {
619
620                 if (((dm_get_uuid(dev, tmpwwid)) == 0) && (strlen(tmpwwid))) {
621                         refwwid = tmpwwid;
622                         goto out;
623                 }
624
625                 /*
626                  * may be a binding
627                  */
628                 refwwid = get_user_friendly_wwid(dev,
629                                                  conf->bindings_file);
630
631                 if (refwwid)
632                         return refwwid;
633
634                 /*
635                  * or may be an alias
636                  */
637                 refwwid = get_mpe_wwid(dev);
638
639                 /*
640                  * or directly a wwid
641                  */
642                 if (!refwwid)
643                         refwwid = dev;
644         }
645 out:
646         if (refwwid && strlen(refwwid))
647                 return STRDUP(refwwid);
648
649         return NULL;
650 }
651