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