Hi lixiaokeng,

On Thu, 2020-10-22 at 15:28 +0800, lixiaokeng wrote:
> When multipath -F are executed first and multipath -v2 or
> -d are executed later, asan will warn memory leaks. The
> reason is that the mpp allocated in coalesce_paths isn't
> freed. Here we use newmp to store mpp. If newmp need not
> be copied to mpvec, we free newmp at the end of the func.
> 
> Signed-off-by: Lixiaokeng <lixiaok...@huawei.com>
> Signed-off-by: Zhiqiang Liu <liuzhiqian...@huawei.com>
> Signed-off-by: Linfeilong <linfeil...@huawei.com>

Thanks. Please see below.

> ---
>  libmultipath/configure.c | 66 +++++++++++++++++++++++++-------------
> --
>  1 file changed, 41 insertions(+), 25 deletions(-)
> 
> diff --git a/libmultipath/configure.c b/libmultipath/configure.c
> index 6fb477fc..9d6eeba1 100644
> --- a/libmultipath/configure.c
> +++ b/libmultipath/configure.c
> @@ -1132,7 +1132,7 @@ out:
>   * FORCE_RELOAD_WEAK: existing maps are compared to the current conf
> and only
>   * reloaded in DM if there's a difference. This is useful during
> startup.
>   */
> -int coalesce_paths (struct vectors * vecs, vector newmp, char *
> refwwid,
> +int coalesce_paths (struct vectors *vecs, vector mpvec, char
> *refwwid,
>                   int force_reload, enum mpath_cmds cmd)
>  {
>       int ret = CP_FAIL;
> @@ -1144,10 +1144,20 @@ int coalesce_paths (struct vectors * vecs,
> vector newmp, char * refwwid,
>       struct path * pp2;
>       vector curmp = vecs->mpvec;
>       vector pathvec = vecs->pathvec;
> +     vector newmp = NULL;

This initialization is not necessary.

>       struct config *conf;
>       int allow_queueing;
>       struct bitfield *size_mismatch_seen;
> 
> +     if (mpvec)
> +             newmp = mpvec;
> +     else
> +             newmp = vector_alloc();
> +     if (!newmp) {
> +             condlog(0, "can not allocate newmp");
> +             return ret;
> +     }
> +
>       /* ignore refwwid if it's empty */
>       if (refwwid && !strlen(refwwid))
>               refwwid = NULL;
> @@ -1270,8 +1280,14 @@ int coalesce_paths (struct vectors * vecs,
> vector newmp, char * refwwid,
>                               goto out;
>                       }
>               }
> -             if (r == DOMAP_DRY)
> +             if (r == DOMAP_DRY) {
> +                     if (!vector_alloc_slot(newmp)) {
> +                             remove_map(mpp, vecs->pathvec, vecs-
> >mpvec, KEEP_VEC);
> +                             goto out;
> +                     }
> +                     vector_set_slot(newmp, mpp);
>                       continue;
> +             }
> 
>               if (r == DOMAP_EXIST && mpp->action == ACT_NOTHING &&
>                   force_reload == FORCE_RELOAD_WEAK)
> @@ -1307,44 +1323,44 @@ int coalesce_paths (struct vectors * vecs,
> vector newmp, char * refwwid,
>                       print_multipath_topology(mpp, verbosity);
>               }
> 
> -             if (newmp) {
> -                     if (mpp->action != ACT_REJECT) {
> -                             if (!vector_alloc_slot(newmp))
> -                                     goto out;
> -                             vector_set_slot(newmp, mpp);
> +             if (mpp->action != ACT_REJECT) {
> +                     if (!vector_alloc_slot(newmp)) {
> +                             remove_map(mpp, vecs->pathvec, vecs-
> >mpvec, KEEP_VEC);
> +                             goto out;
>                       }
> -                     else
> -                             remove_map(mpp, vecs->pathvec, vecs-
> >mpvec,
> -                                        KEEP_VEC);
> +                     vector_set_slot(newmp, mpp);
>               }
> +             else
> +                     remove_map(mpp, vecs->pathvec, vecs->mpvec,
> +                                KEEP_VEC);
>       }
>       /*
>        * Flush maps with only dead paths (ie not in sysfs)
>        * Keep maps with only failed paths
>        */
> -     if (newmp) {
> -             vector_foreach_slot (newmp, mpp, i) {
> -                     char alias[WWID_SIZE];
> +     vector_foreach_slot (newmp, mpp, i) {
> +             char alias[WWID_SIZE];
> 
> -                     if (!deadmap(mpp))
> -                             continue;
> +             if (!deadmap(mpp))
> +                     continue;
> 
> -                     strlcpy(alias, mpp->alias, WWID_SIZE);
> +             strlcpy(alias, mpp->alias, WWID_SIZE);
> 
> -                     vector_del_slot(newmp, i);
> -                     i--;
> -                     remove_map(mpp, vecs->pathvec, vecs->mpvec,
> KEEP_VEC);
> +             vector_del_slot(newmp, i);
> +             i--;
> +             remove_map(mpp, vecs->pathvec, vecs->mpvec, KEEP_VEC);
> 
> -                     if (dm_flush_map(alias))
> -                             condlog(2, "%s: remove failed (dead)",
> -                                     alias);
> -                     else
> -                             condlog(2, "%s: remove (dead)", alias);
> -             }
> +             if (dm_flush_map(alias))
> +                     condlog(2, "%s: remove failed (dead)",
> +                             alias);
> +             else
> +                     condlog(2, "%s: remove (dead)", alias);

Previously, this code, which flushes maps that aren't valid any more,
would only be called from multipathd() -> reconfigure(), because in all
other cases newmp was NULL.

AFAICS, you will now call dm_flush_map() even if called with
newmp==NULL (this means, from cli_add_map(), or from multipath, even if
called with CMD_DRY_RUN). I don't think that's what we want.

Regards,
Martin



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

Reply via email to