On Sat, 2024-07-13 at 02:04 -0400, Benjamin Marzinski wrote:
> In ev_remove_path() it was possible to exit after calling setup_map()
> without resyncing the mpp state with the kernel. This meant that the
> mpp state in multipathd might not match with the kernel state at all.
> 
> It's safe to exit before calling setup_map() if either wait_for_udev
> or need_do_map is set. In both cases, setup_map() will later be
> called,
> either by a uevent or by the calling function.
> 
> Once setup_map() has been called, setup_multipath() and
> sync_map_state()
> are now always called, to make sure the mpp matches the kernel state.
> 
> Signed-off-by: Benjamin Marzinski <[email protected]>
> ---
>  multipathd/main.c | 40 +++++++++++++++++++---------------------
>  1 file changed, 19 insertions(+), 21 deletions(-)
> 
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 179fec24..3c84c2a0 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -1395,6 +1395,8 @@ ev_remove_path (struct path *pp, struct vectors
> * vecs, int need_do_map)
>        * avoid referring to the map of an orphaned path
>        */
>       if ((mpp = pp->mpp)) {
> +             char devt[BLK_DEV_SIZE];
> +
>               /*
>                * Mark the path as removed. In case of success, we
>                * will delete it for good. Otherwise, it will be
> deleted
> @@ -1428,12 +1430,6 @@ ev_remove_path (struct path *pp, struct
> vectors * vecs, int need_do_map)
>                   flush_map_nopaths(mpp, vecs))
>                       goto out;
>  
> -             if (setup_map(mpp, &params, vecs)) {
> -                     condlog(0, "%s: failed to setup map for"
> -                             " removal of path %s", mpp->alias,
> pp->dev);
> -                     goto fail;
> -             }
> -
>               if (mpp->wait_for_udev) {
>                       mpp->wait_for_udev = 2;
>                       retval = REMOVE_PATH_DELAY;
> @@ -1444,33 +1440,35 @@ ev_remove_path (struct path *pp, struct
> vectors * vecs, int need_do_map)
>                       retval = REMOVE_PATH_DELAY;
>                       goto out;
>               }
> +
> +             if (setup_map(mpp, &params, vecs)) {
> +                     condlog(0, "%s: failed to setup map for"
> +                             " removal of path %s", mpp->alias,
> pp->dev);
> +                     goto fail;
> +             }
>               /*
>                * reload the map
>                */
>               mpp->action = ACT_RELOAD;
> +             strlcpy(devt, pp->dev_t, sizeof(devt));

Move this statement further down, directly before the call to
setup_multipath(), perhaps? It's only for the condlog anyway.

Except for that, LGTM.

Martin


>               if (domap(mpp, params, 1) == DOMAP_FAIL) {
>                       condlog(0, "%s: failed in domap for "
>                               "removal of path %s",
>                               mpp->alias, pp->dev);
>                       retval = REMOVE_PATH_FAILURE;
> -             } else {
> -                     /*
> -                      * update our state from kernel
> -                      */
> -                     char devt[BLK_DEV_SIZE];
> -
> -                     strlcpy(devt, pp->dev_t, sizeof(devt));
> -
> -                     /* setup_multipath will free the path
> -                      * regardless of whether it succeeds or
> -                      * fails */
> -                     if (setup_multipath(vecs, mpp))
> -                             return REMOVE_PATH_MAP_ERROR;
> -                     sync_map_state(mpp);
> +             }
> +             /*
> +              * update mpp state from kernel even if domap
> failed.
> +              * If the path was removed from the mpp,
> setup_multipath will
> +              * free the path regardless of whether it succeeds
> or fails
> +              */
> +             if (setup_multipath(vecs, mpp))
> +                     return REMOVE_PATH_MAP_ERROR;
> +             sync_map_state(mpp);
>  
> +             if (retval == REMOVE_PATH_SUCCESS)
>                       condlog(2, "%s: path removed from map %s",
>                               devt, mpp->alias);
> -             }
>       } else {
>               /* mpp == NULL */
>               if ((i = find_slot(vecs->pathvec, (void *)pp)) != -
> 1)


Reply via email to