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