free_multipath() is now always called with free_paths == KEEP_PATHS. Remove the argument and the code for freeing paths.
We must make sure that if we free a struct mpp, no references remain to it in any of the paths that are referenced by it. However, this means that we must always free struct multipath before freeing any paths that it links to. orphan_paths() clears possible references in other paths, which are not referenced from mpp->pg and mpp->paths, which we do mostly for safety. But orphan_paths() also handles the add_when_online logic, and must thus be called before free_multipath() in remove_map(). Suggested-by: Benjamin Marzinski <[email protected]> Signed-off-by: Martin Wilck <[email protected]> --- libmultipath/devmapper.c | 2 +- libmultipath/structs.c | 37 ++++++++++++++++--------------------- libmultipath/structs.h | 2 +- libmultipath/structs_vec.c | 6 ++++-- multipath/main.c | 2 +- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c index 8e632ba..e3870f5 100644 --- a/libmultipath/devmapper.c +++ b/libmultipath/devmapper.c @@ -1279,7 +1279,7 @@ int dm_get_maps(vector mp) switch (dm_get_multipath(names->name, &mpp)) { case DMP_OK: if (!vector_alloc_slot(mp)) { - free_multipath(mpp, KEEP_PATHS); + free_multipath(mpp); return 1; } vector_set_slot(mp, mpp); diff --git a/libmultipath/structs.c b/libmultipath/structs.c index ec8779c..6f2468d 100644 --- a/libmultipath/structs.c +++ b/libmultipath/structs.c @@ -296,9 +296,12 @@ void free_multipath_attributes(struct multipath *mpp) } } -void -free_multipath (struct multipath * mpp, enum free_path_mode free_paths) +void free_multipath(struct multipath *mpp) { + struct pathgroup *pg; + struct path *pp; + int i, j; + if (!mpp) return; @@ -308,23 +311,15 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths) free(mpp->alias); mpp->alias = NULL; } - - if (!free_paths && mpp->pg) { - struct pathgroup *pgp; - struct path *pp; - int i, j; - - /* - * Make sure paths carry no reference to this mpp any more - */ - vector_foreach_slot(mpp->pg, pgp, i) { - vector_foreach_slot(pgp->paths, pp, j) - if (pp->mpp == mpp) - pp->mpp = NULL; - } + vector_foreach_slot (mpp->pg, pg, i) { + vector_foreach_slot (pg->paths, pp, j) + if (pp->mpp == mpp) + pp->mpp = NULL; } - - free_pathvec(mpp->paths, free_paths); + vector_foreach_slot (mpp->paths, pp, i) + if (pp->mpp == mpp) + pp->mpp = NULL; + free_pathvec(mpp->paths, KEEP_PATHS); free_pgvec(mpp->pg); if (mpp->hwe) { vector_free(mpp->hwe); @@ -337,13 +332,13 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths) void cleanup_multipath(struct multipath **pmpp) { if (*pmpp) - free_multipath(*pmpp, KEEP_PATHS); + free_multipath(*pmpp); } void cleanup_multipath_and_paths(struct multipath **pmpp) { if (*pmpp) - free_multipath(*pmpp, FREE_PATHS); + free_multipath(*pmpp); } void free_multipathvec(vector mpvec) @@ -355,7 +350,7 @@ void free_multipathvec(vector mpvec) return; vector_foreach_slot (mpvec, mpp, i) - free_multipath(mpp, KEEP_PATHS); + free_multipath(mpp); vector_free(mpvec); } diff --git a/libmultipath/structs.h b/libmultipath/structs.h index b16bd9e..a637af7 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -580,7 +580,7 @@ void free_pathvec (vector vec, enum free_path_mode free_paths); void cleanup_pathvec_and_free_paths(vector *vec); void free_pathgroup(struct pathgroup *pgp); void free_pgvec(vector pgvec); -void free_multipath (struct multipath *, enum free_path_mode free_paths); +void free_multipath(struct multipath *mpp); void cleanup_multipath(struct multipath **pmpp); void cleanup_multipath_and_paths(struct multipath **pmpp); void free_multipath_attributes(struct multipath *); diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c index 814d477..54280a9 100644 --- a/libmultipath/structs_vec.c +++ b/libmultipath/structs_vec.c @@ -428,11 +428,13 @@ void remove_map(struct multipath *mpp, vector pathvec) mpp->paths = mpp->pg = NULL; /* - * clear references to this map + * clear references to this map. + * This needs to be called before free_multipath(), + * because of the add_when_online logic. */ orphan_paths(pathvec, mpp, "map removed internally"); - free_multipath(mpp, KEEP_PATHS); + free_multipath(mpp); } void diff --git a/multipath/main.c b/multipath/main.c index 4b8d7dd..e3123e5 100644 --- a/multipath/main.c +++ b/multipath/main.c @@ -1069,7 +1069,7 @@ main (int argc, char *argv[]) printf("successfully reset wwids\n"); vector_foreach_slot_backwards(curmp, mpp, i) { vector_del_slot(curmp, i); - free_multipath(mpp, KEEP_PATHS); + free_multipath(mpp); } vector_free(curmp); goto out; -- 2.52.0
