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>
53 #include <sys/resource.h>
58 filter_pathvec (vector pathvec, char * refwwid)
63 if (!refwwid || !strlen(refwwid))
66 vector_foreach_slot (pathvec, pp, i) {
67 if (strncmp(pp->wwid, refwwid, WWID_SIZE) != 0) {
68 condlog(3, "skip path %s : out of scope", pp->dev);
70 vector_del_slot(pathvec, i);
78 usage (char * progname)
80 fprintf (stderr, VERSION_STRING);
81 fprintf (stderr, "Usage:\n");
82 fprintf (stderr, " %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
83 fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
84 fprintf (stderr, " %s -F [-v lvl]\n", progname);
85 fprintf (stderr, " %s -h\n", progname);
89 " -h print this usage text\n" \
90 " -l show multipath topology (sysfs and DM info)\n" \
91 " -ll show multipath topology (maximum info)\n" \
92 " -f flush a multipath device map\n" \
93 " -F flush all multipath device maps\n" \
94 " -d dry run, do not create or update devmaps\n" \
95 " -r force devmap reload\n" \
96 " -p policy failover|multibus|group_by_serial|group_by_prio\n" \
97 " -b fil bindings file location\n" \
98 " -p pol force all maps to specified path grouping policy :\n" \
99 " . failover one path per priority group\n" \
100 " . multibus all paths in one priority group\n" \
101 " . group_by_serial one priority group per serial\n" \
102 " . group_by_prio one priority group per priority lvl\n" \
103 " . group_by_node_name one priority group per target node\n" \
104 " -v lvl verbosity level\n" \
106 " . 1 print created devmap names only\n" \
107 " . 2 default verbosity\n" \
108 " . 3 print debug information\n" \
109 " dev action limited to:\n" \
110 " . multipath named 'dev' (ex: mpath0) or\n" \
111 " . multipath whose wwid is 'dev' (ex: 60051..)\n" \
112 " . multipath including the path named 'dev' (ex: /dev/sda)\n" \
113 " . multipath including the path with maj:min 'dev' (ex: 8:0)\n" \
120 update_paths (struct multipath * mpp)
123 struct pathgroup * pgp;
129 vector_foreach_slot (mpp->pg, pgp, i) {
133 vector_foreach_slot (pgp->paths, pp, j) {
134 if (!strlen(pp->dev)) {
135 if (devt2devname(pp->dev, pp->dev_t)) {
137 * path is not in sysfs anymore
139 pp->state = PATH_DOWN;
143 pathinfo(pp, conf->hwtable, DI_ALL);
147 if (pp->state == PATH_UNCHECKED ||
148 pp->state == PATH_WILD)
149 pathinfo(pp, conf->hwtable, DI_CHECKER);
151 if (pp->priority == PRIO_UNDEF)
152 pathinfo(pp, conf->hwtable, DI_PRIO);
159 get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
162 struct multipath * mpp;
164 if (dm_get_maps(curmp))
167 vector_foreach_slot (curmp, mpp, i) {
169 * discard out of scope maps
171 if (mpp->wwid && refwwid &&
172 strncmp(mpp->wwid, refwwid, WWID_SIZE)) {
173 condlog(3, "skip map %s: out of scope", mpp->alias);
174 free_multipath(mpp, KEEP_PATHS);
175 vector_del_slot(curmp, i);
180 condlog(3, "params = %s", mpp->params);
181 condlog(3, "status = %s", mpp->status);
183 disassemble_map(pathvec, mpp->params, mpp);
186 * disassemble_map() can add new paths to pathvec.
187 * If not in "fast list mode", we need to fetch information
194 mpp->bestpg = select_path_group(mpp);
196 disassemble_status(mpp->status, mpp);
199 print_multipath_topology(mpp, conf->verbosity);
202 reinstate_paths(mpp);
218 vector pathvec = NULL;
222 char * refwwid = NULL;
226 * allocate core vectors to store paths and multipaths
228 curmp = vector_alloc();
229 pathvec = vector_alloc();
231 if (!curmp || !pathvec) {
232 condlog(0, "can not allocate memory");
235 vecs.pathvec = pathvec;
239 * dev is "/dev/" . "sysfs block dev"
242 if (!strncmp(conf->dev, "/dev/", 5) &&
243 strlen(conf->dev) > 5)
250 * if we have a blacklisted device parameter, exit early
253 (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
257 * scope limiting must be translated into a wwid
258 * failing the translation is fatal (by policy)
261 refwwid = get_refwwid(conf->dev, conf->dev_type, pathvec);
264 condlog(3, "scope is nul");
267 condlog(3, "scope limited to %s", refwwid);
268 if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
280 /* extended path info '-ll' */
281 di_flag |= DI_SYSFS | DI_CHECKER;
283 /* minimum path info '-l' */
289 if (path_discovery(pathvec, conf, di_flag))
292 if (conf->verbosity > 2)
293 print_all_paths(pathvec, 1);
295 get_path_layout(pathvec, 0);
297 if (get_dm_mpvec(curmp, pathvec, refwwid))
300 filter_pathvec(pathvec, refwwid);
308 * core logic entry point
310 r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
316 free_multipathvec(curmp, KEEP_PATHS);
317 free_pathvec(pathvec, FREE_PATHS);
323 main (int argc, char *argv[])
331 fprintf(stderr, "need to be root\n");
338 if (load_config(DEFAULT_CONFIGFILE))
341 if (init_checkers()) {
342 condlog(0, "failed to initialize checkers");
346 condlog(0, "failed to initialize prioritizers");
349 if (sysfs_init(conf->sysfs_dir, FILE_NAME_SIZE)) {
350 condlog(0, "multipath tools need sysfs mounted");
353 while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:Br")) != EOF ) {
355 case 1: printf("optarg : %s\n",optarg);
358 if (sizeof(optarg) > sizeof(char *) ||
362 conf->verbosity = atoi(optarg);
365 conf->bindings_file = optarg;
368 conf->bindings_read_only = 1;
374 conf->remove = FLUSH_ONE;
377 conf->remove = FLUSH_ALL;
383 if (optarg && !strncmp(optarg, "l", 1))
389 debug = atoi(optarg);
393 conf->pgpolicy_flag = get_pgpolicy_id(optarg);
394 if (conf->pgpolicy_flag == -1) {
395 printf("'%s' is not a valid policy\n", optarg);
400 conf->force_reload = 1;
405 fprintf(stderr, "Missing option arguement\n");
408 fprintf(stderr, "Unknown switch: %s\n", optarg);
415 conf->dev = MALLOC(FILE_NAME_SIZE);
420 strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
422 if (filepresent(conf->dev))
423 conf->dev_type = DEV_DEVNODE;
424 else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
425 conf->dev_type = DEV_DEVT;
427 conf->dev_type = DEV_DEVMAP;
433 struct rlimit fd_limit;
435 fd_limit.rlim_cur = conf->max_fds;
436 fd_limit.rlim_max = conf->max_fds;
437 if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
438 condlog(0, "can't set open fds limit to %d : %s\n",
439 conf->max_fds, strerror(errno));
444 if (conf->remove == FLUSH_ONE) {
445 if (conf->dev_type == DEV_DEVMAP)
446 r = dm_flush_map(conf->dev);
448 condlog(0, "must provide a map name to remove");
452 else if (conf->remove == FLUSH_ALL) {
456 while ((r = configure()) < 0)
457 condlog(3, "restart multipath configuration process");
460 dm_udev_wait(conf->cookie);
469 * Freeing config must be done after dm_lib_exit(), because
470 * the logging function (dm_write_log()), which is called there,
471 * references the config.
477 dbg_free_final(NULL);