On Thu, Jan 23, 2025 at 11:12:12PM +0100, Martin Wilck wrote:
> If multipathd has already configured maps, and the user changes the
> blacklist or other parameters that cause currently multipathed
> devices to be skipped, and then runs "multipathd reconfigure"
> or restarts multipathd, multipathd flushes the maps in question,
> but doesn't trigger uevents for the now-blacklisted paths.
> 
> This is because the blacklisted paths are removed from the discovered
> maps internally when update_pathvec_from_dm() is called through
> map_discovery() and update_multipath_table(); when later
> trigger_paths_udev_change() is called from coalesce_maps(), the
> map contains no paths for which an uevent could be triggered.
> 
> The map_discovery() code flow is special, because we will call
> coalesce_paths() afterwards anyway and reconstruct the mpvec. Unlike the
> regular code flow, we don't want the maps to be "corrected" in this
> case, because the maps discovered here aren't going to be reloaded.
> We just want update_pathvec_from_dm() to populate the pathvec.
> 
> Therefore add a new flag DI_DISCOVERY, which is only set when
> update_multipath_table() is called from map_discovery(), and if
> this flag is set, keep PATHINFO_SKIPPED paths in the map's table in
> update_pathvec_from_dm(). Later on, the paths will still be visible
> in the old mpp (ompp) in coalesce_maps(), and uevents will be
> triggered for them to release them to systemd.
> 
> We can't always do this for PATHINFO_SKIPPED, because in some cases
> paths may be accepted in a map first and SKIPPED later (for example if
> the WWID wasn't yet available at startup). Therefore the special
> case for DI_DISCOVERY is necessary.
> 
> Signed-off-by: Martin Wilck <mwi...@suse.com>

Reviewed-by: Benjamin Marzinski <bmarz...@redhat.com>

> ---
>  libmultipath/discovery.h   | 2 ++
>  libmultipath/structs_vec.c | 6 +++++-
>  multipathd/main.c          | 2 +-
>  3 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
> index c4a8dd9..2b39eb0 100644
> --- a/libmultipath/discovery.h
> +++ b/libmultipath/discovery.h
> @@ -74,6 +74,7 @@ enum discovery_mode {
>       DI_BLACKLIST__,
>       DI_NOIO__,
>       DI_NOFALLBACK__,
> +     DI_DISCOVERY__,
>  };
>  
>  #define DI_SYSFS     (1 << DI_SYSFS__)
> @@ -84,6 +85,7 @@ enum discovery_mode {
>  #define DI_BLACKLIST (1 << DI_BLACKLIST__)
>  #define DI_NOIO              (1 << DI_NOIO__) /* Avoid IO on the device */
>  #define DI_NOFALLBACK        (1 << DI_NOFALLBACK__) /* do not allow wwid 
> fallback */
> +#define DI_DISCOVERY (1 << DI_DISCOVERY__) /* set only during map discovery 
> */
>  
>  #define DI_ALL               (DI_SYSFS  | DI_IOCTL | DI_CHECKER | DI_PRIO | 
> DI_WWID)
>  
> diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
> index b2bb47c..7d53aa3 100644
> --- a/libmultipath/structs_vec.c
> +++ b/libmultipath/structs_vec.c
> @@ -107,6 +107,9 @@ static void update_pathvec_from_dm(vector pathvec, struct 
> multipath *mpp,
>       bool mpp_has_wwid;
>       bool must_reload = false;
>       bool pg_deleted = false;
> +     bool map_discovery = !!(pathinfo_flags & DI_DISCOVERY);
> +
> +     pathinfo_flags &= ~DI_DISCOVERY;
>  
>       if (!mpp->pg)
>               return;
> @@ -193,7 +196,8 @@ static void update_pathvec_from_dm(vector pathvec, struct 
> multipath *mpp,
>                                       rc = pathinfo(pp, conf,
>                                                     
> DI_SYSFS|DI_WWID|DI_BLACKLIST|DI_NOFALLBACK|pathinfo_flags);
>                                       pthread_cleanup_pop(1);
> -                                     if (rc != PATHINFO_OK) {
> +                                     if (rc == PATHINFO_FAILED ||
> +                                         (rc == PATHINFO_SKIPPED && 
> !map_discovery)) {
>                                               condlog(1, "%s: error %d in 
> pathinfo, discarding path",
>                                                       pp->dev, rc);
>                                               vector_del_slot(pgp->paths, 
> j--);
> diff --git a/multipathd/main.c b/multipathd/main.c
> index b4a366e..43a0240 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -1758,7 +1758,7 @@ map_discovery (struct vectors * vecs)
>               return 1;
>  
>       vector_foreach_slot (vecs->mpvec, mpp, i)
> -             if (update_multipath_table(mpp, vecs->pathvec, 0) != DMP_OK) {
> +             if (update_multipath_table(mpp, vecs->pathvec, DI_DISCOVERY) != 
> DMP_OK) {
>                       vector_del_slot(vecs->mpvec, i--);
>                       remove_map(mpp, vecs->pathvec);
>               }
> -- 
> 2.48.1


Reply via email to