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