multipath-tools: document missing multipath flags in help output
[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 <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include <libudev.h>
32 #include <syslog.h>
33 #include <fcntl.h>
34
35 #include "checkers.h"
36 #include "prio.h"
37 #include "vector.h"
38 #include "memory.h"
39 #include <libdevmapper.h>
40 #include "devmapper.h"
41 #include "util.h"
42 #include "defaults.h"
43 #include "config.h"
44 #include "structs.h"
45 #include "structs_vec.h"
46 #include "dmparser.h"
47 #include "sysfs.h"
48 #include "blacklist.h"
49 #include "discovery.h"
50 #include "debug.h"
51 #include "switchgroup.h"
52 #include "dm-generic.h"
53 #include "print.h"
54 #include "alias.h"
55 #include "configure.h"
56 #include "pgpolicies.h"
57 #include "version.h"
58 #include <errno.h>
59 #include "wwids.h"
60 #include "uxsock.h"
61 #include "mpath_cmd.h"
62 #include "foreign.h"
63 #include "propsel.h"
64 #include "time-util.h"
65 #include "file.h"
66
67 int logsink;
68 struct udev *udev;
69 struct config *multipath_conf;
70
71 /*
72  * Return values of configure(), print_cmd_valid(), and main().
73  * RTVL_{YES,NO} are synonyms for RTVL_{OK,FAIL} for the CMD_VALID_PATH case.
74  */
75 enum {
76         RTVL_OK = 0,
77         RTVL_YES = RTVL_OK,
78         RTVL_FAIL = 1,
79         RTVL_NO = RTVL_FAIL,
80         RTVL_MAYBE, /* only used internally, never returned */
81         RTVL_RETRY, /* returned by configure(), not by main() */
82 };
83
84 struct config *get_multipath_config(void)
85 {
86         return multipath_conf;
87 }
88
89 void put_multipath_config(void *arg)
90 {
91         /* Noop for now */
92 }
93
94 static int
95 dump_config (struct config *conf, vector hwes, vector mpvec)
96 {
97         char * reply = snprint_config(conf, NULL, hwes, mpvec);
98
99         if (reply != NULL) {
100                 printf("%s", reply);
101                 FREE(reply);
102                 return 0;
103         } else
104                 return 1;
105 }
106
107 void rcu_register_thread_memb(void) {}
108
109 void rcu_unregister_thread_memb(void) {}
110
111 static int
112 filter_pathvec (vector pathvec, char * refwwid)
113 {
114         int i;
115         struct path * pp;
116
117         if (!refwwid || !strlen(refwwid))
118                 return 0;
119
120         vector_foreach_slot (pathvec, pp, i) {
121                 if (strncmp(pp->wwid, refwwid, WWID_SIZE) != 0) {
122                         condlog(3, "skip path %s : out of scope", pp->dev);
123                         free_path(pp);
124                         vector_del_slot(pathvec, i);
125                         i--;
126                 }
127         }
128         return 0;
129 }
130
131 static void
132 usage (char * progname)
133 {
134         fprintf (stderr, VERSION_STRING);
135         fprintf (stderr, "Usage:\n");
136         fprintf (stderr, "  %s [-v level] [-B|-d|-i|-q|-r] [-b file] [-p policy] [device]\n", progname);
137         fprintf (stderr, "  %s [-v level] [-R retries] -f device\n", progname);
138         fprintf (stderr, "  %s [-v level] [-R retries] -F\n", progname);
139         fprintf (stderr, "  %s [-v level] [-l|-ll] [device]\n", progname);
140         fprintf (stderr, "  %s [-v level] [-a|-w] device\n", progname);
141         fprintf (stderr, "  %s [-v level] -W\n", progname);
142         fprintf (stderr, "  %s [-v level] [-i] [-c|-C] device\n", progname);
143         fprintf (stderr, "  %s [-v level] [-i] [-u|-U]\n", progname);
144         fprintf (stderr, "  %s [-h|-t|-T]\n", progname);
145         fprintf (stderr,
146                 "\n"
147                 "Where:\n"
148                 "  -h      print this usage text\n"
149                 "  -l      show multipath topology (sysfs and DM info)\n"
150                 "  -ll     show multipath topology (maximum info)\n"
151                 "  -f      flush a multipath device map\n"
152                 "  -F      flush all multipath device maps\n"
153                 "  -a      add a device wwid to the wwids file\n"
154                 "  -c      check if a device should be a path in a multipath device\n"
155                 "  -C      check if a multipath device has usable paths\n"
156                 "  -q      allow queue_if_no_path when multipathd is not running\n"
157                 "  -d      dry run, do not create or update devmaps\n"
158                 "  -t      display the currently used multipathd configuration\n"
159                 "  -T      display the multipathd configuration without builtin defaults\n"
160                 "  -r      force devmap reload\n"
161                 "  -i      ignore wwids file\n"
162                 "  -B      treat the bindings file as read only\n"
163                 "  -b fil  bindings file location\n"
164                 "  -w      remove a device from the wwids file\n"
165                 "  -W      reset the wwids file include only the current devices\n"
166                 "  -R num  number of times to retry removes of in-use devices\n"
167                 "  -u      check if the device specified in the program environment should be a\n"
168                 "          path in a multipath device\n"
169                 "  -U      check if the device specified in the program environment is a\n"
170                 "          multipath device with usable paths, see -C flag\n"
171                 "  -p pol  force all maps to specified path grouping policy:\n"
172                 "          . failover            one path per priority group\n"
173                 "          . multibus            all paths in one priority group\n"
174                 "          . group_by_serial     one priority group per serial\n"
175                 "          . group_by_prio       one priority group per priority lvl\n"
176                 "          . group_by_node_name  one priority group per target node\n"
177                 "  -v lvl  verbosity level:\n"
178                 "          . 0 no output\n"
179                 "          . 1 print created devmap names only\n"
180                 "          . 2 default verbosity\n"
181                 "          . 3 print debug information\n"
182                 "  device  action limited to:\n"
183                 "          . multipath named 'device' (ex: mpath0)\n"
184                 "          . multipath whose wwid is 'device' (ex: 60051...)\n"
185                 "          . multipath including the path named 'device' (ex: /dev/sda or\n"
186                 "            /dev/dm-0)\n"
187                 "          . multipath including the path with maj:min 'device' (ex: 8:0)\n"
188                 );
189
190 }
191
192 static int
193 update_paths (struct multipath * mpp, int quick)
194 {
195         int i, j;
196         struct pathgroup * pgp;
197         struct path * pp;
198         struct config *conf;
199
200         if (!mpp->pg)
201                 return 0;
202
203         vector_foreach_slot (mpp->pg, pgp, i) {
204                 if (!pgp->paths)
205                         continue;
206
207                 vector_foreach_slot (pgp->paths, pp, j) {
208                         if (!strlen(pp->dev)) {
209                                 if (devt2devname(pp->dev, FILE_NAME_SIZE,
210                                                  pp->dev_t)) {
211                                         /*
212                                          * path is not in sysfs anymore
213                                          */
214                                         pp->chkrstate = pp->state = PATH_DOWN;
215                                         pp->offline = 1;
216                                         continue;
217                                 }
218                                 pp->mpp = mpp;
219                                 if (quick)
220                                         continue;
221                                 conf = get_multipath_config();
222                                 if (pathinfo(pp, conf, DI_ALL))
223                                         pp->state = PATH_UNCHECKED;
224                                 put_multipath_config(conf);
225                                 continue;
226                         }
227                         pp->mpp = mpp;
228                         if (quick)
229                                 continue;
230                         if (pp->state == PATH_UNCHECKED ||
231                             pp->state == PATH_WILD) {
232                                 conf = get_multipath_config();
233                                 if (pathinfo(pp, conf, DI_CHECKER))
234                                         pp->state = PATH_UNCHECKED;
235                                 put_multipath_config(conf);
236                         }
237
238                         if (pp->priority == PRIO_UNDEF) {
239                                 conf = get_multipath_config();
240                                 if (pathinfo(pp, conf, DI_PRIO))
241                                         pp->priority = PRIO_UNDEF;
242                                 put_multipath_config(conf);
243                         }
244                 }
245         }
246         return 0;
247 }
248
249 static int
250 get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
251 {
252         int i;
253         struct multipath * mpp;
254         char params[PARAMS_SIZE], status[PARAMS_SIZE];
255
256         if (dm_get_maps(curmp))
257                 return 1;
258
259         vector_foreach_slot (curmp, mpp, i) {
260                 /*
261                  * discard out of scope maps
262                  */
263                 if (refwwid && strlen(refwwid) &&
264                     strncmp(mpp->wwid, refwwid, WWID_SIZE)) {
265                         condlog(3, "skip map %s: out of scope", mpp->alias);
266                         free_multipath(mpp, KEEP_PATHS);
267                         vector_del_slot(curmp, i);
268                         i--;
269                         continue;
270                 }
271
272                 if (cmd == CMD_VALID_PATH)
273                         continue;
274
275                 dm_get_map(mpp->alias, &mpp->size, params);
276                 condlog(3, "params = %s", params);
277                 dm_get_status(mpp->alias, status);
278                 condlog(3, "status = %s", status);
279
280                 disassemble_map(pathvec, params, mpp, 0);
281
282                 /*
283                  * disassemble_map() can add new paths to pathvec.
284                  * If not in "fast list mode", we need to fetch information
285                  * about them
286                  */
287                 update_paths(mpp, (cmd == CMD_LIST_SHORT));
288
289                 if (cmd == CMD_LIST_LONG)
290                         mpp->bestpg = select_path_group(mpp);
291
292                 disassemble_status(status, mpp);
293
294                 if (cmd == CMD_LIST_SHORT ||
295                     cmd == CMD_LIST_LONG) {
296                         struct config *conf = get_multipath_config();
297                         print_multipath_topology(mpp, conf->verbosity);
298                         put_multipath_config(conf);
299                 }
300
301                 if (cmd == CMD_CREATE)
302                         reinstate_paths(mpp);
303         }
304
305         if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG) {
306                 struct config *conf = get_multipath_config();
307
308                 print_foreign_topology(conf->verbosity);
309                 put_multipath_config(conf);
310         }
311
312         return 0;
313 }
314
315 static int check_usable_paths(struct config *conf,
316                               const char *devpath, enum devtypes dev_type)
317 {
318         struct udev_device *ud = NULL;
319         struct multipath *mpp = NULL;
320         struct pathgroup *pg;
321         struct path *pp;
322         char *mapname;
323         vector pathvec = NULL;
324         char params[PARAMS_SIZE], status[PARAMS_SIZE];
325         dev_t devt;
326         int r = 1, i, j;
327
328         ud = get_udev_device(devpath, dev_type);
329         if (ud == NULL)
330                 return r;
331
332         devt = udev_device_get_devnum(ud);
333         if (!dm_is_dm_major(major(devt))) {
334                 condlog(1, "%s is not a dm device", devpath);
335                 goto out;
336         }
337
338         mapname = dm_mapname(major(devt), minor(devt));
339         if (mapname == NULL) {
340                 condlog(1, "dm device not found: %s", devpath);
341                 goto out;
342         }
343
344         if (dm_is_mpath(mapname) != 1) {
345                 condlog(1, "%s is not a multipath map", devpath);
346                 goto free;
347         }
348
349         /* pathvec is needed for disassemble_map */
350         pathvec = vector_alloc();
351         if (pathvec == NULL)
352                 goto free;
353
354         mpp = dm_get_multipath(mapname);
355         if (mpp == NULL)
356                 goto free;
357
358         dm_get_map(mpp->alias, &mpp->size, params);
359         dm_get_status(mpp->alias, status);
360         disassemble_map(pathvec, params, mpp, 0);
361         disassemble_status(status, mpp);
362
363         vector_foreach_slot (mpp->pg, pg, i) {
364                 vector_foreach_slot (pg->paths, pp, j) {
365                         pp->udev = get_udev_device(pp->dev_t, DEV_DEVT);
366                         if (pp->udev == NULL)
367                                 continue;
368                         if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO|DI_CHECKER) != PATHINFO_OK)
369                                 continue;
370
371                         if (pp->state == PATH_UP &&
372                             pp->dmstate == PSTATE_ACTIVE) {
373                                 condlog(3, "%s: path %s is usable",
374                                         devpath, pp->dev);
375                                 r = 0;
376                                 goto found;
377                         }
378                 }
379         }
380 found:
381         condlog(r == 0 ? 3 : 2, "%s:%s usable paths found",
382                 devpath, r == 0 ? "" : " no");
383 free:
384         FREE(mapname);
385         free_multipath(mpp, FREE_PATHS);
386         vector_free(pathvec);
387 out:
388         udev_device_unref(ud);
389         return r;
390 }
391
392 enum {
393         FIND_MULTIPATHS_WAIT_DONE = 0,
394         FIND_MULTIPATHS_WAITING = 1,
395         FIND_MULTIPATHS_ERROR = -1,
396         FIND_MULTIPATHS_NEVER = -2,
397 };
398
399 static const char shm_find_mp_dir[] = MULTIPATH_SHM_BASE "find_multipaths";
400
401 /**
402  * find_multipaths_check_timeout(wwid, tmo)
403  * Helper for "find_multipaths smart"
404  *
405  * @param[in] pp: path to check / record
406  * @param[in] tmo: configured timeout for this WWID, or value <= 0 for checking
407  * @param[out] until: timestamp until we must wait, CLOCK_REALTIME, if return
408  *             value is FIND_MULTIPATHS_WAITING
409  * @returns: FIND_MULTIPATHS_WAIT_DONE, if waiting has finished
410  * @returns: FIND_MULTIPATHS_ERROR, if internal error occurred
411  * @returns: FIND_MULTIPATHS_NEVER, if tmo is 0 and we didn't wait for this
412  *           device
413  * @returns: FIND_MULTIPATHS_WAITING, if timeout hasn't expired
414  */
415 static int find_multipaths_check_timeout(const struct path *pp, long tmo,
416                                          struct timespec *until)
417 {
418         char path[PATH_MAX];
419         struct timespec now, ftimes[2], tdiff;
420         struct stat st;
421         long fd;
422         int r, retries = 0;
423
424         clock_gettime(CLOCK_REALTIME, &now);
425
426         if (snprintf(path, sizeof(path), "%s/%s", shm_find_mp_dir, pp->dev_t)
427             >= sizeof(path)) {
428                 condlog(1, "%s: path name overflow", __func__);
429                 return FIND_MULTIPATHS_ERROR;
430         }
431
432         if (ensure_directories_exist(path, 0700)) {
433                 condlog(1, "%s: error creating directories", __func__);
434                 return FIND_MULTIPATHS_ERROR;
435         }
436
437 retry:
438         fd = open(path, O_RDONLY);
439         if (fd != -1) {
440                 pthread_cleanup_push(close_fd, (void *)fd);
441                 r = fstat(fd, &st);
442                 pthread_cleanup_pop(1);
443
444         } else if (tmo > 0) {
445                 if (errno == ENOENT)
446                         fd = open(path, O_RDWR|O_EXCL|O_CREAT, 0644);
447                 if (fd == -1) {
448                         if (errno == EEXIST && !retries++)
449                                 /* We could have raced with another process */
450                                 goto retry;
451                         condlog(1, "%s: error opening %s: %s",
452                                 __func__, path, strerror(errno));
453                         return FIND_MULTIPATHS_ERROR;
454                 };
455
456                 pthread_cleanup_push(close_fd, (void *)fd);
457                 /*
458                  * We just created the file. Set st_mtim to our desired
459                  * expiry time.
460                  */
461                 ftimes[0].tv_sec = 0;
462                 ftimes[0].tv_nsec = UTIME_OMIT;
463                 ftimes[1].tv_sec = now.tv_sec + tmo;
464                 ftimes[1].tv_nsec = now.tv_nsec;
465                 if (futimens(fd, ftimes) != 0) {
466                         condlog(1, "%s: error in futimens(%s): %s", __func__,
467                                 path, strerror(errno));
468                 }
469                 r = fstat(fd, &st);
470                 pthread_cleanup_pop(1);
471         } else
472                 return FIND_MULTIPATHS_NEVER;
473
474         if (r != 0) {
475                 condlog(1, "%s: error in fstat for %s: %m", __func__, path);
476                 return FIND_MULTIPATHS_ERROR;
477         }
478
479         timespecsub(&st.st_mtim, &now, &tdiff);
480
481         if (tdiff.tv_sec <= 0)
482                 return FIND_MULTIPATHS_WAIT_DONE;
483
484         *until = tdiff;
485         return FIND_MULTIPATHS_WAITING;
486 }
487
488 static int print_cmd_valid(int k, const vector pathvec,
489                            struct config *conf)
490 {
491         int wait = FIND_MULTIPATHS_NEVER;
492         struct timespec until;
493         struct path *pp;
494
495         if (k != RTVL_YES && k != RTVL_NO && k != RTVL_MAYBE)
496                 return RTVL_NO;
497
498         if (k == RTVL_MAYBE) {
499                 /*
500                  * Caller ensures that pathvec[0] is the path to
501                  * examine.
502                  */
503                 pp = VECTOR_SLOT(pathvec, 0);
504                 select_find_multipaths_timeout(conf, pp);
505                 wait = find_multipaths_check_timeout(
506                         pp, pp->find_multipaths_timeout, &until);
507                 if (wait != FIND_MULTIPATHS_WAITING)
508                         k = RTVL_NO;
509         } else if (pathvec != NULL && (pp = VECTOR_SLOT(pathvec, 0)))
510                 wait = find_multipaths_check_timeout(pp, 0, &until);
511         if (wait == FIND_MULTIPATHS_WAITING)
512                 printf("FIND_MULTIPATHS_WAIT_UNTIL=\"%ld.%06ld\"\n",
513                                until.tv_sec, until.tv_nsec/1000);
514         else if (wait == FIND_MULTIPATHS_WAIT_DONE)
515                 printf("FIND_MULTIPATHS_WAIT_UNTIL=\"0\"\n");
516         printf("DM_MULTIPATH_DEVICE_PATH=\"%d\"\n",
517                k == RTVL_MAYBE ? 2 : k == RTVL_YES ? 1 : 0);
518         /* Never return RTVL_MAYBE */
519         return k == RTVL_NO ? RTVL_NO : RTVL_YES;
520 }
521
522 /*
523  * Returns true if this device has been handled before,
524  * and released to systemd.
525  *
526  * This must be called before get_refwwid(),
527  * otherwise udev_device_new_from_environment() will have
528  * destroyed environ(7).
529  */
530 static bool released_to_systemd(void)
531 {
532         static const char dmdp[] = "DM_MULTIPATH_DEVICE_PATH";
533         const char *dm_mp_dev_path = getenv(dmdp);
534         bool ret;
535
536         ret = dm_mp_dev_path != NULL && !strcmp(dm_mp_dev_path, "0");
537         condlog(4, "%s: %s=%s -> %d", __func__, dmdp, dm_mp_dev_path, ret);
538         return ret;
539 }
540
541 static int
542 configure (struct config *conf, enum mpath_cmds cmd,
543            enum devtypes dev_type, char *devpath)
544 {
545         vector curmp = NULL;
546         vector pathvec = NULL;
547         struct vectors vecs;
548         int r = RTVL_FAIL, rc;
549         int di_flag = 0;
550         char * refwwid = NULL;
551         char * dev = NULL;
552         bool released = released_to_systemd();
553
554         /*
555          * allocate core vectors to store paths and multipaths
556          */
557         curmp = vector_alloc();
558         pathvec = vector_alloc();
559
560         if (!curmp || !pathvec) {
561                 condlog(0, "can not allocate memory");
562                 goto out;
563         }
564         vecs.pathvec = pathvec;
565         vecs.mpvec = curmp;
566
567         dev = convert_dev(devpath, (dev_type == DEV_DEVNODE));
568
569         /*
570          * if we have a blacklisted device parameter, exit early
571          */
572         if (dev && (dev_type == DEV_DEVNODE ||
573                     dev_type == DEV_UEVENT) &&
574             cmd != CMD_REMOVE_WWID &&
575             (filter_devnode(conf->blist_devnode,
576                             conf->elist_devnode, dev) > 0)) {
577                 goto print_valid;
578         }
579
580         /*
581          * scope limiting must be translated into a wwid
582          * failing the translation is fatal (by policy)
583          */
584         if (devpath) {
585                 int failed = get_refwwid(cmd, devpath, dev_type,
586                                          pathvec, &refwwid);
587                 if (!refwwid) {
588                         condlog(4, "%s: failed to get wwid", devpath);
589                         if (failed == 2 && cmd == CMD_VALID_PATH)
590                                 goto print_valid;
591                         else
592                                 condlog(3, "scope is null");
593                         goto out;
594                 }
595                 if (cmd == CMD_REMOVE_WWID) {
596                         rc = remove_wwid(refwwid);
597                         if (rc == 0) {
598                                 printf("wwid '%s' removed\n", refwwid);
599                                 r = RTVL_OK;
600                         } else if (rc == 1) {
601                                 printf("wwid '%s' not in wwids file\n",
602                                         refwwid);
603                                 r = RTVL_OK;
604                         }
605                         goto out;
606                 }
607                 if (cmd == CMD_ADD_WWID) {
608                         rc = remember_wwid(refwwid);
609                         if (rc >= 0) {
610                                 printf("wwid '%s' added\n", refwwid);
611                                 r = RTVL_OK;
612                         } else
613                                 printf("failed adding '%s' to wwids file\n",
614                                        refwwid);
615                         goto out;
616                 }
617                 condlog(3, "scope limited to %s", refwwid);
618                 /* If you are ignoring the wwids file and find_multipaths is
619                  * set, you need to actually check if there are two available
620                  * paths to determine if this path should be multipathed. To
621                  * do this, we put off the check until after discovering all
622                  * the paths.
623                  * Paths listed in the wwids file are always considered valid.
624                  */
625                 if (cmd == CMD_VALID_PATH) {
626                         if (is_failed_wwid(refwwid) == WWID_IS_FAILED) {
627                                 r = RTVL_NO;
628                                 goto print_valid;
629                         }
630                         if ((!find_multipaths_on(conf) &&
631                                     ignore_wwids_on(conf)) ||
632                                    check_wwids_file(refwwid, 0) == 0)
633                                 r = RTVL_YES;
634                         if (!ignore_wwids_on(conf))
635                                 goto print_valid;
636                         /* At this point, either r==0 or find_multipaths_on. */
637
638                         /*
639                          * Shortcut for find_multipaths smart:
640                          * Quick check if path is already multipathed.
641                          */
642                         if (sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0))) {
643                                 r = RTVL_YES;
644                                 goto print_valid;
645                         }
646
647                         /*
648                          * DM_MULTIPATH_DEVICE_PATH=="0" means that we have
649                          * been called for this device already, and have
650                          * released it to systemd. Unless the device is now
651                          * already multipathed (see above), we can't try to
652                          * grab it, because setting SYSTEMD_READY=0 would
653                          * cause file systems to be unmounted.
654                          * Leave DM_MULTIPATH_DEVICE_PATH="0".
655                          */
656                         if (released) {
657                                 r = RTVL_NO;
658                                 goto print_valid;
659                         }
660                         if (r == RTVL_YES)
661                                 goto print_valid;
662                         /* find_multipaths_on: Fall through to path detection */
663                 }
664         }
665
666         /*
667          * get a path list
668          */
669         if (devpath)
670                 di_flag = DI_WWID;
671
672         if (cmd == CMD_LIST_LONG)
673                 /* extended path info '-ll' */
674                 di_flag |= DI_SYSFS | DI_CHECKER | DI_SERIAL;
675         else if (cmd == CMD_LIST_SHORT)
676                 /* minimum path info '-l' */
677                 di_flag |= DI_SYSFS;
678         else
679                 /* maximum info */
680                 di_flag = DI_ALL;
681
682         if (path_discovery(pathvec, di_flag) < 0)
683                 goto out;
684
685         if (conf->verbosity > 2)
686                 print_all_paths(pathvec, 1);
687
688         get_path_layout(pathvec, 0);
689         foreign_path_layout();
690
691         if (get_dm_mpvec(cmd, curmp, pathvec, refwwid))
692                 goto out;
693
694         filter_pathvec(pathvec, refwwid);
695
696         if (cmd == CMD_DUMP_CONFIG) {
697                 vector hwes = get_used_hwes(pathvec);
698
699                 dump_config(conf, hwes, curmp);
700                 vector_free(hwes);
701                 goto out;
702         }
703
704         if (cmd == CMD_VALID_PATH) {
705                 struct path *pp;
706                 int fd;
707
708                 /* This only happens if find_multipaths and
709                  * ignore_wwids is set, and the path is not in WWIDs
710                  * file, not currently multipathed, and has
711                  * never been released to systemd.
712                  * If there is currently a multipath device matching
713                  * the refwwid, or there is more than one path matching
714                  * the refwwid, then the path is valid */
715                 if (VECTOR_SIZE(curmp) != 0) {
716                         r = RTVL_YES;
717                         goto print_valid;
718                 } else if (VECTOR_SIZE(pathvec) > 1)
719                         r = RTVL_YES;
720                 else
721                         r = RTVL_MAYBE;
722
723                 /*
724                  * If opening the path with O_EXCL fails, the path
725                  * is in use (e.g. mounted during initramfs processing).
726                  * We know that it's not used by dm-multipath.
727                  * We may not set SYSTEMD_READY=0 on such devices, it
728                  * might cause systemd to umount the device.
729                  * Use O_RDONLY, because udevd would trigger another
730                  * uevent for close-after-write.
731                  *
732                  * The O_EXCL check is potentially dangerous, because it may
733                  * race with other tasks trying to access the device. Therefore
734                  * this code is only executed if the path hasn't been released
735                  * to systemd earlier (see above).
736                  *
737                  * get_refwwid() above stores the path we examine in slot 0.
738                  */
739                 pp = VECTOR_SLOT(pathvec, 0);
740                 fd = open(udev_device_get_devnode(pp->udev),
741                           O_RDONLY|O_EXCL);
742                 if (fd >= 0)
743                         close(fd);
744                 else {
745                         condlog(3, "%s: path %s is in use: %s",
746                                 __func__, pp->dev,
747                                 strerror(errno));
748                         /*
749                          * Check if we raced with multipathd
750                          */
751                         r = sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0)) ?
752                                 RTVL_YES : RTVL_NO;
753                 }
754                 goto print_valid;
755         }
756
757         if (cmd != CMD_CREATE && cmd != CMD_DRY_RUN) {
758                 r = RTVL_OK;
759                 goto out;
760         }
761
762         /*
763          * core logic entry point
764          */
765         rc = coalesce_paths(&vecs, NULL, refwwid,
766                            conf->force_reload, cmd);
767         r = rc == CP_RETRY ? RTVL_RETRY : rc == CP_OK ? RTVL_OK : RTVL_FAIL;
768
769 print_valid:
770         if (cmd == CMD_VALID_PATH)
771                 r = print_cmd_valid(r, pathvec, conf);
772
773 out:
774         if (refwwid)
775                 FREE(refwwid);
776
777         free_multipathvec(curmp, KEEP_PATHS);
778         free_pathvec(pathvec, FREE_PATHS);
779
780         return r;
781 }
782
783 static int
784 get_dev_type(char *dev) {
785         struct stat buf;
786         int i;
787
788         if (stat(dev, &buf) == 0 && S_ISBLK(buf.st_mode)) {
789                 if (dm_is_dm_major(major(buf.st_rdev)))
790                         return DEV_DEVMAP;
791                 return DEV_DEVNODE;
792         }
793         else if (sscanf(dev, "%d:%d", &i, &i) == 2)
794                 return DEV_DEVT;
795         else if (valid_alias(dev))
796                 return DEV_DEVMAP;
797         return DEV_NONE;
798 }
799
800 /*
801  * Some multipath commands are dangerous to run while multipathd is running.
802  * For example, "multipath -r" may apply a modified configuration to the kernel,
803  * while multipathd is still using the old configuration, leading to
804  * inconsistent state.
805  *
806  * It is safer to use equivalent multipathd client commands instead.
807  */
808 enum {
809         DELEGATE_OK = 0,
810         DELEGATE_ERROR = -1,
811         NOT_DELEGATED = 1,
812 };
813
814 int delegate_to_multipathd(enum mpath_cmds cmd, const char *dev,
815                            enum devtypes dev_type, const struct config *conf)
816 {
817         int fd;
818         char command[1024], *p, *reply = NULL;
819         int n, r = DELEGATE_ERROR;
820
821         p = command;
822         *p = '\0';
823         n = sizeof(command);
824
825         if (cmd == CMD_CREATE && conf->force_reload == FORCE_RELOAD_YES) {
826                 p += snprintf(p, n, "reconfigure");
827         }
828         /* Add other translations here */
829
830         if (strlen(command) == 0)
831                 /* No command found, no need to delegate */
832                 return NOT_DELEGATED;
833
834         fd = mpath_connect();
835         if (fd == -1)
836                 return NOT_DELEGATED;
837
838         if (p >= command + sizeof(command)) {
839                 condlog(0, "internal error - command buffer overflow");
840                 goto out;
841         }
842
843         condlog(3, "delegating command to multipathd");
844
845         if (mpath_process_cmd(fd, command, &reply, conf->uxsock_timeout)
846             == -1) {
847                 condlog(1, "error in multipath command %s: %s",
848                         command, strerror(errno));
849                 goto out;
850         }
851
852         if (reply != NULL && *reply != '\0' && strcmp(reply, "ok\n"))
853                 printf("%s", reply);
854         r = DELEGATE_OK;
855
856 out:
857         FREE(reply);
858         close(fd);
859         return r;
860 }
861
862 static int test_multipathd_socket(void)
863 {
864         int fd;
865         /*
866          * "multipath -u" may be run before the daemon is started. In this
867          * case, systemd might own the socket but might delay multipathd
868          * startup until some other unit (udev settle!)  has finished
869          * starting. With many LUNs, the listen backlog may be exceeded, which
870          * would cause connect() to block. This causes udev workers calling
871          * "multipath -u" to hang, and thus creates a deadlock, until "udev
872          * settle" times out.  To avoid this, call connect() in non-blocking
873          * mode here, and take EAGAIN as indication for a filled-up systemd
874          * backlog.
875          */
876
877         fd = __mpath_connect(1);
878         if (fd == -1) {
879                 if (errno == EAGAIN)
880                         condlog(3, "daemon backlog exceeded");
881                 else
882                         return 0;
883         } else
884                 close(fd);
885         return 1;
886 }
887
888 int
889 main (int argc, char *argv[])
890 {
891         int arg;
892         extern char *optarg;
893         extern int optind;
894         int r = RTVL_FAIL;
895         enum mpath_cmds cmd = CMD_CREATE;
896         enum devtypes dev_type = DEV_NONE;
897         char *dev = NULL;
898         struct config *conf;
899         int retries = -1;
900
901         udev = udev_new();
902         logsink = 0;
903         conf = load_config(DEFAULT_CONFIGFILE);
904         if (!conf)
905                 exit(RTVL_FAIL);
906         multipath_conf = conf;
907         conf->retrigger_tries = 0;
908         while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
909                 switch(arg) {
910                 case 1: printf("optarg : %s\n",optarg);
911                         break;
912                 case 'v':
913                         if (sizeof(optarg) > sizeof(char *) ||
914                             !isdigit(optarg[0])) {
915                                 usage (argv[0]);
916                                 exit(RTVL_FAIL);
917                         }
918
919                         conf->verbosity = atoi(optarg);
920                         break;
921                 case 'b':
922                         conf->bindings_file = strdup(optarg);
923                         break;
924                 case 'B':
925                         conf->bindings_read_only = 1;
926                         break;
927                 case 'q':
928                         conf->allow_queueing = 1;
929                         break;
930                 case 'c':
931                         cmd = CMD_VALID_PATH;
932                         break;
933                 case 'C':
934                         cmd = CMD_USABLE_PATHS;
935                         break;
936                 case 'd':
937                         if (cmd == CMD_CREATE)
938                                 cmd = CMD_DRY_RUN;
939                         break;
940                 case 'f':
941                         conf->remove = FLUSH_ONE;
942                         break;
943                 case 'F':
944                         conf->remove = FLUSH_ALL;
945                         break;
946                 case 'l':
947                         if (optarg && !strncmp(optarg, "l", 1))
948                                 cmd = CMD_LIST_LONG;
949                         else
950                                 cmd = CMD_LIST_SHORT;
951
952                         break;
953                 case 'M':
954 #if _DEBUG_
955                         debug = atoi(optarg);
956 #endif
957                         break;
958                 case 'p':
959                         conf->pgpolicy_flag = get_pgpolicy_id(optarg);
960                         if (conf->pgpolicy_flag == IOPOLICY_UNDEF) {
961                                 printf("'%s' is not a valid policy\n", optarg);
962                                 usage(argv[0]);
963                                 exit(RTVL_FAIL);
964                         }
965                         break;
966                 case 'r':
967                         conf->force_reload = FORCE_RELOAD_YES;
968                         break;
969                 case 'i':
970                         conf->find_multipaths |= _FIND_MULTIPATHS_I;
971                         break;
972                 case 't':
973                         r = dump_config(conf, NULL, NULL) ? RTVL_FAIL : RTVL_OK;
974                         goto out_free_config;
975                 case 'T':
976                         cmd = CMD_DUMP_CONFIG;
977                         break;
978                 case 'h':
979                         usage(argv[0]);
980                         exit(RTVL_OK);
981                 case 'u':
982                         cmd = CMD_VALID_PATH;
983                         dev_type = DEV_UEVENT;
984                         break;
985                 case 'U':
986                         cmd = CMD_USABLE_PATHS;
987                         dev_type = DEV_UEVENT;
988                         break;
989                 case 'w':
990                         cmd = CMD_REMOVE_WWID;
991                         break;
992                 case 'W':
993                         cmd = CMD_RESET_WWIDS;
994                         break;
995                 case 'a':
996                         cmd = CMD_ADD_WWID;
997                         break;
998                 case 'R':
999                         retries = atoi(optarg);
1000                         break;
1001                 case ':':
1002                         fprintf(stderr, "Missing option argument\n");
1003                         usage(argv[0]);
1004                         exit(RTVL_FAIL);
1005                 case '?':
1006                         fprintf(stderr, "Unknown switch: %s\n", optarg);
1007                         usage(argv[0]);
1008                         exit(RTVL_FAIL);
1009                 default:
1010                         usage(argv[0]);
1011                         exit(RTVL_FAIL);
1012                 }
1013         }
1014
1015         if (getuid() != 0) {
1016                 fprintf(stderr, "need to be root\n");
1017                 exit(RTVL_FAIL);
1018         }
1019
1020         if (optind < argc) {
1021                 dev = MALLOC(FILE_NAME_SIZE);
1022
1023                 if (!dev)
1024                         goto out;
1025
1026                 strncpy(dev, argv[optind], FILE_NAME_SIZE);
1027                 if (dev_type != DEV_UEVENT)
1028                         dev_type = get_dev_type(dev);
1029                 if (dev_type == DEV_NONE) {
1030                         condlog(0, "'%s' is not a valid argument\n", dev);
1031                         goto out;
1032                 }
1033         }
1034         if (dev_type == DEV_UEVENT) {
1035                 openlog("multipath", 0, LOG_DAEMON);
1036                 setlogmask(LOG_UPTO(conf->verbosity + 3));
1037                 logsink = 1;
1038         }
1039
1040         set_max_fds(conf->max_fds);
1041
1042         libmp_udev_set_sync_support(1);
1043
1044         if (init_checkers(conf->multipath_dir)) {
1045                 condlog(0, "failed to initialize checkers");
1046                 goto out;
1047         }
1048         if (init_prio(conf->multipath_dir)) {
1049                 condlog(0, "failed to initialize prioritizers");
1050                 goto out;
1051         }
1052         /* Failing here is non-fatal */
1053         init_foreign(conf->multipath_dir);
1054         if (cmd == CMD_USABLE_PATHS) {
1055                 r = check_usable_paths(conf, dev, dev_type) ?
1056                         RTVL_FAIL : RTVL_OK;
1057                 goto out;
1058         }
1059         if (cmd == CMD_VALID_PATH &&
1060             (!dev || dev_type == DEV_DEVMAP)) {
1061                 condlog(0, "the -c option requires a path to check");
1062                 goto out;
1063         }
1064         if (cmd == CMD_VALID_PATH &&
1065             dev_type == DEV_UEVENT) {
1066                 if (!test_multipathd_socket()) {
1067                         condlog(3, "%s: daemon is not running", dev);
1068                         if (!systemd_service_enabled(dev)) {
1069                                 r = print_cmd_valid(RTVL_NO, NULL, conf);
1070                                 goto out;
1071                         }
1072                 }
1073         }
1074
1075         if (cmd == CMD_REMOVE_WWID && !dev) {
1076                 condlog(0, "the -w option requires a device");
1077                 goto out;
1078         }
1079
1080         switch(delegate_to_multipathd(cmd, dev, dev_type, conf)) {
1081         case DELEGATE_OK:
1082                 exit(RTVL_OK);
1083         case DELEGATE_ERROR:
1084                 exit(RTVL_FAIL);
1085         case NOT_DELEGATED:
1086                 break;
1087         }
1088
1089         if (cmd == CMD_RESET_WWIDS) {
1090                 struct multipath * mpp;
1091                 int i;
1092                 vector curmp;
1093
1094                 curmp = vector_alloc();
1095                 if (!curmp) {
1096                         condlog(0, "can't allocate memory for mp list");
1097                         goto out;
1098                 }
1099                 if (dm_get_maps(curmp) == 0)
1100                         r = replace_wwids(curmp) ? RTVL_FAIL : RTVL_OK;
1101                 if (r == RTVL_OK)
1102                         printf("successfully reset wwids\n");
1103                 vector_foreach_slot_backwards(curmp, mpp, i) {
1104                         vector_del_slot(curmp, i);
1105                         free_multipath(mpp, KEEP_PATHS);
1106                 }
1107                 vector_free(curmp);
1108                 goto out;
1109         }
1110         if (retries < 0)
1111                 retries = conf->remove_retries;
1112         if (conf->remove == FLUSH_ONE) {
1113                 if (dev_type == DEV_DEVMAP) {
1114                         r = dm_suspend_and_flush_map(dev, retries) ?
1115                                 RTVL_FAIL : RTVL_OK;
1116                 } else
1117                         condlog(0, "must provide a map name to remove");
1118
1119                 goto out;
1120         }
1121         else if (conf->remove == FLUSH_ALL) {
1122                 r = dm_flush_maps(retries) ? RTVL_FAIL : RTVL_OK;
1123                 goto out;
1124         }
1125         while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
1126                 condlog(3, "restart multipath configuration process");
1127
1128 out:
1129         dm_lib_release();
1130         dm_lib_exit();
1131
1132         cleanup_foreign();
1133         cleanup_prio();
1134         cleanup_checkers();
1135
1136         /*
1137          * multipath -u must exit with status 0, otherwise udev won't
1138          * import its output.
1139          */
1140         if (cmd == CMD_VALID_PATH && dev_type == DEV_UEVENT && r == RTVL_NO)
1141                 r = RTVL_OK;
1142
1143         if (dev_type == DEV_UEVENT)
1144                 closelog();
1145
1146 out_free_config:
1147         /*
1148          * Freeing config must be done after dm_lib_exit(), because
1149          * the logging function (dm_write_log()), which is called there,
1150          * references the config.
1151          */
1152         free_config(conf);
1153         conf = NULL;
1154         udev_unref(udev);
1155         if (dev)
1156                 FREE(dev);
1157 #ifdef _DEBUG_
1158         dbg_free_final(NULL);
1159 #endif
1160         return r;
1161 }