Blame SOURCES/1005-fix-leak-device-state-files-rh1810153.patch

245932
From 457fae22aea770e2bf6553630caba645b6e1796d Mon Sep 17 00:00:00 2001
245932
From: Thomas Haller <thaller@redhat.com>
245932
Date: Wed, 4 Mar 2020 13:21:48 +0100
245932
Subject: [PATCH 1/4] core: cleanup nm_config_device_state_prune_unseen() and
245932
 accept NMPlatform for skipping pruning
245932
245932
(cherry picked from commit ad9e7488167ab25a5915040e813e76a5b669257b)
245932
(cherry picked from commit 0b4ebda859a3dc1c8ec4d8c887383d04bcd249f9)
245932
---
245932
 src/nm-config.c  | 36 +++++++++++++++++++++++-------------
245932
 src/nm-config.h  |  3 ++-
245932
 src/nm-manager.c |  8 ++++----
245932
 3 files changed, 29 insertions(+), 18 deletions(-)
245932
245932
diff --git a/src/nm-config.c b/src/nm-config.c
245932
index a0995cf932b8..0fccca4e22dc 100644
245932
--- a/src/nm-config.c
245932
+++ b/src/nm-config.c
245932
@@ -2298,6 +2298,8 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
245932
 	return device_state;
245932
 }
245932
 
245932
+#define DEVICE_STATE_FILENAME_LEN_MAX 60
245932
+
245932
 /**
245932
  * nm_config_device_state_load:
245932
  * @ifindex: the ifindex for which the state is to load
245932
@@ -2309,7 +2311,7 @@ NMConfigDeviceStateData *
245932
 nm_config_device_state_load (int ifindex)
245932
 {
245932
 	NMConfigDeviceStateData *device_state;
245932
-	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
245932
+	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
245932
 	gs_unref_keyfile GKeyFile *kf = NULL;
245932
 	const char *nm_owned_str;
245932
 
245932
@@ -2393,7 +2395,7 @@ nm_config_device_state_write (int ifindex,
245932
                               const char *next_server,
245932
                               const char *root_path)
245932
 {
245932
-	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
245932
+	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
245932
 	GError *local = NULL;
245932
 	gs_unref_keyfile GKeyFile *kf = NULL;
245932
 
245932
@@ -2476,35 +2478,43 @@ nm_config_device_state_write (int ifindex,
245932
 }
245932
 
245932
 void
245932
-nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
245932
+nm_config_device_state_prune_unseen (GHashTable *preserve_ifindexes,
245932
+                                     NMPlatform *preserve_in_platform)
245932
 {
245932
 	GDir *dir;
245932
 	const char *fn;
245932
-	int ifindex;
245932
-	gsize fn_len;
245932
-	char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + 30 + 3] = NM_CONFIG_DEVICE_STATE_DIR"/";
245932
+	char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1] = NM_CONFIG_DEVICE_STATE_DIR"/";
245932
 	char *buf_p = &buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/")];
245932
 
245932
-	g_return_if_fail (seen_ifindexes);
245932
-
245932
 	dir = g_dir_open (NM_CONFIG_DEVICE_STATE_DIR, 0, NULL);
245932
 	if (!dir)
245932
 		return;
245932
 
245932
 	while ((fn = g_dir_read_name (dir))) {
245932
+		int ifindex;
245932
+		gsize fn_len;
245932
+
245932
 		ifindex = _device_state_parse_filename (fn);
245932
 		if (ifindex <= 0)
245932
 			continue;
245932
-		if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex)))
245932
+
245932
+		if (   preserve_ifindexes
245932
+		    && g_hash_table_contains (preserve_ifindexes, GINT_TO_POINTER (ifindex)))
245932
+			continue;
245932
+
245932
+		if (   preserve_in_platform
245932
+		    && nm_platform_link_get (preserve_in_platform, ifindex))
245932
 			continue;
245932
 
245932
-		fn_len = strlen (fn) + 1;
245932
+		fn_len = strlen (fn);
245932
+		nm_assert (fn_len > 0);
245932
 		nm_assert (&buf_p[fn_len] < &buf[G_N_ELEMENTS (buf)]);
245932
-		memcpy (buf_p, fn, fn_len);
245932
+		memcpy (buf_p, fn, fn_len + 1u);
245932
 		nm_assert (({
245932
 		                char bb[30];
245932
-		                nm_sprintf_buf (bb, "%d", ifindex);
245932
-		                nm_streq0 (bb, buf_p);
245932
+
245932
+		                nm_streq0 (nm_sprintf_buf (bb, "%d", ifindex),
245932
+		                           buf_p);
245932
 		           }));
245932
 		_LOGT ("device-state: prune #%d (%s)", ifindex, buf);
245932
 		(void) unlink (buf);
245932
diff --git a/src/nm-config.h b/src/nm-config.h
245932
index d9460ebb46e3..048d64f41f47 100644
245932
--- a/src/nm-config.h
245932
+++ b/src/nm-config.h
245932
@@ -258,7 +258,8 @@ gboolean nm_config_device_state_write (int ifindex,
245932
                                        const char *next_server,
245932
                                        const char *root_path);
245932
 
245932
-void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
245932
+void nm_config_device_state_prune_unseen (GHashTable *preserve_ifindexes,
245932
+                                          NMPlatform *preserve_in_platform);
245932
 
245932
 const GHashTable *nm_config_device_state_get_all (NMConfig *self);
245932
 const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self,
245932
diff --git a/src/nm-manager.c b/src/nm-manager.c
245932
index 7f6657fd70e2..35127fa6cd25 100644
245932
--- a/src/nm-manager.c
245932
+++ b/src/nm-manager.c
245932
@@ -6585,19 +6585,19 @@ void
245932
 nm_manager_write_device_state_all (NMManager *self)
245932
 {
245932
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
245932
-	gs_unref_hashtable GHashTable *seen_ifindexes = NULL;
245932
+	gs_unref_hashtable GHashTable *preserve_ifindexes = NULL;
245932
 	NMDevice *device;
245932
 
245932
-	seen_ifindexes = g_hash_table_new (nm_direct_hash, NULL);
245932
+	preserve_ifindexes = g_hash_table_new (nm_direct_hash, NULL);
245932
 
245932
 	c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
245932
 		if (nm_manager_write_device_state (self, device)) {
245932
-			g_hash_table_add (seen_ifindexes,
245932
+			g_hash_table_add (preserve_ifindexes,
245932
 			                  GINT_TO_POINTER (nm_device_get_ip_ifindex (device)));
245932
 		}
245932
 	}
245932
 
245932
-	nm_config_device_state_prune_unseen (seen_ifindexes);
245932
+	nm_config_device_state_prune_unseen (preserve_ifindexes, NULL);
245932
 }
245932
 
245932
 static gboolean
245932
-- 
245932
2.24.1
245932
245932
245932
From af10b35dabc0b542eba8117bb32b3fee3ff207f9 Mon Sep 17 00:00:00 2001
245932
From: Thomas Haller <thaller@redhat.com>
245932
Date: Wed, 4 Mar 2020 16:52:57 +0100
245932
Subject: [PATCH 2/4] core/trivial: rename
245932
 nm_config_device_state_prune_unseen() to nm_config_device_state_prune_stale()
245932
245932
It's just a more fitting name after the previous change.
245932
245932
(cherry picked from commit ecb0210e7a225f2b73149229cc96ac84f93404d1)
245932
(cherry picked from commit 7fa1e825450ce4b69670b5bfd5a9c705d9c05920)
245932
---
245932
 src/nm-config.c  | 4 ++--
245932
 src/nm-config.h  | 4 ++--
245932
 src/nm-manager.c | 2 +-
245932
 3 files changed, 5 insertions(+), 5 deletions(-)
245932
245932
diff --git a/src/nm-config.c b/src/nm-config.c
245932
index 0fccca4e22dc..0a6082d71a63 100644
245932
--- a/src/nm-config.c
245932
+++ b/src/nm-config.c
245932
@@ -2478,8 +2478,8 @@ nm_config_device_state_write (int ifindex,
245932
 }
245932
 
245932
 void
245932
-nm_config_device_state_prune_unseen (GHashTable *preserve_ifindexes,
245932
-                                     NMPlatform *preserve_in_platform)
245932
+nm_config_device_state_prune_stale (GHashTable *preserve_ifindexes,
245932
+                                    NMPlatform *preserve_in_platform)
245932
 {
245932
 	GDir *dir;
245932
 	const char *fn;
245932
diff --git a/src/nm-config.h b/src/nm-config.h
245932
index 048d64f41f47..b4478ceb04af 100644
245932
--- a/src/nm-config.h
245932
+++ b/src/nm-config.h
245932
@@ -258,8 +258,8 @@ gboolean nm_config_device_state_write (int ifindex,
245932
                                        const char *next_server,
245932
                                        const char *root_path);
245932
 
245932
-void nm_config_device_state_prune_unseen (GHashTable *preserve_ifindexes,
245932
-                                          NMPlatform *preserve_in_platform);
245932
+void nm_config_device_state_prune_stale (GHashTable *preserve_ifindexes,
245932
+                                         NMPlatform *preserve_in_platform);
245932
 
245932
 const GHashTable *nm_config_device_state_get_all (NMConfig *self);
245932
 const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self,
245932
diff --git a/src/nm-manager.c b/src/nm-manager.c
245932
index 35127fa6cd25..c9ef20a526d2 100644
245932
--- a/src/nm-manager.c
245932
+++ b/src/nm-manager.c
245932
@@ -6597,7 +6597,7 @@ nm_manager_write_device_state_all (NMManager *self)
245932
 		}
245932
 	}
245932
 
245932
-	nm_config_device_state_prune_unseen (preserve_ifindexes, NULL);
245932
+	nm_config_device_state_prune_stale (preserve_ifindexes, NULL);
245932
 }
245932
 
245932
 static gboolean
245932
-- 
245932
2.24.1
245932
245932
245932
From 509b555a45b170f843242e3d92b229936457ba75 Mon Sep 17 00:00:00 2001
245932
From: Thomas Haller <thaller@redhat.com>
245932
Date: Wed, 4 Mar 2020 13:38:49 +0100
245932
Subject: [PATCH 3/4] core: return ifindex from nm_manager_write_device_state()
245932
245932
nm_manager_write_device_state() writes the device state to a file. The ifindex
245932
is here important, because that is the identifier for the device and is also
245932
used as file name. Return the ifindex that was used, instead of letting the
245932
caller reimplement the knowledge which ifindex was used.
245932
245932
(cherry picked from commit 5477847eed9654727df5b70767a2a6498da1cb67)
245932
(cherry picked from commit fb6e14cf3f602a840bee66c27dfcb754872f1525)
245932
---
245932
 src/nm-manager.c | 34 +++++++++++++++++++++-------------
245932
 src/nm-manager.h |  2 +-
245932
 2 files changed, 22 insertions(+), 14 deletions(-)
245932
245932
diff --git a/src/nm-manager.c b/src/nm-manager.c
245932
index c9ef20a526d2..74776a24acf2 100644
245932
--- a/src/nm-manager.c
245932
+++ b/src/nm-manager.c
245932
@@ -1515,7 +1515,7 @@ manager_device_state_changed (NMDevice *device,
245932
 	               NM_DEVICE_STATE_UNMANAGED,
245932
 	               NM_DEVICE_STATE_DISCONNECTED,
245932
 	               NM_DEVICE_STATE_ACTIVATED))
245932
-		nm_manager_write_device_state (self, device);
245932
+		nm_manager_write_device_state (self, device, NULL);
245932
 
245932
 	if (NM_IN_SET (new_state,
245932
 	               NM_DEVICE_STATE_UNAVAILABLE,
245932
@@ -6514,7 +6514,7 @@ start_factory (NMDeviceFactory *factory, gpointer user_data)
245932
 }
245932
 
245932
 gboolean
245932
-nm_manager_write_device_state (NMManager *self, NMDevice *device)
245932
+nm_manager_write_device_state (NMManager *self, NMDevice *device, int *out_ifindex)
245932
 {
245932
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
245932
 	int ifindex;
245932
@@ -6530,6 +6530,8 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
245932
 	const char *next_server = NULL;
245932
 	const char *root_path = NULL;
245932
 
245932
+	NM_SET_OUT (out_ifindex, 0);
245932
+
245932
 	ifindex = nm_device_get_ip_ifindex (device);
245932
 	if (ifindex <= 0)
245932
 		return FALSE;
245932
@@ -6570,15 +6572,19 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
245932
 		next_server = nm_dhcp4_config_get_option (dhcp4_config, "next_server");
245932
 	}
245932
 
245932
-	return nm_config_device_state_write (ifindex,
245932
-	                                     managed_type,
245932
-	                                     perm_hw_addr_fake,
245932
-	                                     uuid,
245932
-	                                     nm_owned,
245932
-	                                     route_metric_default_aspired,
245932
-	                                     route_metric_default_effective,
245932
-	                                     next_server,
245932
-	                                     root_path);
245932
+	if (!nm_config_device_state_write (ifindex,
245932
+	                                   managed_type,
245932
+	                                   perm_hw_addr_fake,
245932
+	                                   uuid,
245932
+	                                   nm_owned,
245932
+	                                   route_metric_default_aspired,
245932
+	                                   route_metric_default_effective,
245932
+	                                   next_server,
245932
+	                                   root_path))
245932
+		return FALSE;
245932
+
245932
+	NM_SET_OUT (out_ifindex, ifindex);
245932
+	return TRUE;
245932
 }
245932
 
245932
 void
245932
@@ -6591,9 +6597,11 @@ nm_manager_write_device_state_all (NMManager *self)
245932
 	preserve_ifindexes = g_hash_table_new (nm_direct_hash, NULL);
245932
 
245932
 	c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
245932
-		if (nm_manager_write_device_state (self, device)) {
245932
+		int ifindex;
245932
+
245932
+		if (nm_manager_write_device_state (self, device, &ifindex)) {
245932
 			g_hash_table_add (preserve_ifindexes,
245932
-			                  GINT_TO_POINTER (nm_device_get_ip_ifindex (device)));
245932
+			                  GINT_TO_POINTER (ifindex));
245932
 		}
245932
 	}
245932
 
245932
diff --git a/src/nm-manager.h b/src/nm-manager.h
245932
index ad06e318f4dc..5873abd24b8e 100644
245932
--- a/src/nm-manager.h
245932
+++ b/src/nm-manager.h
245932
@@ -103,7 +103,7 @@ NMSettingsConnection **nm_manager_get_activatable_connections (NMManager *manage
245932
                                                                guint *out_len);
245932
 
245932
 void          nm_manager_write_device_state_all (NMManager *manager);
245932
-gboolean      nm_manager_write_device_state (NMManager *manager, NMDevice *device);
245932
+gboolean      nm_manager_write_device_state (NMManager *manager, NMDevice *device, int *out_ifindex);
245932
 
245932
 /* Device handling */
245932
 
245932
-- 
245932
2.24.1
245932
245932
245932
From d60b888a07d69e155a7bea9dead1376df1a21bfb Mon Sep 17 00:00:00 2001
245932
From: Thomas Haller <thaller@redhat.com>
245932
Date: Wed, 4 Mar 2020 15:44:53 +0100
245932
Subject: [PATCH 4/4] core: periodically cleanup unused device state files from
245932
 /run
245932
245932
Otherwise, we only prune unused files when the service terminates.
245932
Usually, NetworkManager service doesn't get restarted before shutdown
245932
of the system (nor should it be). That means, if you create (and
245932
destroy) a large number of software devices, the state files pile
245932
up.
245932
245932
From time to time, go through the files on disk and delete those that
245932
are no longer relevant.
245932
245932
In this case, "from time to time" means after we write/update state
245932
files 100 times.
245932
245932
(cherry picked from commit 332df7a58e86ce08cfd9331897d8b928ae6d267e)
245932
(cherry picked from commit d65b5c2e81f69ddc9217159a16f49d23d965da1c)
245932
---
245932
 src/nm-manager.c | 20 +++++++++++++++++++-
245932
 1 file changed, 19 insertions(+), 1 deletion(-)
245932
245932
diff --git a/src/nm-manager.c b/src/nm-manager.c
245932
index 74776a24acf2..931d1068f160 100644
245932
--- a/src/nm-manager.c
245932
+++ b/src/nm-manager.c
245932
@@ -50,6 +50,8 @@
245932
 #include "nm-dispatcher.h"
245932
 #include "NetworkManagerUtils.h"
245932
 
245932
+#define DEVICE_STATE_PRUNE_RATELIMIT_MAX 100u
245932
+
245932
 /*****************************************************************************/
245932
 
245932
 typedef struct {
245932
@@ -191,6 +193,8 @@ typedef struct {
245932
 
245932
 	NMConnectivityState connectivity_state;
245932
 
245932
+	guint8 device_state_prune_ratelimit_count;
245932
+
245932
 	bool startup:1;
245932
 	bool devices_inited:1;
245932
 
245932
@@ -1514,9 +1518,23 @@ manager_device_state_changed (NMDevice *device,
245932
 	if (NM_IN_SET (new_state,
245932
 	               NM_DEVICE_STATE_UNMANAGED,
245932
 	               NM_DEVICE_STATE_DISCONNECTED,
245932
-	               NM_DEVICE_STATE_ACTIVATED))
245932
+	               NM_DEVICE_STATE_ACTIVATED)) {
245932
 		nm_manager_write_device_state (self, device, NULL);
245932
 
245932
+		G_STATIC_ASSERT_EXPR (DEVICE_STATE_PRUNE_RATELIMIT_MAX < G_MAXUINT8);
245932
+		if (priv->device_state_prune_ratelimit_count++ > DEVICE_STATE_PRUNE_RATELIMIT_MAX) {
245932
+			/* We write the device state to /run. The state files are named after the
245932
+			 * ifindex (which is assumed to be unique and not repeat -- in practice
245932
+			 * it may repeat). So from time to time, we prune device state files
245932
+			 * for interfaces that no longer exist.
245932
+			 *
245932
+			 * Otherwise, the files might pile up if you create (and destroy) a large
245932
+			 * number of software devices. */
245932
+			priv->device_state_prune_ratelimit_count = 0;
245932
+			nm_config_device_state_prune_stale (NULL, priv->platform);
245932
+		}
245932
+	}
245932
+
245932
 	if (NM_IN_SET (new_state,
245932
 	               NM_DEVICE_STATE_UNAVAILABLE,
245932
 	               NM_DEVICE_STATE_DISCONNECTED))
245932
-- 
245932
2.24.1
245932