2 * Soft: multipath device mapper target autoconfig
4 * Version: $Id: main.h,v 0.0.1 2003/09/18 15:13:38 cvaroqui Exp $
6 * Author: Christophe Varoqui
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.
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.
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
35 #include <libdevmapper.h>
36 #include <devmapper.h>
38 #include <path_state.h>
39 #include <blacklist.h>
48 #include <discovery.h>
50 #include <switchgroup.h>
51 #include <sysfs/libsysfs.h>
56 #include "pgpolicies.h"
59 /* for column aligned output */
60 struct path_layout pl;
63 get_refwwid (vector pathvec)
66 char buff[FILE_NAME_SIZE];
69 if (conf->dev_type == DEV_NONE)
72 if (conf->dev_type == DEV_DEVNODE) {
73 basename(conf->dev, buff);
74 pp = find_path_by_dev(pathvec, buff);
82 strncpy(pp->dev, buff, FILE_NAME_SIZE);
84 if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
87 if (store_path(pathvec, pp)) {
96 if (conf->dev_type == DEV_DEVT) {
97 pp = find_path_by_devt(pathvec, conf->dev);
100 if (devt2devname(buff, conf->dev))
108 strncpy(pp->dev, buff, FILE_NAME_SIZE);
110 if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
113 if (store_path(pathvec, pp)) {
121 if (conf->dev_type == DEV_DEVMAP) {
125 refwwid = get_user_friendly_wwid(conf->dev,
126 conf->bindings_file);
134 refwwid = get_mpe_wwid(conf->dev);
143 if (refwwid && strlen(refwwid))
144 return STRDUP(refwwid);
150 print_path (struct path * pp, char * style)
152 char line[MAX_LINE_LEN];
154 snprint_path(&line[0], MAX_LINE_LEN, style, pp, &pl);
159 print_map (struct multipath * mpp)
161 if (mpp->size && mpp->params)
162 printf("0 %llu %s %s\n",
163 mpp->size, DEFAULT_TARGET, mpp->params);
168 print_all_paths (vector pathvec, int banner)
172 char line[MAX_LINE_LEN];
174 if (!VECTOR_SIZE(pathvec)) {
176 fprintf(stdout, "===== no paths =====\n");
181 fprintf(stdout, "===== paths list =====\n");
183 get_path_layout(&pl, pathvec);
184 snprint_path_header(line, MAX_LINE_LEN, PRINT_PATH_LONG, &pl);
185 fprintf(stdout, "%s", line);
187 vector_foreach_slot (pathvec, pp, i)
188 print_path(pp, PRINT_PATH_LONG);
192 print_mp (struct multipath * mpp)
195 struct path * pp = NULL;
196 struct pathgroup * pgp = NULL;
198 if (mpp->action == ACT_NOTHING || !conf->verbosity || !mpp->size)
201 if (conf->verbosity > 1) {
202 switch (mpp->action) {
204 printf("%s: ", ACT_RELOAD_STR);
208 printf("%s: ", ACT_CREATE_STR);
212 printf("%s: ", ACT_SWITCHPG_STR);
221 printf("%s", mpp->alias);
223 if (conf->verbosity == 1) {
227 if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE))
228 printf(" (%s)", mpp->wwid);
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);
239 printf("[size=%llu TB]", mpp->size >> 31);
242 printf("[features=\"%s\"]", mpp->features);
245 printf("[hwhandler=\"%s\"]", mpp->hwhandler);
247 fprintf(stdout, "\n");
252 vector_foreach_slot (mpp->pg, pgp, j) {
256 printf("%s ", mpp->selector);
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--)
265 printf("[prio=%i]", pgp->priority);
267 switch (pgp->status) {
268 case PGSTATE_ENABLED:
271 case PGSTATE_DISABLED:
272 printf("[disabled]");
282 vector_foreach_slot (pgp->paths, pp, i)
283 print_path(pp, PRINT_PATH_INDENT);
289 filter_pathvec (vector pathvec, char * refwwid)
294 if (!refwwid || !strlen(refwwid))
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);
301 vector_del_slot(pathvec, i);
309 * Transforms the path group vector into a proper device map string
312 assemble_map (struct multipath * mp)
318 struct pathgroup * pgp;
323 freechar = sizeof(mp->params);
325 shift = snprintf(p, freechar, "%s %s %i %i",
326 mp->features, mp->hwhandler,
327 VECTOR_SIZE(mp->pg), mp->bestpg);
329 if (shift >= freechar) {
330 fprintf(stderr, "mp->params too small\n");
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");
347 vector_foreach_slot (pgp->paths, pp, j) {
348 if (mp->rr_weight == RR_WEIGHT_PRIO && pp->priority)
349 minio *= pp->priority;
351 shift = snprintf(p, freechar, " %s %d",
353 if (shift >= freechar) {
354 fprintf(stderr, "mp->params too small\n");
362 fprintf(stderr, "mp->params too small\n");
365 snprintf(p, 1, "\n");
367 if (conf->verbosity > 2)
374 setup_map (struct multipath * mpp)
377 * don't bother if devmap size is unknown
379 if (mpp->size <= 0) {
380 condlog(3, "%s devmap size is unknown", mpp->alias);
385 * properties selectors
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);
396 * apply selected grouping policy to valid paths
398 switch (mpp->pgpolicy) {
403 one_path_per_group(mpp);
405 case GROUP_BY_SERIAL:
406 group_by_serial(mpp);
411 case GROUP_BY_NODE_NAME:
412 group_by_node_name(mpp);
418 if (mpp->pg == NULL) {
419 condlog(3, "pgpolicy failed to produce a pg vector");
424 * ponders each path group and determine highest prio pg
425 * to switch over (default to first)
427 mpp->bestpg = select_path_group(mpp);
430 * transform the mp->pg vector of vectors of paths
431 * into a mp->params strings to feed the device-mapper
433 if (assemble_map(mpp)) {
434 condlog(3, "problem assembing map");
441 pathcount (struct multipath * mpp, int state)
443 struct pathgroup *pgp;
448 vector_foreach_slot (mpp->pg, pgp, i)
449 vector_foreach_slot (pgp->paths, pp, j)
450 if (pp->state == state)
456 compute_pgid(struct pathgroup * pgp)
461 vector_foreach_slot (pgp->paths, pp, i)
466 pgcmp (struct multipath * mpp, struct multipath * cmpp)
469 struct pathgroup * pgp;
470 struct pathgroup * cpgp;
473 vector_foreach_slot (mpp->pg, pgp, i) {
476 vector_foreach_slot (cmpp->pg, cpgp, j) {
477 if (pgp->id == cpgp->id) {
490 select_action (struct multipath * mpp, vector curmp)
492 struct multipath * cmpp;
494 cmpp = find_mp_by_alias(curmp, mpp->alias);
497 cmpp = find_mp_by_wwid(curmp, mpp->wwid);
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);
504 mpp->action = ACT_CREATE;
505 condlog(3, "set ACT_CREATE: map does not exists");
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");
519 if (pathcount(mpp, PATH_UP) == 0) {
520 mpp->action = ACT_NOTHING;
521 condlog(3, "set ACT_NOTHING: no usable path");
524 if (cmpp->size != mpp->size) {
525 mpp->action = ACT_RELOAD;
526 condlog(3, "set ACT_RELOAD: size change");
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");
535 if (strncmp(cmpp->hwhandler, mpp->hwhandler,
536 strlen(mpp->hwhandler))) {
537 mpp->action = ACT_RELOAD;
538 condlog(3, "set ACT_RELOAD: hwhandler change");
541 if (strncmp(cmpp->selector, mpp->selector,
542 strlen(mpp->selector))) {
543 mpp->action = ACT_RELOAD;
544 condlog(3, "set ACT_RELOAD: selector change");
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);
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");
558 if (pgcmp(mpp, cmpp)) {
559 mpp->action = ACT_RELOAD;
560 condlog(3, "set ACT_RELOAD: path group topology change");
563 if (cmpp->nextpg != mpp->bestpg) {
564 mpp->action = ACT_SWITCHPG;
565 condlog(3, "set ACT_SWITCHPG: next path group change");
568 mpp->action = ACT_NOTHING;
569 condlog(3, "set ACT_NOTHING: map unchanged");
574 reinstate_paths (struct multipath * mpp)
577 struct pathgroup * pgp;
583 vector_foreach_slot (mpp->pg, pgp, i) {
587 vector_foreach_slot (pgp->paths, pp, j) {
588 if (pp->state != PATH_UP &&
589 (pgp->status == PGSTATE_DISABLED ||
590 pgp->status == PGSTATE_ACTIVE))
593 if (pp->dmstate == PSTATE_FAILED) {
594 if (dm_reinstate_path(mpp->alias, pp->dev_t))
595 condlog(0, "error reinstating %s",
603 int lock_multipath (struct multipath * mpp, int lock)
605 struct pathgroup * pgp;
609 if (!mpp || !mpp->pg)
612 vector_foreach_slot (mpp->pg, pgp, i) {
615 vector_foreach_slot(pgp->paths, pp, j) {
616 if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
617 errno == EWOULDBLOCK)
620 flock(pp->fd, LOCK_UN);
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.
634 domap (struct multipath * mpp)
639 * last chance to quit before touching the devmaps
646 switch (mpp->action) {
651 dm_switchgroup(mpp->alias, mpp->bestpg);
653 * we may have avoided reinstating paths because there where in
654 * active or disabled PG. Now that the topology has changed,
657 reinstate_paths(mpp);
661 if (lock_multipath(mpp, 1)) {
662 condlog(3, "%s: in use", mpp->alias);
667 if (dm_map_present(mpp->alias))
670 r = dm_addmap(DM_DEVICE_CREATE, mpp->alias, DEFAULT_TARGET,
671 mpp->params, mpp->size, mpp->wwid);
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.
678 if (!r && dm_map_present(mpp->alias)) {
679 condlog(3, "%s: failed to load map "
680 "(a path might be in use)",
682 dm_flush_map(mpp->alias, NULL);
685 lock_multipath(mpp, 0);
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));
701 * DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded
703 dm_switchgroup(mpp->alias, mpp->bestpg);
711 deadmap (struct multipath * mpp)
714 struct pathgroup * pgp;
720 vector_foreach_slot (mpp->pg, pgp, i) {
724 vector_foreach_slot (pgp->paths, pp, j)
726 return 0; /* alive */
733 coalesce_paths (vector curmp, vector pathvec)
737 char empty_buff[WWID_SIZE];
738 struct multipath * mpp;
742 memset(empty_buff, 0, WWID_SIZE);
744 vector_foreach_slot (pathvec, pp1, k) {
745 /* skip this path for some reason */
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))
752 /* 2. if path already coalesced */
757 * at this point, we know we really got a new mp
759 mpp = alloc_multipath();
764 mpp->mpe = find_mpe(pp1->wwid);
766 strcpy(mpp->wwid, pp1->wwid);
770 mpp->size = pp1->size;
771 mpp->paths = vector_alloc();
773 if (pp1->priority < 0)
774 mpp->action = ACT_NOTHING;
779 if (store_path(mpp->paths, pp1))
782 for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
783 pp2 = VECTOR_SLOT(pathvec, i);
785 if (strcmp(pp1->wwid, pp2->wwid))
790 if (pp2->size != mpp->size) {
792 * ouch, avoid feeding that to the DM
794 condlog(3, "path size mismatch : discard %s",
796 mpp->action = ACT_NOTHING;
798 if (pp2->priority < 0)
799 mpp->action = ACT_NOTHING;
801 if (store_path(mpp->paths, pp2))
807 if (mpp->action == ACT_UNDEF)
808 select_action(mpp, curmp);
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);
819 dm_queue_if_no_path(mpp->alias, 1);
823 drop_multipath(curmp, mpp->wwid, KEEP_PATHS);
824 free_multipath(mpp, KEEP_PATHS);
827 * Flush maps with only dead paths (ie not in sysfs)
828 * Keep maps with only failed paths
830 vector_foreach_slot (curmp, mpp, i) {
834 if (dm_flush_map(mpp->alias, DEFAULT_TARGET))
835 condlog(2, "remove: %s (dead) failed!",
838 condlog(2, "remove: %s (dead)", mpp->alias);
844 usage (char * progname)
846 fprintf (stderr, VERSION_STRING);
847 fprintf (stderr, "Usage: %s\t[-v level] [-d] [-l|-ll|-f|-F]\n",
850 "\t\t\t[-p failover|multibus|group_by_serial|group_by_prio]\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" \
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" \
880 update_paths (struct multipath * mpp)
883 struct pathgroup * pgp;
889 vector_foreach_slot (mpp->pg, pgp, i) {
893 vector_foreach_slot (pgp->paths, pp, j) {
894 if (!strlen(pp->dev)) {
895 if (devt2devname(pp->dev, pp->dev_t)) {
897 * path is not in sysfs anymore
899 pp->state = PATH_DOWN;
902 pathinfo(pp, conf->hwtable, DI_ALL);
905 if (pp->state == PATH_UNCHECKED)
906 pathinfo(pp, conf->hwtable, DI_CHECKER);
909 pathinfo(pp, conf->hwtable, DI_PRIO);
916 get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
919 struct multipath * mpp;
921 if (dm_get_maps(curmp, DEFAULT_TARGET))
924 vector_foreach_slot (curmp, mpp, i) {
926 * discard out of scope maps
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);
937 condlog(3, "params = %s", mpp->params);
938 condlog(3, "status = %s", mpp->status);
940 disassemble_map(pathvec, mpp->params, mpp);
943 * disassemble_map() can add new paths to pathvec.
944 * If not in "fast list mode", we need to fetch information
951 mpp->bestpg = select_path_group(mpp);
953 disassemble_status(mpp->status, mpp);
959 reinstate_paths(mpp);
975 vector pathvec = NULL;
978 char * refwwid = NULL;
982 * allocate core vectors to store paths and multipaths
984 curmp = vector_alloc();
985 pathvec = vector_alloc();
987 if (!curmp || !pathvec) {
988 condlog(0, "can not allocate memory");
993 * if we have a blacklisted device parameter, exit early
996 if (!strncmp(conf->dev, "/dev/", 5) &&
997 strlen(conf->dev) > 5)
1003 if (dev && blacklist(conf->blist, dev))
1006 condlog(3, "load path identifiers cache");
1007 cache_load(pathvec);
1009 if (conf->verbosity > 2)
1010 print_all_paths(pathvec, 1);
1013 * scope limiting must be translated into a wwid
1014 * failing the translation is fatal (by policy)
1017 refwwid = get_refwwid(pathvec);
1020 condlog(3, "scope is nul");
1023 condlog(3, "scope limited to %s", refwwid);
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;
1042 if (path_discovery(pathvec, conf, di_flag))
1045 if (conf->verbosity > 2)
1046 print_all_paths(pathvec, 1);
1048 get_path_layout(&pl, pathvec);
1050 if (get_dm_mpvec(curmp, pathvec, refwwid))
1053 filter_pathvec(pathvec, refwwid);
1059 * core logic entry point
1061 r = coalesce_paths(curmp, pathvec);
1067 free_multipathvec(curmp, KEEP_PATHS);
1068 free_pathvec(pathvec, FREE_PATHS);
1074 main (int argc, char *argv[])
1077 extern char *optarg;
1081 if (getuid() != 0) {
1082 fprintf(stderr, "need to be root\n");
1086 if (dm_prereq(DEFAULT_TARGET, 1, 0, 3))
1089 if (sysfs_get_mnt_path(sysfs_path, FILE_NAME_SIZE)) {
1090 condlog(0, "multipath tools need sysfs mounted");
1093 if (load_config(DEFAULT_CONFIGFILE))
1096 while ((arg = getopt(argc, argv, ":qdl::Ffi:M:v:p:b:")) != EOF ) {
1098 case 1: printf("optarg : %s\n",optarg);
1101 if (sizeof(optarg) > sizeof(char *) ||
1102 !isdigit(optarg[0]))
1105 conf->verbosity = atoi(optarg);
1108 conf->bindings_file = optarg;
1114 conf->remove = FLUSH_ONE;
1117 conf->remove = FLUSH_ALL;
1123 if (optarg && !strncmp(optarg, "l", 1))
1129 debug = atoi(optarg);
1133 conf->pgpolicy_flag = get_pgpolicy_id(optarg);
1134 if (conf->pgpolicy_flag == -1) {
1135 printf("'%s' is not a valid policy\n", optarg);
1140 fprintf(stderr, "Missing option arguement\n");
1143 fprintf(stderr, "Unknown switch: %s\n", optarg);
1149 if (optind < argc) {
1150 conf->dev = MALLOC(FILE_NAME_SIZE);
1155 strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
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;
1162 conf->dev_type = DEV_DEVMAP;
1166 if (conf->remove == FLUSH_ONE) {
1167 if (conf->dev_type == DEV_DEVMAP)
1168 dm_flush_map(conf->dev, DEFAULT_TARGET);
1170 condlog(0, "must provide a map name to remove");
1174 else if (conf->remove == FLUSH_ALL) {
1175 dm_flush_maps(DEFAULT_TARGET);
1178 while ((r = configure()) < 0)
1179 condlog(3, "restart multipath configuration process");
1186 dbg_free_final(NULL);