From fb655da18aefccaa09c70036b08c88a03609ec45 Mon Sep 17 00:00:00 2001 From: wangjufeng Date: Sat, 21 Mar 2020 22:23:10 +0800 Subject: [PATCH] multipathd: fix check_path could not resume path state For some unknown reason, after network recovery from disconnection, the paths in a multipath are still in fail state. Use gdb attached multipathd, the paths seem to be changed by orphan_path function, pp->initialized is INIT_OK while pp->mpp is NULL, pp->dmstate is PSTATE_UNDEF, pp->fd is -1. And the multipath could not be found in gvecs->mpvec while it could be found by dmsetup table command. It will lead to that the path state could not be activated by check_path even if the iscsi device is already available. This patch intend to add the multipath map again to avoid IO failure or IO blocked when the above phenomenon occur. Signed-off-by: wangjufeng Reviewed-by: linfeilong --- multipathd/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/multipathd/main.c b/multipathd/main.c index 8baf9ab..4ca622c 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -1962,10 +1962,59 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks) struct config *conf; int marginal_pathgroups, marginal_changed = 0; int ret; + char *param; + int major; + int minor; + int invalid = 0; + char dev_path[PATH_SIZE]; + char *alias = NULL; + struct multipath *mpp; if ((pp->initialized == INIT_OK || - pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp) - return 0; + pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp) { + if (pp->initialized == INIT_OK && !pp->mpp && + pp->dmstate == PSTATE_UNDEF && pp->fd == -1) { + mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); + if (mpp != NULL) { + return 0; + } + /* + * If a multipath is not in gvecs->mpvec, while it could be found in + * device-mapper devices. It should be mapped again, or multipathd + * can not add it again because of that check_path early return. + */ + param = convert_dev(pp->wwid, 0); + conf = get_multipath_config(); + pthread_cleanup_push(put_multipath_config, conf); + if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0) { + invalid = 1; + } + pthread_cleanup_pop(1); + if (invalid) { + condlog(2, "%s: map blacklisted", param); + return 0; + } + + if (dm_get_major_minor(param, &major, &minor) < 0) { + return 0; + } else { + sprintf(dev_path, "dm-%d", minor); + alias = dm_mapname(major, minor); + if (!alias) { + condlog(2, "fail to get alias of %s %d:%d", param, major, minor); + return 0; + } + if (ev_add_map(dev_path, alias, vecs)) { + condlog(2, "fail to add map for mpp %s", alias); + return 0; + } else { + condlog(2, "success to add map for mpp %s", alias); + } + } + } else { + return 0; + } + } if (pp->tick) pp->tick -= (pp->tick > ticks) ? ticks : pp->tick; -- 1.8.3.1