7f5e065590f2163c1749b851502298db0b162a65
[multipath-tools/.git] / libmultipath / configure.c
1 /*
2  * Copyright (c) 2003, 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Kiyoshi Ueda, NEC
5  * Copyright (c) 2005 Patrick Caulfield, Redhat
6  * Copyright (c) 2005 Edward Goggin, EMC
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/file.h>
14 #include <errno.h>
15 #include <libdevmapper.h>
16 #include <libudev.h>
17
18 #include "checkers.h"
19 #include "vector.h"
20 #include "memory.h"
21 #include "devmapper.h"
22 #include "defaults.h"
23 #include "structs.h"
24 #include "structs_vec.h"
25 #include "dmparser.h"
26 #include "config.h"
27 #include "blacklist.h"
28 #include "propsel.h"
29 #include "discovery.h"
30 #include "debug.h"
31 #include "switchgroup.h"
32 #include "print.h"
33 #include "configure.h"
34 #include "pgpolicies.h"
35 #include "dict.h"
36 #include "alias.h"
37 #include "prio.h"
38 #include "util.h"
39 #include "uxsock.h"
40 #include "wwids.h"
41
42 extern int
43 setup_map (struct multipath * mpp, char * params, int params_size)
44 {
45         struct pathgroup * pgp;
46         int i;
47
48         /*
49          * don't bother if devmap size is unknown
50          */
51         if (mpp->size <= 0) {
52                 condlog(3, "%s: devmap size is unknown", mpp->alias);
53                 return 1;
54         }
55
56         /*
57          * free features, selector, and hwhandler properties if they are being reused
58          */
59         free_multipath_attributes(mpp);
60
61         /*
62          * properties selectors
63          */
64         select_pgfailback(mpp);
65         select_pgpolicy(mpp);
66         select_selector(mpp);
67         select_features(mpp);
68         select_hwhandler(mpp);
69         select_rr_weight(mpp);
70         select_minio(mpp);
71         select_no_path_retry(mpp);
72         select_mode(mpp);
73         select_uid(mpp);
74         select_gid(mpp);
75         select_fast_io_fail(mpp);
76         select_dev_loss(mpp);
77         select_reservation_key(mpp);
78         select_retain_hwhandler(mpp);
79
80         sysfs_set_scsi_tmo(mpp);
81         /*
82          * assign paths to path groups -- start with no groups and all paths
83          * in mpp->paths
84          */
85         if (mpp->pg) {
86                 vector_foreach_slot (mpp->pg, pgp, i)
87                         free_pathgroup(pgp, KEEP_PATHS);
88
89                 vector_free(mpp->pg);
90                 mpp->pg = NULL;
91         }
92         if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
93                 return 1;
94
95         mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
96
97         /*
98          * ponders each path group and determine highest prio pg
99          * to switch over (default to first)
100          */
101         mpp->bestpg = select_path_group(mpp);
102
103         /*
104          * transform the mp->pg vector of vectors of paths
105          * into a mp->params strings to feed the device-mapper
106          */
107         if (assemble_map(mpp, params, params_size)) {
108                 condlog(0, "%s: problem assembing map", mpp->alias);
109                 return 1;
110         }
111         return 0;
112 }
113
114 static void
115 compute_pgid(struct pathgroup * pgp)
116 {
117         struct path * pp;
118         int i;
119
120         vector_foreach_slot (pgp->paths, pp, i)
121                 pgp->id ^= (long)pp;
122 }
123
124 static int
125 pgcmp (struct multipath * mpp, struct multipath * cmpp)
126 {
127         int i, j;
128         struct pathgroup * pgp;
129         struct pathgroup * cpgp;
130         int r = 0;
131
132         if (!mpp)
133                 return 0;
134
135         vector_foreach_slot (mpp->pg, pgp, i) {
136                 compute_pgid(pgp);
137
138                 vector_foreach_slot (cmpp->pg, cpgp, j) {
139                         if (pgp->id == cpgp->id &&
140                             !pathcmp(pgp, cpgp)) {
141                                 r = 0;
142                                 break;
143                         }
144                         r++;
145                 }
146                 if (r)
147                         return r;
148         }
149         return r;
150 }
151
152 static void
153 select_action (struct multipath * mpp, vector curmp, int force_reload)
154 {
155         struct multipath * cmpp;
156         struct multipath * cmpp_by_name;
157
158         cmpp = find_mp_by_wwid(curmp, mpp->wwid);
159         cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
160
161         if (!cmpp_by_name) {
162                 if (cmpp) {
163                         condlog(2, "%s: rename %s to %s", mpp->wwid,
164                                 cmpp->alias, mpp->alias);
165                         strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
166                         mpp->action = ACT_RENAME;
167                         return;
168                 }
169                 mpp->action = ACT_CREATE;
170                 condlog(3, "%s: set ACT_CREATE (map does not exist)",
171                         mpp->alias);
172                 return;
173         }
174
175         if (!cmpp) {
176                 condlog(2, "%s: remove (wwid changed)", mpp->alias);
177                 dm_flush_map(mpp->alias);
178                 strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE);
179                 drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
180                 mpp->action = ACT_CREATE;
181                 condlog(3, "%s: set ACT_CREATE (map wwid change)",
182                         mpp->alias);
183                 return;
184         }
185
186         if (cmpp != cmpp_by_name) {
187                 condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
188                         mpp->wwid, cmpp->alias, mpp->alias,
189                         mpp->alias, cmpp_by_name->wwid);
190                 mpp->action = ACT_NOTHING;
191                 return;
192         }
193
194         if (pathcount(mpp, PATH_UP) == 0) {
195                 mpp->action = ACT_NOTHING;
196                 condlog(3, "%s: set ACT_NOTHING (no usable path)",
197                         mpp->alias);
198                 return;
199         }
200         if (force_reload) {
201                 mpp->action = ACT_RELOAD;
202                 condlog(3, "%s: set ACT_RELOAD (forced by user)",
203                         mpp->alias);
204                 return;
205         }
206         if (cmpp->size != mpp->size) {
207                 mpp->action = ACT_RESIZE;
208                 condlog(3, "%s: set ACT_RESIZE (size change)",
209                         mpp->alias);
210                 return;
211         }
212         if (!mpp->no_path_retry &&
213             (strlen(cmpp->features) != strlen(mpp->features) ||
214              strcmp(cmpp->features, mpp->features))) {
215                 mpp->action =  ACT_RELOAD;
216                 condlog(3, "%s: set ACT_RELOAD (features change)",
217                         mpp->alias);
218                 return;
219         }
220         if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
221             (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
222              strncmp(cmpp->hwhandler, mpp->hwhandler,
223                     strlen(mpp->hwhandler)))) {
224                 mpp->action = ACT_RELOAD;
225                 condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
226                         mpp->alias);
227                 return;
228         }
229         if (!cmpp->selector || strncmp(cmpp->selector, mpp->selector,
230                     strlen(mpp->selector))) {
231                 mpp->action = ACT_RELOAD;
232                 condlog(3, "%s: set ACT_RELOAD (selector change)",
233                         mpp->alias);
234                 return;
235         }
236         if (cmpp->minio != mpp->minio) {
237                 mpp->action = ACT_RELOAD;
238                 condlog(3, "%s: set ACT_RELOAD (minio change, %u->%u)",
239                         mpp->alias, cmpp->minio, mpp->minio);
240                 return;
241         }
242         if (!cmpp->pg || VECTOR_SIZE(cmpp->pg) != VECTOR_SIZE(mpp->pg)) {
243                 mpp->action = ACT_RELOAD;
244                 condlog(3, "%s: set ACT_RELOAD (path group number change)",
245                         mpp->alias);
246                 return;
247         }
248         if (pgcmp(mpp, cmpp)) {
249                 mpp->action = ACT_RELOAD;
250                 condlog(3, "%s: set ACT_RELOAD (path group topology change)",
251                         mpp->alias);
252                 return;
253         }
254         if (cmpp->nextpg != mpp->bestpg) {
255                 mpp->action = ACT_SWITCHPG;
256                 condlog(3, "%s: set ACT_SWITCHPG (next path group change)",
257                         mpp->alias);
258                 return;
259         }
260         mpp->action = ACT_NOTHING;
261         condlog(3, "%s: set ACT_NOTHING (map unchanged)",
262                 mpp->alias);
263         return;
264 }
265
266 extern int
267 reinstate_paths (struct multipath * mpp)
268 {
269         int i, j;
270         struct pathgroup * pgp;
271         struct path * pp;
272
273         if (!mpp->pg)
274                 return 0;
275
276         vector_foreach_slot (mpp->pg, pgp, i) {
277                 if (!pgp->paths)
278                         continue;
279
280                 vector_foreach_slot (pgp->paths, pp, j) {
281                         if (pp->state != PATH_UP &&
282                             (pgp->status == PGSTATE_DISABLED ||
283                              pgp->status == PGSTATE_ACTIVE))
284                                 continue;
285
286                         if (pp->dmstate == PSTATE_FAILED) {
287                                 if (dm_reinstate_path(mpp->alias, pp->dev_t))
288                                         condlog(0, "%s: error reinstating",
289                                                 pp->dev);
290                         }
291                 }
292         }
293         return 0;
294 }
295
296 static int
297 lock_multipath (struct multipath * mpp, int lock)
298 {
299         struct pathgroup * pgp;
300         struct path * pp;
301         int i, j;
302         int x, y;
303
304         if (!mpp || !mpp->pg)
305                 return 0;
306
307         vector_foreach_slot (mpp->pg, pgp, i) {
308                 if (!pgp->paths)
309                         continue;
310                 vector_foreach_slot(pgp->paths, pp, j) {
311                         if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
312                             errno == EWOULDBLOCK)
313                                 goto fail;
314                         else if (!lock)
315                                 flock(pp->fd, LOCK_UN);
316                 }
317         }
318         return 0;
319 fail:
320         vector_foreach_slot (mpp->pg, pgp, x) {
321                 if (x > i)
322                         return 1;
323                 if (!pgp->paths)
324                         continue;
325                 vector_foreach_slot(pgp->paths, pp, y) {
326                         if (x == i && y >= j)
327                                 return 1;
328                         flock(pp->fd, LOCK_UN);
329                 }
330         }
331         return 1;
332 }
333
334 /*
335  * Return value:
336  */
337 #define DOMAP_RETRY     -1
338 #define DOMAP_FAIL      0
339 #define DOMAP_OK        1
340 #define DOMAP_EXIST     2
341 #define DOMAP_DRY       3
342
343 extern int
344 domap (struct multipath * mpp, char * params)
345 {
346         int r = 0;
347
348         /*
349          * last chance to quit before touching the devmaps
350          */
351         if (conf->dry_run && mpp->action != ACT_NOTHING) {
352                 print_multipath_topology(mpp, conf->verbosity);
353                 return DOMAP_DRY;
354         }
355
356         switch (mpp->action) {
357         case ACT_REJECT:
358         case ACT_NOTHING:
359                 return DOMAP_EXIST;
360
361         case ACT_SWITCHPG:
362                 dm_switchgroup(mpp->alias, mpp->bestpg);
363                 /*
364                  * we may have avoided reinstating paths because there where in
365                  * active or disabled PG. Now that the topology has changed,
366                  * retry.
367                  */
368                 reinstate_paths(mpp);
369                 return DOMAP_EXIST;
370
371         case ACT_CREATE:
372                 if (lock_multipath(mpp, 1)) {
373                         condlog(3, "%s: failed to create map (in use)",
374                                 mpp->alias);
375                         return DOMAP_RETRY;
376                 }
377
378                 if (dm_map_present(mpp->alias)) {
379                         condlog(3, "%s: map already present", mpp->alias);
380                         lock_multipath(mpp, 0);
381                         break;
382                 }
383
384                 r = dm_addmap_create(mpp, params);
385
386                 if (!r)
387                         r = dm_addmap_create_ro(mpp, params);
388
389                 lock_multipath(mpp, 0);
390                 break;
391
392         case ACT_RELOAD:
393                 r = dm_addmap_reload(mpp, params);
394                 if (!r)
395                         r = dm_addmap_reload_ro(mpp, params);
396                 if (r)
397                         r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias);
398                 break;
399
400         case ACT_RESIZE:
401                 r = dm_addmap_reload(mpp, params);
402                 if (!r)
403                         r = dm_addmap_reload_ro(mpp, params);
404                 if (r)
405                         r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1);
406                 break;
407
408         case ACT_RENAME:
409                 r = dm_rename(mpp->alias_old, mpp->alias);
410                 break;
411
412         default:
413                 break;
414         }
415
416         if (r) {
417                 /*
418                  * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
419                  * succeeded
420                  */
421                 if (mpp->action == ACT_CREATE)
422                         remember_wwid(mpp->wwid);
423                 if (!conf->daemon) {
424                         /* multipath client mode */
425                         dm_switchgroup(mpp->alias, mpp->bestpg);
426                 } else  {
427                         /* multipath daemon mode */
428                         mpp->stat_map_loads++;
429                         condlog(2, "%s: load table [0 %llu %s %s]", mpp->alias,
430                                 mpp->size, TGT_MPATH, params);
431                         /*
432                          * Required action is over, reset for the stateful daemon.
433                          * But don't do it for creation as we use in the caller the
434                          * mpp->action to figure out whether to start the watievent checker.
435                          */
436                         if (mpp->action != ACT_CREATE)
437                                 mpp->action = ACT_NOTHING;
438                 }
439                 dm_setgeometry(mpp);
440                 return DOMAP_OK;
441         }
442         return DOMAP_FAIL;
443 }
444
445 static int
446 deadmap (struct multipath * mpp)
447 {
448         int i, j;
449         struct pathgroup * pgp;
450         struct path * pp;
451
452         if (!mpp->pg)
453                 return 1;
454
455         vector_foreach_slot (mpp->pg, pgp, i) {
456                 if (!pgp->paths)
457                         continue;
458
459                 vector_foreach_slot (pgp->paths, pp, j)
460                         if (strlen(pp->dev))
461                                 return 0; /* alive */
462         }
463
464         return 1; /* dead */
465 }
466
467 int check_daemon(void)
468 {
469         int fd;
470         char *reply;
471         size_t len;
472         int ret = 0;
473
474         fd = ux_socket_connect(DEFAULT_SOCKET);
475         if (fd == -1)
476                 return 0;
477
478         if (send_packet(fd, "show daemon", 12) != 0)
479                 goto out;
480         if (recv_packet(fd, &reply, &len) != 0)
481                 goto out;
482
483         if (strstr(reply, "shutdown"))
484                 goto out_free;
485
486         ret = 1;
487
488 out_free:
489         FREE(reply);
490 out:
491         close(fd);
492         return ret;
493 }
494
495 extern int
496 coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload)
497 {
498         int r = 1;
499         int k, i;
500         char empty_buff[WWID_SIZE];
501         char params[PARAMS_SIZE];
502         struct multipath * mpp;
503         struct path * pp1;
504         struct path * pp2;
505         vector curmp = vecs->mpvec;
506         vector pathvec = vecs->pathvec;
507
508         memset(empty_buff, 0, WWID_SIZE);
509
510         if (force_reload) {
511                 vector_foreach_slot (pathvec, pp1, k) {
512                         pp1->mpp = NULL;
513                 }
514         }
515         vector_foreach_slot (pathvec, pp1, k) {
516                 /* skip this path for some reason */
517
518                 /* 1. if path has no unique id or wwid blacklisted */
519                 if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
520                     filter_path(conf, pp1) > 0) {
521                         orphan_path(pp1);
522                         continue;
523                 }
524
525                 /* 2. if path already coalesced */
526                 if (pp1->mpp)
527                         continue;
528
529                 /* 3. if path has disappeared */
530                 if (!pp1->size) {
531                         orphan_path(pp1);
532                         continue;
533                 }
534
535                 /* 4. path is out of scope */
536                 if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
537                         continue;
538
539                 /*
540                  * at this point, we know we really got a new mp
541                  */
542                 mpp = add_map_with_path(vecs, pp1, 0);
543                 if (!mpp)
544                         return 1;
545
546                 if (pp1->priority == PRIO_UNDEF)
547                         mpp->action = ACT_REJECT;
548
549                 if (!mpp->paths) {
550                         condlog(0, "%s: skip coalesce (no paths)", mpp->alias);
551                         remove_map(mpp, vecs, 0);
552                         continue;
553                 }
554
555                 for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
556                         pp2 = VECTOR_SLOT(pathvec, i);
557
558                         if (strcmp(pp1->wwid, pp2->wwid))
559                                 continue;
560
561                         if (!pp2->size)
562                                 continue;
563
564                         if (pp2->size != mpp->size) {
565                                 /*
566                                  * ouch, avoid feeding that to the DM
567                                  */
568                                 condlog(0, "%s: size %llu, expected %llu. "
569                                         "Discard", pp2->dev_t, pp2->size,
570                                         mpp->size);
571                                 mpp->action = ACT_REJECT;
572                         }
573                         if (pp2->priority == PRIO_UNDEF)
574                                 mpp->action = ACT_REJECT;
575                 }
576                 verify_paths(mpp, vecs, NULL);
577
578                 params[0] = '\0';
579                 if (setup_map(mpp, params, PARAMS_SIZE)) {
580                         remove_map(mpp, vecs, 0);
581                         continue;
582                 }
583
584                 if (mpp->action == ACT_UNDEF)
585                         select_action(mpp, curmp, force_reload);
586
587                 r = domap(mpp, params);
588
589                 if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
590                         condlog(3, "%s: domap (%u) failure "
591                                    "for create/reload map",
592                                 mpp->alias, r);
593                         if (r == DOMAP_FAIL) {
594                                 condlog(2, "%s: %s map",
595                                         mpp->alias, (mpp->action == ACT_CREATE)?
596                                         "ignoring" : "removing");
597                                 remove_map(mpp, vecs, 0);
598                                 continue;
599                         } else /* if (r == DOMAP_RETRY) */
600                                 return r;
601                 }
602                 if (r == DOMAP_DRY)
603                         continue;
604
605                 if (!conf->daemon && !conf->allow_queueing && !check_daemon()) {
606                         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
607                             mpp->no_path_retry != NO_PATH_RETRY_FAIL)
608                                 condlog(3, "%s: multipathd not running, unset "
609                                         "queue_if_no_path feature", mpp->alias);
610                         if (!dm_queue_if_no_path(mpp->alias, 0))
611                                 remove_feature(&mpp->features,
612                                                "queue_if_no_path");
613                 }
614                 else if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
615                         if (mpp->no_path_retry == NO_PATH_RETRY_FAIL) {
616                                 condlog(3, "%s: unset queue_if_no_path feature",
617                                         mpp->alias);
618                                 if (!dm_queue_if_no_path(mpp->alias, 0))
619                                         remove_feature(&mpp->features,
620                                                        "queue_if_no_path");
621                         } else {
622                                 condlog(3, "%s: set queue_if_no_path feature",
623                                         mpp->alias);
624                                 if (!dm_queue_if_no_path(mpp->alias, 1))
625                                         add_feature(&mpp->features,
626                                                     "queue_if_no_path");
627                         }
628                 }
629
630                 if (!conf->daemon && mpp->action != ACT_NOTHING)
631                         print_multipath_topology(mpp, conf->verbosity);
632
633                 if (newmp) {
634                         if (mpp->action != ACT_REJECT) {
635                                 if (!vector_alloc_slot(newmp))
636                                         return 1;
637                                 vector_set_slot(newmp, mpp);
638                         }
639                         else
640                                 remove_map(mpp, vecs, 0);
641                 }
642         }
643         /*
644          * Flush maps with only dead paths (ie not in sysfs)
645          * Keep maps with only failed paths
646          */
647         if (newmp) {
648                 vector_foreach_slot (newmp, mpp, i) {
649                         char alias[WWID_SIZE];
650                         int j;
651
652                         if (!deadmap(mpp))
653                                 continue;
654
655                         strncpy(alias, mpp->alias, WWID_SIZE);
656
657                         if ((j = find_slot(newmp, (void *)mpp)) != -1)
658                                 vector_del_slot(newmp, j);
659
660                         remove_map(mpp, vecs, 0);
661
662                         if (dm_flush_map(alias))
663                                 condlog(2, "%s: remove failed (dead)",
664                                         alias);
665                         else
666                                 condlog(2, "%s: remove (dead)", alias);
667                 }
668         }
669         return 0;
670 }
671
672 /*
673  * returns:
674  * 0 - success
675  * 1 - failure
676  * 2 - blacklist
677  */
678 extern int
679 get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
680 {
681         int ret = 1;
682         struct path * pp;
683         char buff[FILE_NAME_SIZE];
684         char * refwwid = NULL, tmpwwid[WWID_SIZE];
685
686         if (!wwid)
687                 return 1;
688         *wwid = NULL;
689
690         if (dev_type == DEV_NONE)
691                 return 1;
692
693         if (dev_type == DEV_DEVNODE) {
694                 if (basenamecpy(dev, buff, FILE_NAME_SIZE) == 0) {
695                         condlog(1, "basename failed for '%s' (%s)",
696                                 dev, buff);
697                         return 1;
698                 }
699
700                 pp = find_path_by_dev(pathvec, buff);
701                 if (!pp) {
702                         struct udev_device *udevice = udev_device_new_from_subsystem_sysname(conf->udev, "block", buff);
703
704                         if (!udevice) {
705                                 condlog(2, "%s: can't get udev device", buff);
706                                 return 1;
707                         }
708                         ret = store_pathinfo(pathvec, conf->hwtable, udevice,
709                                              DI_SYSFS | DI_WWID, &pp);
710                         udev_device_unref(udevice);
711                         if (!pp) {
712                                 if (ret == 1)
713                                         condlog(0, "%s can't store path info",
714                                                 buff);
715                                 return ret;
716                         }
717                 }
718                 refwwid = pp->wwid;
719                 goto out;
720         }
721
722         if (dev_type == DEV_DEVT) {
723                 strchop(dev);
724                 pp = find_path_by_devt(pathvec, dev);
725                 if (!pp) {
726                         struct udev_device *udevice = udev_device_new_from_devnum(conf->udev, 'b', parse_devt(dev));
727
728                         if (!udevice) {
729                                 condlog(2, "%s: can't get udev device", dev);
730                                 return 1;
731                         }
732                         ret = store_pathinfo(pathvec, conf->hwtable, udevice,
733                                              DI_SYSFS | DI_WWID, &pp);
734                         udev_device_unref(udevice);
735                         if (!pp) {
736                                 if (ret == 1)
737                                         condlog(0, "%s can't store path info",
738                                                 buff);
739                                 return ret;
740                         }
741                 }
742                 refwwid = pp->wwid;
743                 goto out;
744         }
745         if (dev_type == DEV_DEVMAP) {
746
747                 if (((dm_get_uuid(dev, tmpwwid)) == 0) && (strlen(tmpwwid))) {
748                         refwwid = tmpwwid;
749                         goto check;
750                 }
751
752                 /*
753                  * may be a binding
754                  */
755                 if (get_user_friendly_wwid(dev, tmpwwid,
756                                            conf->bindings_file) == 0) {
757                         refwwid = tmpwwid;
758                         goto check;
759                 }
760
761                 /*
762                  * or may be an alias
763                  */
764                 refwwid = get_mpe_wwid(dev);
765
766                 /*
767                  * or directly a wwid
768                  */
769                 if (!refwwid)
770                         refwwid = dev;
771
772 check:
773                 if (refwwid && strlen(refwwid)) {
774                         if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
775                                         refwwid) > 0)
776                         return 2;
777                 }
778         }
779 out:
780         if (refwwid && strlen(refwwid)) {
781                 *wwid = STRDUP(refwwid);
782                 return 0;
783         }
784
785         return 1;
786 }
787
788 extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh)
789 {
790         char params[PARAMS_SIZE] = {0};
791         struct path *pp;
792         int i, r;
793
794         update_mpp_paths(mpp, vecs->pathvec);
795         if (refresh) {
796                 vector_foreach_slot (mpp->paths, pp, i) {
797                         r = pathinfo(pp, conf->hwtable, DI_PRIO);
798                         if (r) {
799                                 condlog(2, "%s: failed to refresh pathinfo",
800                                         mpp->alias);
801                                 return 1;
802                         }
803                 }
804         }
805         if (setup_map(mpp, params, PARAMS_SIZE)) {
806                 condlog(0, "%s: failed to setup map", mpp->alias);
807                 return 1;
808         }
809         select_action(mpp, vecs->mpvec, 1);
810
811         r = domap(mpp, params);
812         if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
813                 condlog(3, "%s: domap (%u) failure "
814                         "for reload map", mpp->alias, r);
815                 return 1;
816         }
817         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
818                 if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
819                         dm_queue_if_no_path(mpp->alias, 0);
820                 else
821                         dm_queue_if_no_path(mpp->alias, 1);
822         }
823
824         return 0;
825 }