dm-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
* [dm-devel] [PATCH v2] libmultipath: fix memory leaks in coalesce_paths
@ 2020-10-22  7:28 lixiaokeng
  2020-11-01 21:23 ` Martin Wilck
  0 siblings, 1 reply; 3+ messages in thread
From: lixiaokeng @ 2020-10-22  7:28 UTC (permalink / raw)
  To: Christophe Varoqui, Benjamin Marzinski, Martin Wilck,
	dm-devel mailing list
  Cc: linfeilong, liuzhiqiang (I)

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 <lixiaokeng@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
---
 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;
 	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);
 	}
 	ret = CP_OK;
 out:
 	free(size_mismatch_seen);
+	if (!mpvec)
+		free_multipathvec(newmp, KEEP_PATHS);
 	return ret;
 }

-- 

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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [dm-devel] [PATCH v2] libmultipath: fix memory leaks in coalesce_paths
  2020-10-22  7:28 [dm-devel] [PATCH v2] libmultipath: fix memory leaks in coalesce_paths lixiaokeng
@ 2020-11-01 21:23 ` Martin Wilck
  2020-11-02  2:35   ` lixiaokeng
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Wilck @ 2020-11-01 21:23 UTC (permalink / raw)
  To: lixiaokeng, Christophe Varoqui, Benjamin Marzinski,
	dm-devel mailing list
  Cc: linfeilong, liuzhiqiang (I)

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 <lixiaokeng@huawei.com>
> Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
> Signed-off-by: Linfeilong <linfeilong@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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [dm-devel] [PATCH v2] libmultipath: fix memory leaks in coalesce_paths
  2020-11-01 21:23 ` Martin Wilck
@ 2020-11-02  2:35   ` lixiaokeng
  0 siblings, 0 replies; 3+ messages in thread
From: lixiaokeng @ 2020-11-02  2:35 UTC (permalink / raw)
  To: Martin Wilck, Christophe Varoqui, Benjamin Marzinski,
	dm-devel mailing list
  Cc: linfeilong, liuzhiqiang (I)



On 2020/11/2 5:23, Martin Wilck wrote:
> 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.
Hi
 Thanks for your review. I will change my patch to make sure dm_flush_map()
is called only when mpvec (newmp in old code) is not NULL. Thanks for your
advice again.

Regards,
Lixiaokeng

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


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-11-02  2:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-22  7:28 [dm-devel] [PATCH v2] libmultipath: fix memory leaks in coalesce_paths lixiaokeng
2020-11-01 21:23 ` Martin Wilck
2020-11-02  2:35   ` lixiaokeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).