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:\n");
79 fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
80 fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
81 fprintf (stderr, " %s -F [-v lvl]\n", progname);
82 fprintf (stderr, " %s -h\n", progname);
86 " -h print this usage text\n" \
87 " -l show multipath topology (sysfs and DM info)\n" \
88 " -ll show multipath topology (maximum info)\n" \
89 " -f flush a multipath device map\n" \
90 " -F flush all multipath device maps\n" \
91 " -d dry run, do not create or update devmaps\n" \
92 " -r force devmap reload\n" \
93 " -p policy failover|multibus|group_by_serial|group_by_prio\n" \
94 " -b fil bindings file location\n" \
95 " -p pol force all maps to specified path grouping policy :\n" \
96 " . failover one path per priority group\n" \
97 " . multibus all paths in one priority group\n" \
98 " . group_by_serial one priority group per serial\n" \
99 " . group_by_prio one priority group per priority lvl\n" \
100 " . group_by_node_name one priority group per target node\n" \
101 " -v lvl verbosity level\n" \
103 " . 1 print created devmap names only\n" \
104 " . 2 default verbosity\n" \
105 " . 3 print debug information\n" \
106 " dev action limited to:\n" \
107 " . multipath named 'dev' (ex: mpath0) or\n" \
108 " . multipath whose wwid is 'dev' (ex: 60051..)\n" \
109 " . multipath including the path named 'dev' (ex: /dev/sda)\n" \
110 " . multipath including the path with maj:min 'dev' (ex: 8:0)\n" \
117 update_paths (struct multipath * mpp)
120 struct pathgroup * pgp;
126 vector_foreach_slot (mpp->pg, pgp, i) {
130 vector_foreach_slot (pgp->paths, pp, j) {
131 if (!strlen(pp->dev)) {
132 if (devt2devname(pp->dev, pp->dev_t)) {
134 * path is not in sysfs anymore
136 pp->state = PATH_DOWN;
140 pathinfo(pp, conf->hwtable, DI_ALL);
144 if (pp->state == PATH_UNCHECKED ||
145 pp->state == PATH_WILD)
146 pathinfo(pp, conf->hwtable, DI_CHECKER);
148 if (pp->priority == PRIO_UNDEF)
149 pathinfo(pp, conf->hwtable, DI_PRIO);
156 get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
159 struct multipath * mpp;
161 if (dm_get_maps(curmp))
164 vector_foreach_slot (curmp, mpp, i) {
166 * discard out of scope maps
168 if (mpp->wwid && refwwid &&
169 strncmp(mpp->wwid, refwwid, WWID_SIZE)) {
170 condlog(3, "skip map %s: out of scope", mpp->alias);
171 free_multipath(mpp, KEEP_PATHS);
172 vector_del_slot(curmp, i);
177 condlog(3, "params = %s", mpp->params);
178 condlog(3, "status = %s", mpp->status);
180 disassemble_map(pathvec, mpp->params, mpp);
183 * disassemble_map() can add new paths to pathvec.
184 * If not in "fast list mode", we need to fetch information
191 mpp->bestpg = select_path_group(mpp);
193 disassemble_status(mpp->status, mpp);
196 print_multipath_topology(mpp, conf->verbosity);
199 reinstate_paths(mpp);
215 vector pathvec = NULL;
219 char * refwwid = NULL;
223 * allocate core vectors to store paths and multipaths
225 curmp = vector_alloc();
226 pathvec = vector_alloc();
228 if (!curmp || !pathvec) {
229 condlog(0, "can not allocate memory");
232 vecs.pathvec = pathvec;
236 * dev is "/dev/" . "sysfs block dev"
239 if (!strncmp(conf->dev, "/dev/", 5) &&
240 strlen(conf->dev) > 5)
247 * if we have a blacklisted device parameter, exit early
250 (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
254 * scope limiting must be translated into a wwid
255 * failing the translation is fatal (by policy)
258 refwwid = get_refwwid(conf->dev, conf->dev_type, pathvec);
261 condlog(3, "scope is nul");
264 condlog(3, "scope limited to %s", refwwid);
265 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
277 /* extended path info '-ll' */
278 di_flag |= DI_SYSFS | DI_CHECKER;
280 /* minimum path info '-l' */
286 if (path_discovery(pathvec, conf, di_flag))
289 if (conf->verbosity > 2)
290 print_all_paths(pathvec, 1);
292 get_path_layout(pathvec, 0);
294 if (get_dm_mpvec(curmp, pathvec, refwwid))
297 filter_pathvec(pathvec, refwwid);
305 * core logic entry point
307 r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
313 free_multipathvec(curmp, KEEP_PATHS);
314 free_pathvec(pathvec, FREE_PATHS);
320 main (int argc, char *argv[])
328 fprintf(stderr, "need to be root\n");
335 if (load_config(DEFAULT_CONFIGFILE))
338 if (init_checkers()) {
339 condlog(0, "failed to initialize checkers");
343 condlog(0, "failed to initialize prioritizers");
346 if (sysfs_init(conf->sysfs_dir, FILE_NAME_SIZE)) {
347 condlog(0, "multipath tools need sysfs mounted");
350 while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) {
352 case 1: printf("optarg : %s\n",optarg);
355 if (sizeof(optarg) > sizeof(char *) ||
359 conf->verbosity = atoi(optarg);
362 conf->bindings_file = optarg;
368 conf->remove = FLUSH_ONE;
371 conf->remove = FLUSH_ALL;
377 if (optarg && !strncmp(optarg, "l", 1))
383 debug = atoi(optarg);
387 conf->pgpolicy_flag = get_pgpolicy_id(optarg);
388 if (conf->pgpolicy_flag == -1) {
389 printf("'%s' is not a valid policy\n", optarg);
394 conf->force_reload = 1;
399 fprintf(stderr, "Missing option arguement\n");
402 fprintf(stderr, "Unknown switch: %s\n", optarg);
409 conf->dev = MALLOC(FILE_NAME_SIZE);
414 strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
416 if (filepresent(conf->dev))
417 conf->dev_type = DEV_DEVNODE;
418 else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
419 conf->dev_type = DEV_DEVT;
421 conf->dev_type = DEV_DEVMAP;
426 if (conf->remove == FLUSH_ONE) {
427 if (conf->dev_type == DEV_DEVMAP)
428 r = dm_flush_map(conf->dev);
430 condlog(0, "must provide a map name to remove");
434 else if (conf->remove == FLUSH_ALL) {
438 while ((r = configure()) < 0)
439 condlog(3, "restart multipath configuration process");
450 * Freeing config must be done after dm_lib_exit(), because
451 * the logging function (dm_write_log()), which is called there,
452 * references the config.
458 dbg_free_final(NULL);