[libmultipath] extend the scope of the "rr_min_io" keyword to hwe and mpe
[platform/upstream/multipath-tools.git] / multipath / main.c
1 /*
2  * Soft:        multipath device mapper target autoconfig
3  *
4  * Version:     $Id: main.h,v 0.0.1 2003/09/18 15:13:38 cvaroqui Exp $
5  *
6  * Author:      Christophe Varoqui
7  *
8  *              This program is distributed in the hope that it will be useful,
9  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *              See the GNU General Public License for more details.
12  *
13  *              This program is free software; you can redistribute it and/or
14  *              modify it under the terms of the GNU General Public License
15  *              as published by the Free Software Foundation; either version
16  *              2 of the License, or (at your option) any later version.
17  *
18  * Copyright (c) 2003, 2004, 2005 Christophe Varoqui
19  * Copyright (c) 2005 Benjamin Marzinski, Redhat
20  * Copyright (c) 2005 Kiyoshi Ueda, NEC
21  * Copyright (c) 2005 Patrick Caulfield, Redhat
22  * Copyright (c) 2005 Edward Goggin, EMC
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <sys/file.h>
30 #include <errno.h>
31
32 #include <parser.h>
33 #include <vector.h>
34 #include <memory.h>
35 #include <libdevmapper.h>
36 #include <devmapper.h>
37 #include <checkers.h>
38 #include <path_state.h>
39 #include <blacklist.h>
40 #include <hwtable.h>
41 #include <util.h>
42 #include <defaults.h>
43 #include <structs.h>
44 #include <dmparser.h>
45 #include <cache.h>
46 #include <config.h>
47 #include <propsel.h>
48 #include <discovery.h>
49 #include <debug.h>
50 #include <switchgroup.h>
51 #include <sysfs/libsysfs.h>
52 #include <print.h>
53 #include <alias.h>
54
55 #include "main.h"
56 #include "pgpolicies.h"
57 #include "dict.h"
58
59 /* for column aligned output */
60 struct path_layout pl;
61
62 static char *
63 get_refwwid (vector pathvec)
64 {
65         struct path * pp;
66         char buff[FILE_NAME_SIZE];
67         char * refwwid;
68
69         if (conf->dev_type == DEV_NONE)
70                 return NULL;
71
72         if (conf->dev_type == DEV_DEVNODE) {
73                 basename(conf->dev, buff);
74                 pp = find_path_by_dev(pathvec, buff);
75                 
76                 if (!pp) {
77                         pp = alloc_path();
78
79                         if (!pp)
80                                 return NULL;
81
82                         strncpy(pp->dev, buff, FILE_NAME_SIZE);
83
84                         if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
85                                 return NULL;
86
87                         if (store_path(pathvec, pp)) {
88                                 free_path(pp);
89                                 return NULL;
90                         }
91                 }
92                 refwwid = pp->wwid;
93                 goto out;
94         }
95
96         if (conf->dev_type == DEV_DEVT) {
97                 pp = find_path_by_devt(pathvec, conf->dev);
98                 
99                 if (!pp) {
100                         if (devt2devname(buff, conf->dev))
101                                 return NULL;
102
103                         pp = alloc_path();
104
105                         if (!pp)
106                                 return NULL;
107
108                         strncpy(pp->dev, buff, FILE_NAME_SIZE);
109
110                         if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
111                                 return NULL;
112                         
113                         if (store_path(pathvec, pp)) {
114                                 free_path(pp);
115                                 return NULL;
116                         }
117                 }
118                 refwwid = pp->wwid;
119                 goto out;
120         }
121         if (conf->dev_type == DEV_DEVMAP) {
122                 /*
123                  * may be a binding
124                  */
125                 refwwid = get_user_friendly_wwid(conf->dev,
126                                                  conf->bindings_file);
127
128                 if (refwwid)
129                         return refwwid;
130
131                 /*
132                  * or may be an alias
133                  */
134                 refwwid = get_mpe_wwid(conf->dev);
135
136                 /*
137                  * or directly a wwid
138                  */
139                 if (!refwwid)
140                         refwwid = conf->dev;
141         }
142 out:
143         if (refwwid && strlen(refwwid))
144                 return STRDUP(refwwid);
145
146         return NULL;
147 }
148
149 static void
150 print_path (struct path * pp, char * style)
151 {
152         char line[MAX_LINE_LEN];
153
154         snprint_path(&line[0], MAX_LINE_LEN, style, pp, &pl);
155         printf("%s", line);
156 }
157
158 static void
159 print_map (struct multipath * mpp)
160 {
161         if (mpp->size && mpp->params)
162                 printf("0 %llu %s %s\n",
163                          mpp->size, DEFAULT_TARGET, mpp->params);
164         return;
165 }
166
167 static void
168 print_all_paths (vector pathvec, int banner)
169 {
170         int i;
171         struct path * pp;
172         char line[MAX_LINE_LEN];
173
174         if (!VECTOR_SIZE(pathvec)) {
175                 if (banner)
176                         fprintf(stdout, "===== no paths =====\n");
177                 return;
178         }
179         
180         if (banner)
181                 fprintf(stdout, "===== paths list =====\n");
182
183         get_path_layout(&pl, pathvec);
184         snprint_path_header(line, MAX_LINE_LEN, PRINT_PATH_LONG, &pl);
185         fprintf(stdout, "%s", line);
186
187         vector_foreach_slot (pathvec, pp, i)
188                 print_path(pp, PRINT_PATH_LONG);
189 }
190
191 static void
192 print_mp (struct multipath * mpp)
193 {
194         int j, i;
195         struct path * pp = NULL;
196         struct pathgroup * pgp = NULL;
197
198         if (mpp->action == ACT_NOTHING || !conf->verbosity || !mpp->size)
199                 return;
200
201         if (conf->verbosity > 1) {
202                 switch (mpp->action) {
203                 case ACT_RELOAD:
204                         printf("%s: ", ACT_RELOAD_STR);
205                         break;
206
207                 case ACT_CREATE:
208                         printf("%s: ", ACT_CREATE_STR);
209                         break;
210
211                 case ACT_SWITCHPG:
212                         printf("%s: ", ACT_SWITCHPG_STR);
213                         break;
214
215                 default:
216                         break;
217                 }
218         }
219
220         if (mpp->alias)
221                 printf("%s", mpp->alias);
222
223         if (conf->verbosity == 1) {
224                 printf("\n");
225                 return;
226         }
227         if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE))
228                 printf(" (%s)", mpp->wwid);
229
230         printf("\n");
231
232         if (mpp->size < (1 << 11))
233                 printf("[size=%llu kB]", mpp->size >> 1);
234         else if (mpp->size < (1 << 21))
235                 printf("[size=%llu MB]", mpp->size >> 11);
236         else if (mpp->size < (1 << 31))
237                 printf("[size=%llu GB]", mpp->size >> 21);
238         else
239                 printf("[size=%llu TB]", mpp->size >> 31);
240
241         if (mpp->features)
242                 printf("[features=\"%s\"]", mpp->features);
243
244         if (mpp->hwhandler)
245                 printf("[hwhandler=\"%s\"]", mpp->hwhandler);
246
247         fprintf(stdout, "\n");
248
249         if (!mpp->pg)
250                 return;
251
252         vector_foreach_slot (mpp->pg, pgp, j) {
253                 printf("\\_ ");
254
255                 if (mpp->selector) {
256                         printf("%s ", mpp->selector);
257 #if 0
258                         /* align to path status info */
259                         for (i = pl.hbtl_len + pl.dev_len + pl.dev_t_len + 4;
260                              i > strlen(mpp->selector); i--)
261                                 printf(" ");
262 #endif
263                 }
264                 if (pgp->priority)
265                         printf("[prio=%i]", pgp->priority);
266
267                 switch (pgp->status) {
268                 case PGSTATE_ENABLED:
269                         printf("[enabled]");
270                         break;
271                 case PGSTATE_DISABLED:
272                         printf("[disabled]");
273                         break;
274                 case PGSTATE_ACTIVE:
275                         printf("[active]");
276                         break;
277                 default:
278                         break;
279                 }
280                 printf("\n");
281
282                 vector_foreach_slot (pgp->paths, pp, i)
283                         print_path(pp, PRINT_PATH_INDENT);
284         }
285         printf("\n");
286 }
287
288 static int
289 filter_pathvec (vector pathvec, char * refwwid)
290 {
291         int i;
292         struct path * pp;
293
294         if (!refwwid || !strlen(refwwid))
295                 return 0;
296
297         vector_foreach_slot (pathvec, pp, i) {
298                 if (strncmp(pp->wwid, refwwid, WWID_SIZE) != 0) {
299                         condlog(3, "skip path %s : out of scope", pp->dev);
300                         free_path(pp);
301                         vector_del_slot(pathvec, i);
302                         i--;
303                 }
304         }
305         return 0;
306 }
307
308 /*
309  * Transforms the path group vector into a proper device map string
310  */
311 int
312 assemble_map (struct multipath * mp)
313 {
314         int i, j;
315         int shift, freechar;
316         int minio;
317         char * p;
318         struct pathgroup * pgp;
319         struct path * pp;
320
321         minio = mp->minio;
322         p = mp->params;
323         freechar = sizeof(mp->params);
324         
325         shift = snprintf(p, freechar, "%s %s %i %i",
326                          mp->features, mp->hwhandler,
327                          VECTOR_SIZE(mp->pg), mp->bestpg);
328
329         if (shift >= freechar) {
330                 fprintf(stderr, "mp->params too small\n");
331                 return 1;
332         }
333         p += shift;
334         freechar -= shift;
335         
336         vector_foreach_slot (mp->pg, pgp, i) {
337                 pgp = VECTOR_SLOT(mp->pg, i);
338                 shift = snprintf(p, freechar, " %s %i 1", mp->selector,
339                                  VECTOR_SIZE(pgp->paths));
340                 if (shift >= freechar) {
341                         fprintf(stderr, "mp->params too small\n");
342                         return 1;
343                 }
344                 p += shift;
345                 freechar -= shift;
346
347                 vector_foreach_slot (pgp->paths, pp, j) {
348                         if (mp->rr_weight == RR_WEIGHT_PRIO && pp->priority)
349                                 minio *= pp->priority;
350
351                         shift = snprintf(p, freechar, " %s %d",
352                                          pp->dev_t, minio);
353                         if (shift >= freechar) {
354                                 fprintf(stderr, "mp->params too small\n");
355                                 return 1;
356                         }
357                         p += shift;
358                         freechar -= shift;
359                 }
360         }
361         if (freechar < 1) {
362                 fprintf(stderr, "mp->params too small\n");
363                 return 1;
364         }
365         snprintf(p, 1, "\n");
366
367         if (conf->verbosity > 2)
368                 print_map(mp);
369
370         return 0;
371 }
372
373 static int
374 setup_map (struct multipath * mpp)
375 {
376         /*
377          * don't bother if devmap size is unknown
378          */
379         if (mpp->size <= 0) {
380                 condlog(3, "%s devmap size is unknown", mpp->alias);
381                 return 1;
382         }
383
384         /*
385          * properties selectors
386          */
387         select_pgpolicy(mpp);
388         select_selector(mpp);
389         select_features(mpp);
390         select_hwhandler(mpp);
391         select_rr_weight(mpp);
392         select_no_path_retry(mpp);
393         select_minio(mpp);
394
395         /*
396          * apply selected grouping policy to valid paths
397          */
398         switch (mpp->pgpolicy) {
399         case MULTIBUS:
400                 one_group(mpp);
401                 break;
402         case FAILOVER:
403                 one_path_per_group(mpp);
404                 break;
405         case GROUP_BY_SERIAL:
406                 group_by_serial(mpp);
407                 break;
408         case GROUP_BY_PRIO:
409                 group_by_prio(mpp);
410                 break;
411         case GROUP_BY_NODE_NAME:
412                 group_by_node_name(mpp);
413                 break;
414         default:
415                 break;
416         }
417
418         if (mpp->pg == NULL) {
419                 condlog(3, "pgpolicy failed to produce a pg vector");
420                 return 1;
421         }
422
423         /*
424          * ponders each path group and determine highest prio pg
425          * to switch over (default to first)
426          */
427         mpp->bestpg = select_path_group(mpp);
428
429         /*
430          * transform the mp->pg vector of vectors of paths
431          * into a mp->params strings to feed the device-mapper
432          */
433         if (assemble_map(mpp)) {
434                 condlog(3, "problem assembing map");
435                 return 1;
436         }
437         return 0;
438 }
439
440 static int
441 pathcount (struct multipath * mpp, int state)
442 {
443         struct pathgroup *pgp;
444         struct path *pp;
445         int i, j;
446         int count = 0;
447
448         vector_foreach_slot (mpp->pg, pgp, i)
449                 vector_foreach_slot (pgp->paths, pp, j)
450                         if (pp->state == state)
451                                 count++;
452         return count;
453 }
454
455 static void
456 compute_pgid(struct pathgroup * pgp)
457 {
458         struct path * pp;
459         int i;
460
461         vector_foreach_slot (pgp->paths, pp, i)
462                 pgp->id ^= (long)pp;
463 }
464
465 static int
466 pgcmp (struct multipath * mpp, struct multipath * cmpp)
467 {
468         int i, j;
469         struct pathgroup * pgp;
470         struct pathgroup * cpgp;
471         int r = 0;
472
473         vector_foreach_slot (mpp->pg, pgp, i) {
474                 compute_pgid(pgp);
475
476                 vector_foreach_slot (cmpp->pg, cpgp, j) {
477                         if (pgp->id == cpgp->id) {
478                                 r = 0;
479                                 break;
480                         }
481                         r++;
482                 }
483                 if (r)
484                         return r;
485         }
486         return r;
487 }
488
489 static void
490 select_action (struct multipath * mpp, vector curmp)
491 {
492         struct multipath * cmpp;
493
494         cmpp = find_mp_by_alias(curmp, mpp->alias);
495
496         if (!cmpp) {
497                 cmpp = find_mp_by_wwid(curmp, mpp->wwid);
498
499                 if (cmpp && !conf->dry_run) {
500                         condlog(2, "remove: %s (dup of %s)",
501                                 cmpp->alias, mpp->alias);
502                         dm_flush_map(cmpp->alias, DEFAULT_TARGET);
503                 }
504                 mpp->action = ACT_CREATE;
505                 condlog(3, "set ACT_CREATE: map does not exists");
506                 return;
507         }
508
509         if (!find_mp_by_wwid(curmp, mpp->wwid)) {
510                 condlog(2, "remove: %s (wwid changed)", cmpp->alias);
511                 dm_flush_map(mpp->alias, NULL);
512                 strncat(cmpp->wwid, mpp->wwid, WWID_SIZE);
513                 drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
514                 mpp->action = ACT_CREATE;
515                 condlog(3, "set ACT_CREATE: map wwid change");
516                 return;
517         }
518                 
519         if (pathcount(mpp, PATH_UP) == 0) {
520                 mpp->action = ACT_NOTHING;
521                 condlog(3, "set ACT_NOTHING: no usable path");
522                 return;
523         }
524         if (cmpp->size != mpp->size) {
525                 mpp->action = ACT_RELOAD;
526                 condlog(3, "set ACT_RELOAD: size change");
527                 return;
528         }
529         if (!mpp->no_path_retry && /* let features be handled by the daemon */
530             strncmp(cmpp->features, mpp->features, strlen(mpp->features))) {
531                 mpp->action =  ACT_RELOAD;
532                 condlog(3, "set ACT_RELOAD: features change");
533                 return;
534         }
535         if (strncmp(cmpp->hwhandler, mpp->hwhandler,
536                     strlen(mpp->hwhandler))) {
537                 mpp->action = ACT_RELOAD;
538                 condlog(3, "set ACT_RELOAD: hwhandler change");
539                 return;
540         }
541         if (strncmp(cmpp->selector, mpp->selector,
542                     strlen(mpp->selector))) {
543                 mpp->action = ACT_RELOAD;
544                 condlog(3, "set ACT_RELOAD: selector change");
545                 return;
546         }
547         if (cmpp->minio != mpp->minio) {
548                 mpp->action = ACT_RELOAD;
549                 condlog(3, "set ACT_RELOAD: minio change (%u->%u)",
550                         cmpp->minio, mpp->minio);
551                 return;
552         }
553         if (VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) {
554                 mpp->action = ACT_RELOAD;
555                 condlog(3, "set ACT_RELOAD: number of path group change");
556                 return;
557         }
558         if (pgcmp(mpp, cmpp)) {
559                 mpp->action = ACT_RELOAD;
560                 condlog(3, "set ACT_RELOAD: path group topology change");
561                 return;
562         }
563         if (cmpp->nextpg != mpp->bestpg) {
564                 mpp->action = ACT_SWITCHPG;
565                 condlog(3, "set ACT_SWITCHPG: next path group change");
566                 return;
567         }
568         mpp->action = ACT_NOTHING;
569         condlog(3, "set ACT_NOTHING: map unchanged");
570         return;
571 }
572
573 static int
574 reinstate_paths (struct multipath * mpp)
575 {
576         int i, j;
577         struct pathgroup * pgp;
578         struct path * pp;
579
580         if (!mpp->pg)
581                 return 0;
582
583         vector_foreach_slot (mpp->pg, pgp, i) {
584                 if (!pgp->paths)
585                         continue;
586
587                 vector_foreach_slot (pgp->paths, pp, j) {
588                         if (pp->state != PATH_UP &&
589                             (pgp->status == PGSTATE_DISABLED ||
590                              pgp->status == PGSTATE_ACTIVE))
591                                 continue;
592
593                         if (pp->dmstate == PSTATE_FAILED) {
594                                 if (dm_reinstate_path(mpp->alias, pp->dev_t))
595                                         condlog(0, "error reinstating %s",
596                                                 pp->dev);
597                         }
598                 }
599         }
600         return 0;
601 }
602
603 int lock_multipath (struct multipath * mpp, int lock)
604 {
605         struct pathgroup * pgp;
606         struct path * pp;
607         int i, j;
608
609         if (!mpp || !mpp->pg)
610                 return 0;
611         
612         vector_foreach_slot (mpp->pg, pgp, i) {
613                 if (!pgp->paths)
614                         continue;
615                 vector_foreach_slot(pgp->paths, pp, j) {
616                         if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
617                             errno == EWOULDBLOCK)
618                                 return 1;
619                         else if (!lock)
620                                 flock(pp->fd, LOCK_UN);
621                 }
622         }
623         return 0;
624 }
625
626 /*
627  * Return value:
628  *  -1: Retry
629  *   0: DM_DEVICE_CREATE or DM_DEVICE_RELOAD failed, or dry_run mode.
630  *   1: DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded.
631  *   2: Map is already existing.
632  */
633 static int
634 domap (struct multipath * mpp)
635 {
636         int r = 0;
637
638         /*
639          * last chance to quit before touching the devmaps
640          */
641         if (conf->dry_run) {
642                 print_mp(mpp);
643                 return 0;
644         }
645
646         switch (mpp->action) {
647         case ACT_NOTHING:
648                 return 2;
649
650         case ACT_SWITCHPG:
651                 dm_switchgroup(mpp->alias, mpp->bestpg);
652                 /*
653                  * we may have avoided reinstating paths because there where in
654                  * active or disabled PG. Now that the topology has changed,
655                  * retry.
656                  */
657                 reinstate_paths(mpp);
658                 return 2;
659
660         case ACT_CREATE:
661                 if (lock_multipath(mpp, 1)) {
662                         condlog(3, "%s: in use", mpp->alias);
663                         return -1;
664                 }
665                 dm_shut_log();
666
667                 if (dm_map_present(mpp->alias))
668                         break;
669
670                 r = dm_addmap(DM_DEVICE_CREATE, mpp->alias, DEFAULT_TARGET,
671                               mpp->params, mpp->size, mpp->wwid);
672
673                 /*
674                  * DM_DEVICE_CREATE is actually DM_DEV_CREATE plus
675                  * DM_TABLE_LOAD. Failing the second part leaves an
676                  * empty map. Clean it up.
677                  */
678                 if (!r && dm_map_present(mpp->alias)) {
679                         condlog(3, "%s: failed to load map "
680                                    "(a path might be in use)",
681                                    mpp->alias);
682                         dm_flush_map(mpp->alias, NULL);
683                 }
684
685                 lock_multipath(mpp, 0);
686                 dm_restore_log();
687                 break;
688
689         case ACT_RELOAD:
690                 r = (dm_addmap(DM_DEVICE_RELOAD, mpp->alias, DEFAULT_TARGET,
691                               mpp->params, mpp->size, NULL) &&
692                      dm_simplecmd(DM_DEVICE_RESUME, mpp->alias));
693                 break;
694
695         default:
696                 break;
697         }
698
699         if (r) {
700                 /*
701                  * DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded
702                  */
703                 dm_switchgroup(mpp->alias, mpp->bestpg);
704                 print_mp(mpp);
705         }
706
707         return r;
708 }
709
710 static int
711 deadmap (struct multipath * mpp)
712 {
713         int i, j;
714         struct pathgroup * pgp;
715         struct path * pp;
716
717         if (!mpp->pg)
718                 return 1;
719
720         vector_foreach_slot (mpp->pg, pgp, i) {
721                 if (!pgp->paths)
722                         continue;
723
724                 vector_foreach_slot (pgp->paths, pp, j)
725                         if (strlen(pp->dev))
726                                 return 0; /* alive */
727         }
728         
729         return 1; /* dead */
730 }
731
732 static int
733 coalesce_paths (vector curmp, vector pathvec)
734 {
735         int r = 1;
736         int k, i;
737         char empty_buff[WWID_SIZE];
738         struct multipath * mpp;
739         struct path * pp1;
740         struct path * pp2;
741
742         memset(empty_buff, 0, WWID_SIZE);
743
744         vector_foreach_slot (pathvec, pp1, k) {
745                 /* skip this path for some reason */
746
747                 /* 1. if path has no unique id or wwid blacklisted */
748                 if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
749                     blacklist(conf->blist, pp1->wwid))
750                         continue;
751
752                 /* 2. if path already coalesced */
753                 if (pp1->mpp)
754                         continue;
755
756                 /*
757                  * at this point, we know we really got a new mp
758                  */
759                 mpp = alloc_multipath();
760
761                 if (!mpp)
762                         return 1;
763
764                 mpp->mpe = find_mpe(pp1->wwid);
765                 mpp->hwe = pp1->hwe;
766                 strcpy(mpp->wwid, pp1->wwid);
767                 select_alias(mpp);
768
769                 pp1->mpp = mpp;
770                 mpp->size = pp1->size;
771                 mpp->paths = vector_alloc();
772
773                 if (pp1->priority < 0)
774                         mpp->action = ACT_NOTHING;
775
776                 if (!mpp->paths)
777                         return 1;
778                 
779                 if (store_path(mpp->paths, pp1))
780                         return 1;
781
782                 for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
783                         pp2 = VECTOR_SLOT(pathvec, i);
784
785                         if (strcmp(pp1->wwid, pp2->wwid))
786                                 continue;
787                         
788                         pp2->mpp = mpp;
789
790                         if (pp2->size != mpp->size) {
791                                 /*
792                                  * ouch, avoid feeding that to the DM
793                                  */
794                                 condlog(3, "path size mismatch : discard %s",
795                                      mpp->wwid);
796                                 mpp->action = ACT_NOTHING;
797                         }
798                         if (pp2->priority < 0)
799                                 mpp->action = ACT_NOTHING;
800
801                         if (store_path(mpp->paths, pp2))
802                                 return 1;
803                 }
804                 if (setup_map(mpp))
805                         goto next;
806
807                 if (mpp->action == ACT_UNDEF)
808                         select_action(mpp, curmp);
809
810                 r = domap(mpp);
811
812                 if (r < 0)
813                         return r;
814
815                 if (r && mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
816                         if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
817                                 dm_queue_if_no_path(mpp->alias, 0);
818                         else
819                                 dm_queue_if_no_path(mpp->alias, 1);
820                 }
821
822 next:
823                 drop_multipath(curmp, mpp->wwid, KEEP_PATHS);
824                 free_multipath(mpp, KEEP_PATHS);
825         }
826         /*
827          * Flush maps with only dead paths (ie not in sysfs)
828          * Keep maps with only failed paths
829          */
830         vector_foreach_slot (curmp, mpp, i) {
831                 if (!deadmap(mpp))
832                         continue;
833
834                 if (dm_flush_map(mpp->alias, DEFAULT_TARGET))
835                         condlog(2, "remove: %s (dead) failed!",
836                                 mpp->alias);
837                 else
838                         condlog(2, "remove: %s (dead)", mpp->alias);
839         }
840         return 0;
841 }
842
843 static void
844 usage (char * progname)
845 {
846         fprintf (stderr, VERSION_STRING);
847         fprintf (stderr, "Usage: %s\t[-v level] [-d] [-l|-ll|-f|-F]\n",
848                 progname);
849         fprintf (stderr,
850                 "\t\t\t[-p failover|multibus|group_by_serial|group_by_prio]\n" \
851                 "\t\t\t[device]\n" \
852                 "\n" \
853                 "\t-v level\tverbosity level\n" \
854                 "\t   0\t\t\tno output\n" \
855                 "\t   1\t\t\tprint created devmap names only\n" \
856                 "\t   2\t\t\tdefault verbosity\n" \
857                 "\t   3\t\t\tprint debug information\n" \
858                 "\t-b file\t\tbindings file location\n" \
859                 "\t-d\t\tdry run, do not create or update devmaps\n" \
860                 "\t-l\t\tshow multipath topology (sysfs and DM info)\n" \
861                 "\t-ll\t\tshow multipath topology (maximum info)\n" \
862                 "\t-f\t\tflush a multipath device map\n" \
863                 "\t-F\t\tflush all multipath device maps\n" \
864                 "\t-p policy\tforce all maps to specified policy :\n" \
865                 "\t   failover\t\t1 path per priority group\n" \
866                 "\t   multibus\t\tall paths in 1 priority group\n" \
867                 "\t   group_by_serial\t1 priority group per serial\n" \
868                 "\t   group_by_prio\t1 priority group per priority lvl\n" \
869                 "\t   group_by_node_name\t1 priority group per target node\n" \
870                 "\n" \
871                 "\tdevice\t\tlimit scope to the device's multipath\n" \
872                 "\t\t\t(udev-style $DEVNAME reference, eg /dev/sdb\n" \
873                 "\t\t\tor major:minor or a device map name)\n" \
874                 );
875
876         exit(1);
877 }
878
879 static int
880 update_paths (struct multipath * mpp)
881 {
882         int i, j;
883         struct pathgroup * pgp;
884         struct path * pp;
885
886         if (!mpp->pg)
887                 return 0;
888
889         vector_foreach_slot (mpp->pg, pgp, i) {
890                 if (!pgp->paths)
891                         continue;
892
893                 vector_foreach_slot (pgp->paths, pp, j) {
894                         if (!strlen(pp->dev)) {
895                                 if (devt2devname(pp->dev, pp->dev_t)) {
896                                         /*
897                                          * path is not in sysfs anymore
898                                          */
899                                         pp->state = PATH_DOWN;
900                                         continue;
901                                 }
902                                 pathinfo(pp, conf->hwtable, DI_ALL);
903                                 continue;
904                         }
905                         if (pp->state == PATH_UNCHECKED)
906                                 pathinfo(pp, conf->hwtable, DI_CHECKER);
907
908                         if (!pp->priority)
909                                 pathinfo(pp, conf->hwtable, DI_PRIO);
910                 }
911         }
912         return 0;
913 }
914
915 static int
916 get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
917 {
918         int i;
919         struct multipath * mpp;
920
921         if (dm_get_maps(curmp, DEFAULT_TARGET))
922                 return 1;
923
924         vector_foreach_slot (curmp, mpp, i) {
925                 /*
926                  * discard out of scope maps
927                  */
928                 if (mpp->wwid && refwwid &&
929                     strncmp(mpp->wwid, refwwid, WWID_SIZE)) {
930                         condlog(3, "skip map %s: out of scope", mpp->alias);
931                         free_multipath(mpp, KEEP_PATHS);
932                         vector_del_slot(curmp, i);
933                         i--;
934                         continue;
935                 }
936
937                 condlog(3, "params = %s", mpp->params);
938                 condlog(3, "status = %s", mpp->status);
939
940                 disassemble_map(pathvec, mpp->params, mpp);
941
942                 /*
943                  * disassemble_map() can add new paths to pathvec.
944                  * If not in "fast list mode", we need to fetch information
945                  * about them
946                  */
947                 if (conf->list != 1)
948                         update_paths(mpp);
949
950                 if (conf->list > 1)
951                         mpp->bestpg = select_path_group(mpp);
952
953                 disassemble_status(mpp->status, mpp);
954
955                 if (conf->list)
956                         print_mp(mpp);
957
958                 if (!conf->dry_run)
959                         reinstate_paths(mpp);
960         }
961         return 0;
962 }
963
964
965 /*
966  * Return value:
967  *  -1: Retry
968  *   0: Success
969  *   1: Failure
970  */
971 static int
972 configure (void)
973 {
974         vector curmp = NULL;
975         vector pathvec = NULL;
976         int r = 1;
977         int di_flag = 0;
978         char * refwwid = NULL;
979         char * dev = NULL;
980
981         /*
982          * allocate core vectors to store paths and multipaths
983          */
984         curmp = vector_alloc();
985         pathvec = vector_alloc();
986
987         if (!curmp || !pathvec) {
988                 condlog(0, "can not allocate memory");
989                 goto out;
990         }
991
992         /*
993          * if we have a blacklisted device parameter, exit early
994          */
995         if (conf->dev) {
996                 if (!strncmp(conf->dev, "/dev/", 5) &&
997                     strlen(conf->dev) > 5)
998                         dev = conf->dev + 5;
999                 else
1000                         dev = conf->dev;
1001         }
1002         
1003         if (dev && blacklist(conf->blist, dev))
1004                 goto out;
1005         
1006         condlog(3, "load path identifiers cache");
1007         cache_load(pathvec);
1008
1009         if (conf->verbosity > 2)
1010                 print_all_paths(pathvec, 1);
1011
1012         /*
1013          * scope limiting must be translated into a wwid
1014          * failing the translation is fatal (by policy)
1015          */
1016         if (conf->dev) {
1017                 refwwid = get_refwwid(pathvec);
1018
1019                 if (!refwwid) {
1020                         condlog(3, "scope is nul");
1021                         goto out;
1022                 }
1023                 condlog(3, "scope limited to %s", refwwid);
1024         }
1025
1026         /*
1027          * get a path list
1028          */
1029         if (conf->dev)
1030                 di_flag = DI_WWID;
1031
1032         if (conf->list > 1)
1033                 /* extended path info '-ll' */
1034                 di_flag |= DI_SYSFS | DI_CHECKER;
1035         else if (conf->list)
1036                 /* minimum path info '-l' */
1037                 di_flag |= DI_SYSFS;
1038         else
1039                 /* maximum info */
1040                 di_flag = DI_ALL;
1041
1042         if (path_discovery(pathvec, conf, di_flag))
1043                 goto out;
1044
1045         if (conf->verbosity > 2)
1046                 print_all_paths(pathvec, 1);
1047
1048         get_path_layout(&pl, pathvec);
1049
1050         if (get_dm_mpvec(curmp, pathvec, refwwid))
1051                 goto out;
1052
1053         filter_pathvec(pathvec, refwwid);
1054
1055         if (conf->list)
1056                 goto out;
1057
1058         /*
1059          * core logic entry point
1060          */
1061         r = coalesce_paths(curmp, pathvec);
1062
1063 out:
1064         if (refwwid)
1065                 FREE(refwwid);
1066
1067         free_multipathvec(curmp, KEEP_PATHS);
1068         free_pathvec(pathvec, FREE_PATHS);
1069
1070         return r;
1071 }
1072
1073 int
1074 main (int argc, char *argv[])
1075 {
1076         int arg;
1077         extern char *optarg;
1078         extern int optind;
1079         int i, r;
1080
1081         if (getuid() != 0) {
1082                 fprintf(stderr, "need to be root\n");
1083                 exit(1);
1084         }
1085
1086         if (dm_prereq(DEFAULT_TARGET, 1, 0, 3))
1087                 exit(1);
1088
1089         if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
1090                 condlog(0, "multipath tools need sysfs mounted");
1091                 exit(1);
1092         }
1093         if (load_config(DEFAULT_CONFIGFILE))
1094                 exit(1);
1095
1096         while ((arg = getopt(argc, argv, ":qdl::Ffi:M:v:p:b:")) != EOF ) {
1097                 switch(arg) {
1098                 case 1: printf("optarg : %s\n",optarg);
1099                         break;
1100                 case 'v':
1101                         if (sizeof(optarg) > sizeof(char *) ||
1102                             !isdigit(optarg[0]))
1103                                 usage (argv[0]);
1104
1105                         conf->verbosity = atoi(optarg);
1106                         break;
1107                 case 'b':
1108                         conf->bindings_file = optarg;
1109                         break;
1110                 case 'd':
1111                         conf->dry_run = 1;
1112                         break;
1113                 case 'f':
1114                         conf->remove = FLUSH_ONE;
1115                         break;
1116                 case 'F':
1117                         conf->remove = FLUSH_ALL;
1118                         break;
1119                 case 'l':
1120                         conf->list = 1;
1121                         conf->dry_run = 1;
1122
1123                         if (optarg && !strncmp(optarg, "l", 1))
1124                                 conf->list++;
1125
1126                         break;
1127                 case 'M':
1128 #if _DEBUG_
1129                         debug = atoi(optarg);
1130 #endif
1131                         break;
1132                 case 'p':
1133                         conf->pgpolicy_flag = get_pgpolicy_id(optarg);
1134                         if (conf->pgpolicy_flag == -1) {
1135                                 printf("'%s' is not a valid policy\n", optarg);
1136                                 usage(argv[0]);
1137                         }                
1138                         break;
1139                 case ':':
1140                         fprintf(stderr, "Missing option arguement\n");
1141                         usage(argv[0]);        
1142                 case '?':
1143                         fprintf(stderr, "Unknown switch: %s\n", optarg);
1144                         usage(argv[0]);
1145                 default:
1146                         usage(argv[0]);
1147                 }
1148         }        
1149         if (optind < argc) {
1150                 conf->dev = MALLOC(FILE_NAME_SIZE);
1151
1152                 if (!conf->dev)
1153                         goto out;
1154
1155                 strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
1156
1157                 if (filepresent(conf->dev))
1158                         conf->dev_type = DEV_DEVNODE;
1159                 else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
1160                         conf->dev_type = DEV_DEVT;
1161                 else
1162                         conf->dev_type = DEV_DEVMAP;
1163
1164         }
1165
1166         if (conf->remove == FLUSH_ONE) {
1167                 if (conf->dev_type == DEV_DEVMAP)
1168                         dm_flush_map(conf->dev, DEFAULT_TARGET);
1169                 else
1170                         condlog(0, "must provide a map name to remove");
1171
1172                 goto out;
1173         }
1174         else if (conf->remove == FLUSH_ALL) {
1175                 dm_flush_maps(DEFAULT_TARGET);
1176                 goto out;
1177         }
1178         while ((r = configure()) < 0)
1179                 condlog(3, "restart multipath configuration process");
1180         
1181 out:
1182         free_config(conf);
1183         dm_lib_release();
1184         dm_lib_exit();
1185 #ifdef _DEBUG_
1186         dbg_free_final(NULL);
1187 #endif
1188         return r;
1189 }