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
33 #include <libdevmapper.h>
34 #include <devmapper.h>
38 #include <structs_vec.h>
42 #include <blacklist.h>
43 #include <discovery.h>
45 #include <switchgroup.h>
48 #include <configure.h>
49 #include <pgpolicies.h>
55 filter_pathvec (vector pathvec, char * refwwid)
60 if (!refwwid || !strlen(refwwid))
63 vector_foreach_slot (pathvec, pp, i) {
64 if (strncmp(pp->wwid, refwwid, WWID_SIZE) != 0) {
65 condlog(3, "skip path %s : out of scope", pp->dev);
67 vector_del_slot(pathvec, i);
75 usage (char * progname)
77 fprintf (stderr, VERSION_STRING);
78 fprintf (stderr, "Usage: %s\t[-v level] [-d] [-h|-l|-ll|-f|-F]\n",
81 "\t\t\t[-p failover|multibus|group_by_serial|group_by_prio]\n" \
84 "\t-v level\tverbosity level\n" \
85 "\t 0\t\t\tno output\n" \
86 "\t 1\t\t\tprint created devmap names only\n" \
87 "\t 2\t\t\tdefault verbosity\n" \
88 "\t 3\t\t\tprint debug information\n" \
89 "\t-h\t\tprint this usage text\n" \
90 "\t-b file\t\tbindings file location\n" \
91 "\t-d\t\tdry run, do not create or update devmaps\n" \
92 "\t-l\t\tshow multipath topology (sysfs and DM info)\n" \
93 "\t-ll\t\tshow multipath topology (maximum info)\n" \
94 "\t-f\t\tflush a multipath device map\n" \
95 "\t-F\t\tflush all multipath device maps\n" \
96 "\t-p policy\tforce all maps to specified policy :\n" \
97 "\t failover\t\t1 path per priority group\n" \
98 "\t multibus\t\tall paths in 1 priority group\n" \
99 "\t group_by_serial\t1 priority group per serial\n" \
100 "\t group_by_prio\t1 priority group per priority lvl\n" \
101 "\t group_by_node_name\t1 priority group per target node\n" \
103 "\tdevice\t\tlimit scope to the device's multipath\n" \
104 "\t\t\t(udev-style $DEVNAME reference, eg /dev/sdb\n" \
105 "\t\t\tor major:minor or a device map name)\n" \
112 update_paths (struct multipath * mpp)
115 struct pathgroup * pgp;
121 vector_foreach_slot (mpp->pg, pgp, i) {
125 vector_foreach_slot (pgp->paths, pp, j) {
126 if (!strlen(pp->dev)) {
127 if (devt2devname(pp->dev, pp->dev_t)) {
129 * path is not in sysfs anymore
131 pp->state = PATH_DOWN;
135 pathinfo(pp, conf->hwtable, DI_ALL);
139 if (pp->state == PATH_UNCHECKED)
140 pathinfo(pp, conf->hwtable, DI_CHECKER);
142 if (pp->priority == PRIO_UNDEF)
143 pathinfo(pp, conf->hwtable, DI_PRIO);
150 get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
153 struct multipath * mpp;
155 if (dm_get_maps(curmp, DEFAULT_TARGET))
158 vector_foreach_slot (curmp, mpp, i) {
160 * discard out of scope maps
162 if (mpp->wwid && refwwid &&
163 strncmp(mpp->wwid, refwwid, WWID_SIZE)) {
164 condlog(3, "skip map %s: out of scope", mpp->alias);
165 free_multipath(mpp, KEEP_PATHS);
166 vector_del_slot(curmp, i);
171 condlog(3, "params = %s", mpp->params);
172 condlog(3, "status = %s", mpp->status);
174 disassemble_map(pathvec, mpp->params, mpp);
177 * disassemble_map() can add new paths to pathvec.
178 * If not in "fast list mode", we need to fetch information
185 mpp->bestpg = select_path_group(mpp);
187 disassemble_status(mpp->status, mpp);
190 print_multipath_topology(mpp, conf->verbosity);
193 reinstate_paths(mpp);
209 vector pathvec = NULL;
213 char * refwwid = NULL;
217 * allocate core vectors to store paths and multipaths
219 curmp = vector_alloc();
220 pathvec = vector_alloc();
222 if (!curmp || !pathvec) {
223 condlog(0, "can not allocate memory");
226 vecs.pathvec = pathvec;
230 * dev is "/dev/" . "sysfs block dev"
233 if (!strncmp(conf->dev, "/dev/", 5) &&
234 strlen(conf->dev) > 5)
241 * if we have a blacklisted device parameter, exit early
244 (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
248 * scope limiting must be translated into a wwid
249 * failing the translation is fatal (by policy)
252 refwwid = get_refwwid(conf->dev, conf->dev_type, pathvec);
255 condlog(3, "scope is nul");
258 condlog(3, "scope limited to %s", refwwid);
259 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
271 /* extended path info '-ll' */
272 di_flag |= DI_SYSFS | DI_CHECKER;
274 /* minimum path info '-l' */
280 if (path_discovery(pathvec, conf, di_flag))
283 if (conf->verbosity > 2)
284 print_all_paths(pathvec, 1);
286 get_path_layout(pathvec);
288 if (get_dm_mpvec(curmp, pathvec, refwwid))
291 filter_pathvec(pathvec, refwwid);
299 * core logic entry point
301 r = coalesce_paths(&vecs, NULL, NULL);
307 free_multipathvec(curmp, KEEP_PATHS);
308 free_pathvec(pathvec, FREE_PATHS);
314 main (int argc, char *argv[])
322 fprintf(stderr, "need to be root\n");
326 if (dm_prereq(DEFAULT_TARGET))
329 if (load_config(DEFAULT_CONFIGFILE))
332 if (init_checkers()) {
333 condlog(0, "failed to initialize checkers");
337 condlog(0, "failed to initialize prioritizers");
340 if (sysfs_init(conf->sysfs_dir, FILE_NAME_SIZE)) {
341 condlog(0, "multipath tools need sysfs mounted");
344 while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:")) != EOF ) {
346 case 1: printf("optarg : %s\n",optarg);
349 if (sizeof(optarg) > sizeof(char *) ||
353 conf->verbosity = atoi(optarg);
356 conf->bindings_file = optarg;
362 conf->remove = FLUSH_ONE;
365 conf->remove = FLUSH_ALL;
371 if (optarg && !strncmp(optarg, "l", 1))
377 debug = atoi(optarg);
381 conf->pgpolicy_flag = get_pgpolicy_id(optarg);
382 if (conf->pgpolicy_flag == -1) {
383 printf("'%s' is not a valid policy\n", optarg);
390 fprintf(stderr, "Missing option arguement\n");
393 fprintf(stderr, "Unknown switch: %s\n", optarg);
400 conf->dev = MALLOC(FILE_NAME_SIZE);
405 strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
407 if (filepresent(conf->dev))
408 conf->dev_type = DEV_DEVNODE;
409 else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
410 conf->dev_type = DEV_DEVT;
412 conf->dev_type = DEV_DEVMAP;
417 if (conf->remove == FLUSH_ONE) {
418 if (conf->dev_type == DEV_DEVMAP)
419 dm_flush_map(conf->dev, DEFAULT_TARGET);
421 condlog(0, "must provide a map name to remove");
425 else if (conf->remove == FLUSH_ALL) {
426 dm_flush_maps(DEFAULT_TARGET);
429 while ((r = configure()) < 0)
430 condlog(3, "restart multipath configuration process");
438 * Freeing config must be done after dm_lib_exit(), because
439 * the logging function (dm_write_log()), which is called there,
440 * references the config.
446 dbg_free_final(NULL);