remove_map() should just do what the name says, remove the map. It is unexpected that it also frees the paths of the map, which can happen if these paths are in INIT_PARTIAL or INIT_REMOVED state. This is particularly wrong if remove_map is called from a code path where other data structures are still holding references to the paths in question, in particular configure() -> coalesce_paths().
Don't free paths in orphan_paths(). A follow-up patch will make sure that these paths are freed from the checker loop. Signed-off-by: Martin Wilck <[email protected]> --- libmultipath/structs.c | 4 ++++ libmultipath/structs_vec.c | 15 +++------------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/libmultipath/structs.c b/libmultipath/structs.c index e6e673f..7df5562 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -139,6 +139,10 @@ alloc_path (void) return pp; } +/* + * we don't set pp->initialized here. + * check_removed_path() relies on it being preserved. + */ void uninitialize_path(struct path *pp) { diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c index 7f5da21..3344005 100644 --- a/libmultipath/structs_vec.c +++ b/libmultipath/structs_vec.c @@ -383,18 +383,9 @@ static void orphan_paths(vector pathvec, struct multipath *mpp, const char *reas struct path * pp; vector_foreach_slot (pathvec, pp, i) { - if (pp->mpp == mpp) { - if (pp->initialized == INIT_REMOVED || - pp->initialized == INIT_PARTIAL) { - condlog(3, "%s: freeing path in %s state", - pp->dev, - pp->initialized == INIT_REMOVED ? - "removed" : "partial"); - vector_del_slot(pathvec, i--); - free_path(pp); - } else - orphan_path(pp, reason); - } else if (pp->add_when_online && + if (pp->mpp == mpp) + orphan_path(pp, reason); + else if (pp->add_when_online && strncmp(mpp->wwid, pp->wwid, WWID_SIZE) == 0) { pp->add_when_online = false; } -- 2.52.0
