summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-06-24 21:47:15 +0200
committerThomas Haller <thaller@redhat.com>2021-07-01 11:33:56 +0200
commit006733d9b101c63b3cfb6f4c859a127e6ad4e76d (patch)
tree9d071e17f325982f3a186cd5880b46ac54ff136b
parent697a445f6b0b73d6366355e6de0b18280c6a604f (diff)
downloadNetworkManager-006733d9b101c63b3cfb6f4c859a127e6ad4e76d.tar.gz
settings: prune old entries from keyfile databases
We have two GKeyfile files (timestamps and seen-bssids). When a profile was deleted while NetworkManager was running, then entries were removed from these keyfiles. But if a profile disappeared while NetworkManger was stopped, then those UUIDs piled up. This also happens if you have temporary connections in /run and reboot. We need a way to garbage collect entries that are no longer relevant. As the keyfile databases only get loaded once from disk, we will prune all UUIDs for which we have no more connection loaded, on the first time we write out the files again. Note what this means: if you "temporarily" remove a connection profile (without NetworkManager noticing) and restore it later, then the additional information might have been pruned. There is no way how NetworkManager could know that this UUID is coming back. The alternative is what we did before: pile them up indefinitely. That seems more problematic. (cherry picked from commit 2e720a1dc8b488969d80150487a733d462ccfacb)
-rw-r--r--src/core/settings/nm-settings.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c
index c876ea148c..631b795df1 100644
--- a/src/core/settings/nm-settings.c
+++ b/src/core/settings/nm-settings.c
@@ -388,6 +388,9 @@ typedef struct {
guint kf_db_flush_idle_id_timestamps;
guint kf_db_flush_idle_id_seen_bssids;
+ bool kf_db_pruned_timestamps;
+ bool kf_db_pruned_seen_bssid;
+
bool started : 1;
/* Whether NMSettingsConnections changed in a way that affects the comparison
@@ -3684,6 +3687,37 @@ again:
/*****************************************************************************/
+static gboolean
+_kf_db_prune_predicate(const char *uuid, gpointer user_data)
+{
+ return !!nm_settings_get_connection_by_uuid(user_data, uuid);
+}
+
+static void
+_kf_db_to_file(NMSettings *self, gboolean is_timestamps, gboolean force_write)
+{
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self);
+ NMKeyFileDB * kf_db;
+ bool * p_kf_db_pruned;
+
+ if (is_timestamps) {
+ kf_db = priv->kf_db_timestamps;
+ p_kf_db_pruned = &priv->kf_db_pruned_timestamps;
+ } else {
+ kf_db = priv->kf_db_seen_bssids;
+ p_kf_db_pruned = &priv->kf_db_pruned_seen_bssid;
+ }
+
+ if (!*p_kf_db_pruned) {
+ /* we only prune the DB once, because afterwards every
+ * add/remove of an connection will lead to a direct update. */
+ *p_kf_db_pruned = TRUE;
+ nm_key_file_db_prune(kf_db, _kf_db_prune_predicate, self);
+ }
+
+ nm_key_file_db_to_file(kf_db, force_write);
+}
+
G_GNUC_PRINTF(4, 5)
static void
_kf_db_log_fcn(NMKeyFileDB *kf_db, int syslog_level, gpointer user_data, const char *fmt, ...)
@@ -3732,7 +3766,7 @@ _kf_db_got_dirty_flush(NMSettings *self, gboolean is_timestamps)
}
if (nm_key_file_db_is_dirty(kf_db))
- nm_key_file_db_to_file(kf_db, FALSE);
+ _kf_db_to_file(self, is_timestamps, FALSE);
else {
_LOGT("[%s-keyfile]: skip saving changes to \"%s\"",
prefix,
@@ -3785,15 +3819,10 @@ _kf_db_got_dirty_fcn(NMKeyFileDB *kf_db, gpointer user_data)
void
nm_settings_kf_db_write(NMSettings *self)
{
- NMSettingsPrivate *priv;
-
g_return_if_fail(NM_IS_SETTINGS(self));
- priv = NM_SETTINGS_GET_PRIVATE(self);
- if (priv->kf_db_timestamps)
- nm_key_file_db_to_file(priv->kf_db_timestamps, TRUE);
- if (priv->kf_db_seen_bssids)
- nm_key_file_db_to_file(priv->kf_db_seen_bssids, TRUE);
+ _kf_db_to_file(self, TRUE, TRUE);
+ _kf_db_to_file(self, FALSE, TRUE);
}
/*****************************************************************************/
@@ -4031,8 +4060,8 @@ finalize(GObject *object)
nm_clear_g_source(&priv->kf_db_flush_idle_id_timestamps);
nm_clear_g_source(&priv->kf_db_flush_idle_id_seen_bssids);
- nm_key_file_db_to_file(priv->kf_db_timestamps, FALSE);
- nm_key_file_db_to_file(priv->kf_db_seen_bssids, FALSE);
+ _kf_db_to_file(self, TRUE, FALSE);
+ _kf_db_to_file(self, FALSE, FALSE);
nm_key_file_db_destroy(priv->kf_db_timestamps);
nm_key_file_db_destroy(priv->kf_db_seen_bssids);