13 #include "structs_vec.h"
15 #include "devmapper.h"
18 #include "discovery.h"
20 #include "configure.h"
21 #include "libdevmapper.h"
22 #include "io_err_stat.h"
23 #include "switchgroup.h"
26 * creates or updates mpp->paths reading mpp->pg
28 int update_mpp_paths(struct multipath *mpp, vector pathvec)
30 struct pathgroup * pgp;
33 bool store_failure = false;
39 !(mpp->paths = vector_alloc()))
42 vector_foreach_slot (mpp->pg, pgp, i) {
43 vector_foreach_slot (pgp->paths, pp, j) {
44 if (!find_path_by_devt(mpp->paths, pp->dev_t)) {
48 * Avoid adding removed paths to the map again
49 * when we reload it. Such paths may exist in
50 * ev_remove_paths() or if it returns failure.
52 pp1 = find_path_by_devt(pathvec, pp->dev_t);
53 if (pp1 && pp->initialized != INIT_REMOVED &&
54 store_path(mpp->paths, pp))
63 static bool guess_mpp_wwid(struct multipath *mpp)
66 struct pathgroup *pgp;
69 if (strlen(mpp->wwid) || !mpp->pg)
72 vector_foreach_slot(mpp->pg, pgp, i) {
75 vector_foreach_slot(pgp->paths, pp, j) {
76 if (pp->initialized == INIT_OK && strlen(pp->wwid)) {
77 strlcpy(mpp->wwid, pp->wwid, sizeof(mpp->wwid));
78 condlog(2, "%s: guessed WWID %s from path %s",
79 mpp->alias, mpp->wwid, pp->dev);
84 condlog(1, "%s: unable to guess WWID", mpp->alias);
89 * update_pathvec_from_dm() - update pathvec after disassemble_map()
91 * disassemble_map() may return block devices that are members in
92 * multipath maps but haven't been discovered. Check whether they
93 * need to be added to pathvec or discarded.
95 * Returns: true if immediate map reload is desirable
98 * - may delete non-existing paths and empty pathgroups from mpp
99 * - may set pp->wwid and / or mpp->wwid
100 * - calls pathinfo() on existing paths is pathinfo_flags is not 0
102 static bool update_pathvec_from_dm(vector pathvec, struct multipath *mpp,
106 struct pathgroup *pgp;
110 bool must_reload = false;
116 * This will initialize mpp->wwid with an educated guess,
117 * either from the dm uuid or from a member path with properly
120 mpp_has_wwid = guess_mpp_wwid(mpp);
122 vector_foreach_slot(mpp->pg, pgp, i) {
126 vector_foreach_slot(pgp->paths, pp, j) {
128 if (pp->mpp && pp->mpp != mpp) {
129 condlog(0, "BUG: %s: found path %s which is already in %s",
130 mpp->alias, pp->dev, pp->mpp->alias);
133 * Either we added this path to the other mpp
134 * explicitly, or we came by here earlier and
135 * decided it belonged there. In both cases,
136 * the path should remain in the other map,
137 * and be deleted here.
140 dm_fail_path(mpp->alias, pp->dev_t);
141 vector_del_slot(pgp->paths, j--);
147 * The way disassemble_map() works: If it encounters a
148 * path device which isn't found in pathvec, it adds an
149 * uninitialized struct path to pgp->paths, with only
150 * pp->dev_t filled in. Thus if pp->udev is set here,
151 * we know that the path is in pathvec already.
154 if (pathinfo_flags & ~DI_NOIO) {
155 conf = get_multipath_config();
156 pthread_cleanup_push(put_multipath_config,
158 if (pathinfo(pp, conf, pathinfo_flags) != PATHINFO_OK)
159 condlog(2, "%s: pathinfo failed for existing path %s (flags=0x%x)",
160 __func__, pp->dev, pathinfo_flags);
161 pthread_cleanup_pop(1);
164 /* If this fails, the device is not in sysfs */
165 pp->udev = get_udev_device(pp->dev_t, DEV_DEVT);
168 condlog(2, "%s: discarding non-existing path %s",
169 mpp->alias, pp->dev_t);
170 vector_del_slot(pgp->paths, j--);
177 strlcpy(pp->dev, udev_device_get_sysname(pp->udev),
179 conf = get_multipath_config();
180 pthread_cleanup_push(put_multipath_config,
182 pp->checkint = conf->checkint;
183 rc = pathinfo(pp, conf,
184 DI_SYSFS|DI_WWID|DI_BLACKLIST|DI_NOFALLBACK|pathinfo_flags);
185 pthread_cleanup_pop(1);
186 if (rc != PATHINFO_OK) {
187 condlog(1, "%s: error %d in pathinfo, discarding path",
189 vector_del_slot(pgp->paths, j--);
194 condlog(2, "%s: adding new path %s",
195 mpp->alias, pp->dev);
196 pp->initialized = INIT_PARTIAL;
197 pp->partial_retrigger_delay = 180;
198 store_path(pathvec, pp);
203 /* We don't set the map WWID from paths here */
208 * At this point, pp->udev is valid and and pp->wwid
209 * is the best we could get
211 if (*pp->wwid && strcmp(mpp->wwid, pp->wwid)) {
212 condlog(0, "%s: path %s WWID %s doesn't match, removing from map",
213 mpp->wwid, pp->dev_t, pp->wwid);
215 * This path exists, but in the wrong map.
216 * We can't reload the map from here.
217 * Make sure it isn't used in this map
218 * any more, and let the checker re-add
221 dm_fail_path(mpp->alias, pp->dev_t);
222 vector_del_slot(pgp->paths, j--);
223 orphan_path(pp, "WWID mismatch");
226 } else if (!*pp->wwid) {
227 condlog(3, "%s: setting wwid from map: %s",
229 strlcpy(pp->wwid, mpp->wwid,
233 if (VECTOR_SIZE(pgp->paths) != 0)
236 condlog(2, "%s: removing empty pathgroup %d", mpp->alias, i);
237 vector_del_slot(mpp->pg, i--);
238 free_pathgroup(pgp, KEEP_PATHS);
241 mpp->need_reload = mpp->need_reload || must_reload;
245 int adopt_paths(vector pathvec, struct multipath *mpp)
254 if (update_mpp_paths(mpp, pathvec))
257 vector_foreach_slot (pathvec, pp, i) {
258 if (!strncmp(mpp->wwid, pp->wwid, WWID_SIZE)) {
259 if (pp->size != 0 && mpp->size != 0 &&
260 pp->size != mpp->size) {
261 condlog(3, "%s: size mismatch for %s, not adding path",
262 pp->dev, mpp->alias);
265 if (pp->initialized == INIT_REMOVED)
267 if (!mpp->paths && !(mpp->paths = vector_alloc()))
270 conf = get_multipath_config();
271 pthread_cleanup_push(put_multipath_config, conf);
272 ret = pathinfo(pp, conf,
273 DI_PRIO | DI_CHECKER);
274 pthread_cleanup_pop(1);
276 condlog(3, "%s: pathinfo failed for %s",
281 if (!find_path_by_devt(mpp->paths, pp->dev_t) &&
282 store_path(mpp->paths, pp))
286 condlog(3, "%s: ownership set to %s",
287 pp->dev, mpp->alias);
292 condlog(1, "error setting ownership of %s to %s", pp->dev, mpp->alias);
296 void orphan_path(struct path *pp, const char *reason)
298 condlog(3, "%s: orphan path, %s", pp->dev, reason);
300 uninitialize_path(pp);
303 static void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
308 vector_foreach_slot (pathvec, pp, i) {
309 if (pp->mpp == mpp) {
310 if (pp->initialized == INIT_REMOVED ||
311 pp->initialized == INIT_PARTIAL) {
312 condlog(3, "%s: freeing path in %s state",
314 pp->initialized == INIT_REMOVED ?
315 "removed" : "partial");
316 vector_del_slot(pathvec, i--);
319 orphan_path(pp, reason);
324 void set_path_removed(struct path *pp)
326 struct multipath *mpp = pp->mpp;
328 orphan_path(pp, "removed");
330 * Keep link to mpp. It will be removed when the path
331 * is successfully removed from the map.
334 condlog(0, "%s: internal error: mpp == NULL", pp->dev);
336 pp->initialized = INIT_REMOVED;
340 remove_map(struct multipath *mpp, vector pathvec, vector mpvec)
344 free_pathvec(mpp->paths, KEEP_PATHS);
345 free_pgvec(mpp->pg, KEEP_PATHS);
346 mpp->paths = mpp->pg = NULL;
349 * clear references to this map
351 orphan_paths(pathvec, mpp, "map removed internally");
354 (i = find_slot(mpvec, (void *)mpp)) != -1)
355 vector_del_slot(mpvec, i);
360 free_multipath(mpp, KEEP_PATHS);
364 remove_map_by_alias(const char *alias, struct vectors * vecs)
366 struct multipath * mpp = find_mp_by_alias(vecs->mpvec, alias);
368 condlog(2, "%s: removing map by alias", alias);
369 remove_map(mpp, vecs->pathvec, vecs->mpvec);
374 remove_maps(struct vectors * vecs)
377 struct multipath * mpp;
382 vector_foreach_slot (vecs->mpvec, mpp, i) {
383 remove_map(mpp, vecs->pathvec, vecs->mpvec);
387 vector_free(vecs->mpvec);
392 extract_hwe_from_path(struct multipath * mpp)
394 struct path * pp = NULL;
397 if (mpp->hwe || !mpp->paths)
400 condlog(4, "%s: searching paths for valid hwe", mpp->alias);
401 /* doing this in two passes seems like paranoia to me */
402 vector_foreach_slot(mpp->paths, pp, i) {
403 if (pp->state == PATH_UP && pp->initialized != INIT_PARTIAL &&
404 pp->initialized != INIT_REMOVED && pp->hwe)
407 vector_foreach_slot(mpp->paths, pp, i) {
408 if ((pp->state != PATH_UP || pp->initialized == INIT_PARTIAL) &&
409 pp->initialized != INIT_REMOVED && pp->hwe)
413 if (i < VECTOR_SIZE(mpp->paths))
414 (void)set_mpp_hwe(mpp, pp);
417 condlog(3, "%s: got hwe from path %s", mpp->alias, pp->dev);
419 condlog(2, "%s: no hwe found", mpp->alias);
423 update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
431 r = dm_get_map(mpp->alias, &mpp->size, ¶ms);
433 condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting table" : "map not present");
437 if (disassemble_map(pathvec, params, mpp)) {
438 condlog(2, "%s: cannot disassemble map", mpp->alias);
445 if (dm_get_status(mpp->alias, ¶ms) != DMP_OK)
446 condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting status" : "map not present");
447 else if (disassemble_status(params, mpp))
448 condlog(2, "%s: cannot disassemble status", mpp->alias);
451 /* FIXME: we should deal with the return value here */
452 update_pathvec_from_dm(pathvec, mpp, flags);
457 static struct path *find_devt_in_pathgroups(const struct multipath *mpp,
460 struct pathgroup *pgp;
464 vector_foreach_slot(mpp->pg, pgp, j) {
465 pp = find_path_by_devt(pgp->paths, dev_t);
472 static void check_removed_paths(const struct multipath *mpp, vector pathvec)
477 vector_foreach_slot(pathvec, pp, i) {
478 if (pp->mpp == mpp &&
479 (pp->initialized == INIT_REMOVED ||
480 pp->initialized == INIT_PARTIAL) &&
481 !find_devt_in_pathgroups(mpp, pp->dev_t)) {
482 condlog(2, "%s: %s: freeing path in %s state",
484 pp->initialized == INIT_REMOVED ?
485 "removed" : "partial");
486 vector_del_slot(pathvec, i--);
492 void sync_paths(struct multipath *mpp, vector pathvec)
495 struct pathgroup *pgp;
498 vector_foreach_slot (mpp->paths, pp, i) {
500 vector_foreach_slot(mpp->pg, pgp, j) {
501 if (find_slot(pgp->paths, (void *)pp) != -1) {
507 condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
508 vector_del_slot(mpp->paths, i--);
509 orphan_path(pp, "path removed externally");
512 check_removed_paths(mpp, pathvec);
513 update_mpp_paths(mpp, pathvec);
514 vector_foreach_slot (mpp->paths, pp, i)
519 update_multipath_strings(struct multipath *mpp, vector pathvec)
521 struct pathgroup *pgp;
527 update_mpp_paths(mpp, pathvec);
528 condlog(4, "%s: %s", mpp->alias, __FUNCTION__);
530 free_multipath_attributes(mpp);
531 free_pgvec(mpp->pg, KEEP_PATHS);
534 r = update_multipath_table(mpp, pathvec, 0);
538 sync_paths(mpp, pathvec);
540 vector_foreach_slot(mpp->pg, pgp, i)
542 path_group_prio_update(pgp);
547 static void enter_recovery_mode(struct multipath *mpp)
549 unsigned int checkint;
552 if (mpp->in_recovery || mpp->no_path_retry <= 0)
555 conf = get_multipath_config();
556 checkint = conf->checkint;
557 put_multipath_config(conf);
561 * meaning of +1: retry_tick may be decremented in checkerloop before
564 mpp->in_recovery = true;
565 mpp->stat_queueing_timeouts++;
566 mpp->retry_tick = mpp->no_path_retry * checkint + 1;
567 condlog(1, "%s: Entering recovery mode: max_retries=%d",
568 mpp->alias, mpp->no_path_retry);
571 static void leave_recovery_mode(struct multipath *mpp)
573 bool recovery = mpp->in_recovery;
575 mpp->in_recovery = false;
579 * in_recovery is only ever set if mpp->no_path_retry > 0
580 * (see enter_recovery_mode()). But no_path_retry may have been
581 * changed while the map was recovering, so test it here again.
583 if (recovery && (mpp->no_path_retry == NO_PATH_RETRY_QUEUE ||
584 mpp->no_path_retry > 0)) {
585 dm_queue_if_no_path(mpp->alias, 1);
586 condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
587 condlog(1, "%s: Recovered to normal mode", mpp->alias);
591 void __set_no_path_retry(struct multipath *mpp, bool check_features)
593 bool is_queueing = false; /* assign a value to make gcc happy */
595 check_features = check_features && mpp->features != NULL;
597 is_queueing = strstr(mpp->features, "queue_if_no_path");
599 switch (mpp->no_path_retry) {
600 case NO_PATH_RETRY_UNDEF:
602 case NO_PATH_RETRY_FAIL:
603 if (!check_features || is_queueing)
604 dm_queue_if_no_path(mpp->alias, 0);
606 case NO_PATH_RETRY_QUEUE:
607 if (!check_features || !is_queueing)
608 dm_queue_if_no_path(mpp->alias, 1);
611 if (count_active_paths(mpp) > 0) {
613 * If in_recovery is set, leave_recovery_mode() takes
614 * care of dm_queue_if_no_path. Otherwise, do it here.
616 if ((!check_features || !is_queueing) &&
618 dm_queue_if_no_path(mpp->alias, 1);
619 leave_recovery_mode(mpp);
621 enter_recovery_mode(mpp);
627 sync_map_state(struct multipath *mpp)
629 struct pathgroup *pgp;
636 vector_foreach_slot (mpp->pg, pgp, i){
637 vector_foreach_slot (pgp->paths, pp, j){
638 if (pp->state == PATH_UNCHECKED ||
639 pp->state == PATH_WILD ||
640 pp->state == PATH_DELAYED)
642 if (mpp->ghost_delay_tick > 0)
644 if ((pp->dmstate == PSTATE_FAILED ||
645 pp->dmstate == PSTATE_UNDEF) &&
646 (pp->state == PATH_UP || pp->state == PATH_GHOST))
647 dm_reinstate_path(mpp->alias, pp->dev_t);
648 else if ((pp->dmstate == PSTATE_ACTIVE ||
649 pp->dmstate == PSTATE_UNDEF) &&
650 (pp->state == PATH_DOWN ||
651 pp->state == PATH_SHAKY)) {
652 condlog(2, "sync_map_state: failing %s state %d dmstate %d",
653 pp->dev, pp->state, pp->dmstate);
654 dm_fail_path(mpp->alias, pp->dev_t);
661 find_existing_alias (struct multipath * mpp,
662 struct vectors *vecs)
664 struct multipath * mp;
667 vector_foreach_slot (vecs->mpvec, mp, i)
668 if (strncmp(mp->wwid, mpp->wwid, WWID_SIZE - 1) == 0) {
669 strlcpy(mpp->alias_old, mp->alias, WWID_SIZE);
674 struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp,
677 struct multipath * mpp;
678 struct config *conf = NULL;
680 if (!strlen(pp->wwid))
683 if (!(mpp = alloc_multipath()))
686 conf = get_multipath_config();
687 mpp->mpe = find_mpe(conf->mptable, pp->wwid);
688 put_multipath_config(conf);
691 * We need to call this before select_alias(),
692 * because that accesses hwe properties.
694 if (pp->hwe && !set_mpp_hwe(mpp, pp))
697 strcpy(mpp->wwid, pp->wwid);
698 find_existing_alias(mpp, vecs);
699 if (select_alias(conf, mpp))
701 mpp->size = pp->size;
703 if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp ||
704 find_slot(mpp->paths, pp) == -1)
708 if (!vector_alloc_slot(vecs->mpvec))
711 vector_set_slot(vecs->mpvec, mpp);
717 remove_map(mpp, vecs->pathvec, vecs->mpvec);
721 int verify_paths(struct multipath *mpp)
730 vector_foreach_slot (mpp->paths, pp, i) {
732 * see if path is in sysfs
734 if (!pp->udev || sysfs_attr_get_value(pp->udev, "dev",
735 pp->dev_t, BLK_DEV_SIZE) < 0) {
736 if (pp->state != PATH_DOWN) {
737 condlog(1, "%s: removing valid path %s in state %d",
738 mpp->alias, pp->dev, pp->state);
740 condlog(2, "%s: failed to access path %s",
741 mpp->alias, pp->dev);
744 vector_del_slot(mpp->paths, i);
748 * Don't delete path from pathvec yet. We'll do this
749 * after the path has been removed from the map, in
752 set_path_removed(pp);
754 condlog(4, "%s: verified path %s dev_t %s",
755 mpp->alias, pp->dev, pp->dev_t);
762 * mpp->no_path_retry:
763 * -2 (QUEUE) : queue_if_no_path enabled, never turned off
764 * -1 (FAIL) : fail_if_no_path
765 * 0 (UNDEF) : nothing
766 * >0 : queue_if_no_path enabled, turned off after polling n times
768 void update_queue_mode_del_path(struct multipath *mpp)
770 int active = count_active_paths(mpp);
773 enter_recovery_mode(mpp);
774 if (mpp->no_path_retry != NO_PATH_RETRY_QUEUE)
775 mpp->stat_map_failures++;
777 condlog(2, "%s: remaining active paths: %d", mpp->alias, active);
780 void update_queue_mode_add_path(struct multipath *mpp)
782 int active = count_active_paths(mpp);
785 leave_recovery_mode(mpp);
786 condlog(2, "%s: remaining active paths: %d", mpp->alias, active);
789 vector get_used_hwes(const struct _vector *pathvec)
794 vector v = vector_alloc();
799 vector_foreach_slot(pathvec, pp, i) {
800 vector_foreach_slot_backwards(pp->hwe, hwe, j) {
801 vector_find_or_add_slot(v, hwe);