diff mbox series

libmultipath/foreign: fix memory leak in nvme foreign handler

Message ID 20250109000653.2469651-1-bmarzins@redhat.com (mailing list archive)
State New
Headers show
Series libmultipath/foreign: fix memory leak in nvme foreign handler | expand

Commit Message

Benjamin Marzinski Jan. 9, 2025, 12:06 a.m. UTC
_find_controllers() needs to free the udev device if it doesn't get
added to a path. Otherwise it can leak memory whenever check_foreign()
is called, causing multipathd's memory usage to continually grow.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
 libmultipath/foreign/nvme.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

Comments

Benjamin Marzinski Jan. 9, 2025, 12:26 a.m. UTC | #1
On Wed, Jan 08, 2025 at 07:06:53PM -0500, Benjamin Marzinski wrote:
> _find_controllers() needs to free the udev device if it doesn't get
> added to a path. Otherwise it can leak memory whenever check_foreign()
> is called, causing multipathd's memory usage to continually grow.
> 

This also belongs in the stable branch.

-Ben

> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
>  libmultipath/foreign/nvme.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
> index 0b7f4eab..cde660ce 100644
> --- a/libmultipath/foreign/nvme.c
> +++ b/libmultipath/foreign/nvme.c
> @@ -675,7 +675,8 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
>  	pthread_cleanup_push_cast(free_scandir_result, &sr);
>  	for (i = 0; i < r; i++) {
>  		char *fn = di[i]->d_name;
> -		struct udev_device *ctrl, *udev;
> +		struct udev_device *ctrl;
> +		struct udev_device *udev __attribute__((cleanup(cleanup_udev_device))) = NULL;
>  
>  		if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn))
>  			continue;
> @@ -719,11 +720,11 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
>  			continue;
>  
>  		path->gen.ops = &nvme_path_ops;
> -		path->udev = udev;
> +		path->udev = steal_ptr(udev);
>  		path->seen = true;
>  		path->map = map;
>  		path->ctl = udev_device_get_parent_with_subsystem_devtype
> -			(udev, "nvme", NULL);
> +			(path->udev, "nvme", NULL);
>  		if (path->ctl == NULL) {
>  			condlog(1, "%s: %s: failed to get controller for %s",
>  				__func__, THIS, fn);
> @@ -744,7 +745,7 @@ static void _find_controllers(struct context *ctx, struct nvme_map *map)
>  		}
>  		vector_set_slot(&map->pgvec, &path->pg);
>  		condlog(3, "%s: %s: new path %s added to %s",
> -			__func__, THIS, udev_device_get_sysname(udev),
> +			__func__, THIS, udev_device_get_sysname(path->udev),
>  			udev_device_get_sysname(map->udev));
>  	}
>  	pthread_cleanup_pop(1);
> -- 
> 2.46.2
>
Martin Wilck Jan. 14, 2025, 9:45 p.m. UTC | #2
On Wed, 2025-01-08 at 19:06 -0500, Benjamin Marzinski wrote:
> _find_controllers() needs to free the udev device if it doesn't get
> added to a path. Otherwise it can leak memory whenever
> check_foreign()
> is called, causing multipathd's memory usage to continually grow.
> 
> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>

Reviewed-by: Martin Wilck <mwilck@suse.com>
diff mbox series

Patch

diff --git a/libmultipath/foreign/nvme.c b/libmultipath/foreign/nvme.c
index 0b7f4eab..cde660ce 100644
--- a/libmultipath/foreign/nvme.c
+++ b/libmultipath/foreign/nvme.c
@@ -675,7 +675,8 @@  static void _find_controllers(struct context *ctx, struct nvme_map *map)
 	pthread_cleanup_push_cast(free_scandir_result, &sr);
 	for (i = 0; i < r; i++) {
 		char *fn = di[i]->d_name;
-		struct udev_device *ctrl, *udev;
+		struct udev_device *ctrl;
+		struct udev_device *udev __attribute__((cleanup(cleanup_udev_device))) = NULL;
 
 		if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n, "/%s", fn))
 			continue;
@@ -719,11 +720,11 @@  static void _find_controllers(struct context *ctx, struct nvme_map *map)
 			continue;
 
 		path->gen.ops = &nvme_path_ops;
-		path->udev = udev;
+		path->udev = steal_ptr(udev);
 		path->seen = true;
 		path->map = map;
 		path->ctl = udev_device_get_parent_with_subsystem_devtype
-			(udev, "nvme", NULL);
+			(path->udev, "nvme", NULL);
 		if (path->ctl == NULL) {
 			condlog(1, "%s: %s: failed to get controller for %s",
 				__func__, THIS, fn);
@@ -744,7 +745,7 @@  static void _find_controllers(struct context *ctx, struct nvme_map *map)
 		}
 		vector_set_slot(&map->pgvec, &path->pg);
 		condlog(3, "%s: %s: new path %s added to %s",
-			__func__, THIS, udev_device_get_sysname(udev),
+			__func__, THIS, udev_device_get_sysname(path->udev),
 			udev_device_get_sysname(map->udev));
 	}
 	pthread_cleanup_pop(1);