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