From: Martin Wilck <mwi...@suse.com>

Introduce a new state for pp->initialized, INIT_REMOVED. This state
means that the path is about to be removed, either by a remove uevent
or by the operator. It will normally be a very short-lived state, because
the path will be deleted from pathvec quickly after setting this state.
Only if the path is member of a multipath map, and reloading the map
fails, this state will persist until a later map reload or flush eventually
cancels the membership in the map.

Paths in INIT_REMOVED state are treated as if they didn't exist.

Signed-off-by: Martin Wilck <mwi...@suse.com>
---
 libmultipath/discovery.c   |  4 ++++
 libmultipath/structs.h     |  5 +++++
 libmultipath/structs_vec.c | 17 +++++++++++++++++
 libmultipath/structs_vec.h |  1 +
 multipathd/main.c          |  5 +++--
 5 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index c202d58..efcef67 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -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
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 894099d..1f0a78a 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -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 {
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 05c8626..27d6547 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -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)
 {
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index 4b3b8b7..cf7d569 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -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);
diff --git a/multipathd/main.c b/multipathd/main.c
index cd0e29b..4a5aa17 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -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)
-- 
2.26.2


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to