@@ -2078,6 +2078,10 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
if (!pp || !conf)
return PATHINFO_FAILED;
+ /* Treat removed paths as if they didn't exist */
+ if (pp->initialized == INIT_REMOVED)
+ return PATHINFO_FAILED;
+
/*
* For behavior backward-compatibility with multipathd,
* the blacklisting by filter_property|devnode() is not
@@ -193,6 +193,11 @@ enum initialized_states {
INIT_MISSING_UDEV,
INIT_REQUESTED_UDEV,
INIT_OK,
+ /*
+ * INIT_REMOVED: supposed to be removed from pathvec, but still
+ * mapped by some multipath map because of map reload failure.
+ */
+ INIT_REMOVED,
};
enum prkey_sources {
@@ -113,6 +113,23 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
}
}
+void set_path_removed(struct path *pp)
+{
+ struct multipath *mpp = pp->mpp;
+
+ orphan_path(pp, "removed");
+ /*
+ * Keep link to mpp. It will be removed when the path
+ * is successfully removed from the map.
+ */
+ if (!mpp) {
+ condlog(0, "%s: internal error: mpp == NULL", pp->dev);
+ return;
+ }
+ pp->mpp = mpp;
+ pp->initialized = INIT_REMOVED;
+}
+
void
remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec)
{
@@ -18,6 +18,7 @@ int adopt_paths (vector pathvec, struct multipath * mpp);
void orphan_paths(vector pathvec, struct multipath *mpp,
const char *reason);
void orphan_path (struct path * pp, const char *reason);
+void set_path_removed(struct path *pp);
int verify_paths(struct multipath * mpp, struct vectors * vecs);
int update_mpp_paths(struct multipath * mpp, vector pathvec);
@@ -1962,8 +1962,9 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
int marginal_pathgroups, marginal_changed = 0;
int ret;
- if ((pp->initialized == INIT_OK ||
- pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp)
+ if (((pp->initialized == INIT_OK ||
+ pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp) ||
+ pp->initialized == INIT_REMOVED)
return 0;
if (pp->tick)