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