summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-07-19 14:37:57 +0200
committerThomas Haller <thaller@redhat.com>2019-07-25 22:02:00 +0200
commitaade7e5317253be58c4a5091bbb978e2a9adc0cd (patch)
tree45c0eb5c0cecfd385ba79ebc3575a94dfd50d279
parentc7e2fe7da6899b09e24791e8a82c6de4e623e2b3 (diff)
downloadNetworkManager-aade7e5317253be58c4a5091bbb978e2a9adc0cd.tar.gz
settings: refactor handling of storages with meta-data/tombstones
Currently, meta-data has a very narrow use: as tombstones. Later, we will need to store additional per UUID meta-data. For example, when a profile becomes unsaved, we may need to remember the original filename. Refactor the code for that. This is for the most part just renaming and slightly different handling of the fields.
-rw-r--r--src/settings/nm-settings.c46
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.c56
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.c97
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.h116
4 files changed, 195 insertions, 120 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 66858ed99b..3e7d847b58 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -168,16 +168,12 @@ nm_assert_storage_data_lst (CList *head)
static gboolean
_storage_data_is_alive (StorageData *sd)
{
- if (sd->connection)
- return TRUE;
-
- if (nm_settings_storage_is_keyfile_tombstone (sd->storage)) {
- /* entry does not have a profile, but it's here as a tombstone to
- * hide/shadow other connections. That's also relevant. */
- return TRUE;
- }
-
- return FALSE;
+ /* If the storage tracks a connection, it is considered alive.
+ *
+ * Meta-data storages are special: they never track a connection.
+ * We need to check them specially to know when to drop them. */
+ return sd->connection
+ || nm_settings_storage_is_meta_data_alive (sd->storage);
}
/*****************************************************************************/
@@ -1192,6 +1188,7 @@ _connection_changed_track (NMSettings *self,
if (_LOGT_ENABLED ()) {
const char *filename;
+ const NMSettingsMetaData *meta_data;
filename = nm_settings_storage_get_filename (storage);
if (connection) {
@@ -1200,11 +1197,18 @@ _connection_changed_track (NMSettings *self,
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
nm_connection_get_id (connection),
NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
- } else if (nm_settings_storage_is_keyfile_tombstone (storage)) {
- _LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event for hiding profile%s%s%s",
- sett_conn_entry->uuid,
- NM_SETTINGS_STORAGE_PRINT_ARG (storage),
- NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
+ } else if ((meta_data = nm_settings_storage_is_meta_data (storage))) {
+ if (meta_data->is_tombstone) {
+ _LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event for hiding profile%s%s%s",
+ sett_conn_entry->uuid,
+ NM_SETTINGS_STORAGE_PRINT_ARG (storage),
+ NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
+ } else {
+ _LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event with meta data for profile%s%s%s",
+ sett_conn_entry->uuid,
+ NM_SETTINGS_STORAGE_PRINT_ARG (storage),
+ NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
+ }
} else {
_LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event for dropping profile%s%s%s",
sett_conn_entry->uuid,
@@ -1467,8 +1471,12 @@ nm_settings_add_connection (NMSettings *self,
sett_conn_entry = _connection_changed_track (self, new_storage, new_connection, TRUE);
c_list_for_each_entry (sd, &sett_conn_entry->sd_lst_head, sd_lst) {
+ const NMSettingsMetaData *meta_data;
+
+ meta_data = nm_settings_storage_is_meta_data_alive (sd->storage);
- if (!nm_settings_storage_is_keyfile_tombstone (sd->storage))
+ if ( !meta_data
+ || !meta_data->is_tombstone)
continue;
if (nm_settings_storage_is_keyfile_run (sd->storage)) {
@@ -1484,7 +1492,7 @@ nm_settings_add_connection (NMSettings *self,
sd->storage,
NULL);
- nm_assert (!nm_settings_storage_is_keyfile_tombstone (sd->storage));
+ nm_assert (!_storage_data_is_alive (sd));
_connection_changed_track (self, sd->storage, NULL, FALSE);
}
@@ -1871,10 +1879,10 @@ nm_settings_delete_connection (NMSettings *self,
c_list_for_each_entry (sd, &sett_conn_entry->sd_lst_head, sd_lst) {
if (sd->storage == cur_storage)
continue;
- if (nm_settings_storage_is_keyfile_tombstone (sd->storage))
- continue;
if (!_storage_data_is_alive (sd))
continue;
+ if (nm_settings_storage_is_meta_data (sd->storage))
+ continue;
/* we have still conflicting storages. We need to hide them with tombstones. */
if (nm_settings_storage_is_keyfile_run (sd->storage)) {
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index de076c0122..a7048a8dd1 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -244,7 +244,7 @@ _nm_assert_storage (gpointer plugin /* NMSKeyfilePlugin */,
nm_assert (!plugin || NMS_IS_KEYFILE_PLUGIN (plugin));
nm_assert (NMS_IS_KEYFILE_STORAGE (storage));
nm_assert (!plugin || plugin == nm_settings_storage_get_plugin (storage));
- nm_assert (!((NMSKeyfileStorage *) storage)->is_tombstone || !(((NMSKeyfileStorage *) storage)->connection));
+
nm_assert (({
const char *f = nms_keyfile_storage_get_filename (storage);
f && f[0] == '/';
@@ -254,6 +254,11 @@ _nm_assert_storage (gpointer plugin /* NMSKeyfilePlugin */,
nm_assert (nm_utils_is_uuid (uuid));
+ nm_assert ( ((NMSKeyfileStorage *) storage)->is_meta_data
+ || !(((NMSKeyfileStorage *) storage)->u.conn_data.connection)
+ || ( NM_IS_CONNECTION ((((NMSKeyfileStorage *) storage)->u.conn_data.connection))
+ && nm_streq0 (uuid, nm_connection_get_uuid ((((NMSKeyfileStorage *) storage)->u.conn_data.connection)))));
+
nm_assert ( !tracked
|| !plugin
|| c_list_contains (&NMS_KEYFILE_PLUGIN_GET_PRIVATE (plugin)->storages._storage_lst_head,
@@ -264,7 +269,8 @@ _nm_assert_storage (gpointer plugin /* NMSKeyfilePlugin */,
|| storage == g_hash_table_lookup (NMS_KEYFILE_PLUGIN_GET_PRIVATE (plugin)->storages.idx_by_filename,
nms_keyfile_storage_get_filename (storage)));
- if (tracked && plugin) {
+ if ( tracked
+ && plugin) {
sbuh = g_hash_table_lookup (NMS_KEYFILE_PLUGIN_GET_PRIVATE (plugin)->storages.idx_by_uuid, &uuid);
nm_assert (sbuh);
nm_assert (c_list_contains (&sbuh->_storage_by_uuid_lst_head, &((NMSKeyfileStorage *) storage)->parent._storage_by_uuid_lst));
@@ -454,7 +460,7 @@ _storages_consolidate (NMSKeyfilePlugin *self,
c_list_init (&storages_deleted);
c_list_for_each_entry (storage_old, &priv->storages._storage_lst_head, parent._storage_lst)
- storage_old->dirty = TRUE;
+ storage_old->is_dirty = TRUE;
c_list_for_each_entry_safe (storage_new, storage_safe, &storages_new->_storage_lst_head, parent._storage_lst) {
storage_old = nm_sett_util_storages_lookup_by_filename (&priv->storages, nms_keyfile_storage_get_filename (storage_new));
@@ -465,28 +471,28 @@ _storages_consolidate (NMSKeyfilePlugin *self,
|| !nm_streq (nms_keyfile_storage_get_uuid (storage_new), nms_keyfile_storage_get_uuid (storage_old))) {
if (storage_old) {
nm_sett_util_storages_steal (&priv->storages, storage_old);
- c_list_link_tail (&storages_deleted, &storage_old->parent._storage_lst);
+ c_list_link_tail (&storages_deleted, &storage_old->parent._storage_by_uuid_lst);
}
- storage_new->dirty = FALSE;
+ storage_new->is_dirty = FALSE;
nm_sett_util_storages_add_take (&priv->storages, storage_new);
g_ptr_array_add (storages_modified, g_object_ref (storage_new));
continue;
}
- storage_old->dirty = FALSE;
+ storage_old->is_dirty = FALSE;
nms_keyfile_storage_copy_content (storage_old, storage_new);
nms_keyfile_storage_destroy (storage_new);
g_ptr_array_add (storages_modified, g_object_ref (storage_old));
}
c_list_for_each_entry_safe (storage_old, storage_safe, &priv->storages._storage_lst_head, parent._storage_lst) {
- if (!storage_old->dirty)
+ if (!storage_old->is_dirty)
continue;
if ( replace_all
|| ( storages_replaced
&& g_hash_table_contains (storages_replaced, storage_old))) {
nm_sett_util_storages_steal (&priv->storages, storage_old);
- c_list_link_tail (&storages_deleted, &storage_old->parent._storage_lst);
+ c_list_link_tail (&storages_deleted, &storage_old->parent._storage_by_uuid_lst);
}
}
@@ -494,7 +500,7 @@ _storages_consolidate (NMSKeyfilePlugin *self,
for (i = 0; i < storages_modified->len; i++) {
storage = storages_modified->pdata[i];
- storage->dirty = TRUE;
+ storage->is_dirty = TRUE;
}
for (i = 0; i < storages_modified->len; i++) {
@@ -502,19 +508,22 @@ _storages_consolidate (NMSKeyfilePlugin *self,
storage = storages_modified->pdata[i];
- if (!storage->dirty) {
- /* the entry is no longer dirty. In the meantime we already emited
+ if (!storage->is_dirty) {
+ /* the entry is no longer is_dirty. In the meantime we already emited
* another signal for it. */
continue;
}
- storage->dirty = FALSE;
- if (storage != nm_sett_util_storages_lookup_by_filename (&priv->storages, nms_keyfile_storage_get_filename (storage))) {
+ storage->is_dirty = FALSE;
+
+ if (c_list_is_empty (&storage->parent._storage_lst)) {
/* hm? The profile was deleted in the meantime? That is only possible
* if the signal handler called again into the plugin. In any case, the event
* was already emitted. Skip. */
continue;
}
+ nm_assert (storage == nm_sett_util_storages_lookup_by_filename (&priv->storages, nms_keyfile_storage_get_filename (storage)));
+
connection = nms_keyfile_storage_steal_connection (storage);
callback (NM_SETTINGS_PLUGIN (self),
@@ -523,9 +532,8 @@ _storages_consolidate (NMSKeyfilePlugin *self,
user_data);
}
- while ((storage = c_list_first_entry (&storages_deleted, NMSKeyfileStorage, parent._storage_lst))) {
- c_list_unlink (&storage->parent._storage_lst);
- storage->is_tombstone = FALSE;
+ while ((storage = c_list_first_entry (&storages_deleted, NMSKeyfileStorage, parent._storage_by_uuid_lst))) {
+ c_list_unlink (&storage->parent._storage_by_uuid_lst);
callback (NM_SETTINGS_PLUGIN (self),
NM_SETTINGS_STORAGE (storage),
NULL,
@@ -851,6 +859,7 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
|| storage->storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN);
nm_assert ( priv->dirname_etc
|| storage->storage_type != NMS_KEYFILE_STORAGE_TYPE_ETC);
+ nm_assert (!storage->is_meta_data);
previous_filename = nms_keyfile_storage_get_filename (storage);
uuid = nms_keyfile_storage_get_uuid (storage);
@@ -895,9 +904,9 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
uuid,
nm_connection_get_id (connection));
- storage->is_nm_generated = is_nm_generated;
- storage->is_volatile = is_volatile;
- storage->stat_mtime = *nm_sett_util_stat_mtime (full_filename, FALSE, &mtime);
+ storage->u.conn_data.is_nm_generated = is_nm_generated;
+ storage->u.conn_data.is_volatile = is_volatile;
+ storage->u.conn_data.stat_mtime = *nm_sett_util_stat_mtime (full_filename, FALSE, &mtime);
*out_storage = g_object_ref (NM_SETTINGS_STORAGE (storage));
*out_connection = g_steal_pointer (&reread);
@@ -969,14 +978,13 @@ delete_connection (NMSettingsPlugin *plugin,
_LOGT ("commit: deleted \"%s\", %s %s (%s%s%s%s)",
previous_filename,
- storage->is_tombstone ? "tombstone" : "profile",
+ storage->is_meta_data ? "meta-data" : "profile",
uuid,
operation_message,
NM_PRINT_FMT_QUOTED (remove_from_disk_errmsg, ": ", remove_from_disk_errmsg, "", ""));
if (success) {
nm_sett_util_storages_steal (&priv->storages, storage);
- storage->is_tombstone = FALSE;
nms_keyfile_storage_destroy (storage);
}
@@ -1088,7 +1096,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
storage = nm_sett_util_storages_lookup_by_filename (&priv->storages, nmmeta_filename);
nm_assert ( !storage
- || ( storage->is_tombstone
+ || ( storage->is_meta_data
&& storage->storage_type == storage_type
&& nm_streq (nms_keyfile_storage_get_uuid (storage), uuid)));
@@ -1104,10 +1112,8 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
storage_result = g_object_ref (storage);
} else {
- if (storage) {
+ if (storage)
storage_result = nm_sett_util_storages_steal (&priv->storages, storage);
- storage_result->is_tombstone = FALSE;
- }
}
out:
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.c b/src/settings/plugins/keyfile/nms-keyfile-storage.c
index d38e187d22..33ebb8f941 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.c
@@ -41,24 +41,32 @@ nms_keyfile_storage_copy_content (NMSKeyfileStorage *dst,
{
nm_assert (src != dst);
nm_assert (nm_streq (nms_keyfile_storage_get_uuid (dst), nms_keyfile_storage_get_uuid (src)));
- nm_assert (nms_keyfile_storage_get_filename (dst) && nm_streq (nms_keyfile_storage_get_filename (dst), nms_keyfile_storage_get_filename (src)));
-
- nm_g_object_ref_set (&dst->connection, src->connection);
- dst->storage_type = src->storage_type;
- dst->stat_mtime = src->stat_mtime;
- dst->is_nm_generated = src->is_nm_generated;
- dst->is_volatile = src->is_volatile;
- dst->is_tombstone = src->is_tombstone;
+ nm_assert ( nms_keyfile_storage_get_filename (dst)
+ && nm_streq (nms_keyfile_storage_get_filename (dst), nms_keyfile_storage_get_filename (src)));
+ nm_assert (dst->storage_type == src->storage_type);
+ nm_assert (dst->is_meta_data == src->is_meta_data);
+
+ if (dst->is_meta_data)
+ dst->u.meta_data = src->u.meta_data;
+ else {
+ gs_unref_object NMConnection *connection_to_free = NULL;
+
+ connection_to_free = g_steal_pointer (&dst->u.conn_data.connection);
+ dst->u.conn_data = src->u.conn_data;
+ nm_g_object_ref (dst->u.conn_data.connection);
+ }
}
NMConnection *
nms_keyfile_storage_steal_connection (NMSKeyfileStorage *self)
{
nm_assert (NMS_IS_KEYFILE_STORAGE (self));
- nm_assert ( (!self->connection && self->is_tombstone)
- || NM_IS_CONNECTION (self->connection));
+ nm_assert ( self->is_meta_data
+ || NM_IS_CONNECTION (self->u.conn_data.connection));
- return g_steal_pointer (&self->connection);
+ return self->is_meta_data
+ ? NULL
+ : g_steal_pointer (&self->u.conn_data.connection);
}
/*****************************************************************************/
@@ -75,16 +83,19 @@ cmp_fcn (const NMSKeyfileStorage *a,
* (inverse) priority. */
NM_CMP_FIELD_UNSAFE (b, a, storage_type);
- /* tombstones are more important. */
- nm_assert (a->is_tombstone == nm_settings_storage_is_keyfile_tombstone (NM_SETTINGS_STORAGE (a)));
- nm_assert (b->is_tombstone == nm_settings_storage_is_keyfile_tombstone (NM_SETTINGS_STORAGE (b)));
- NM_CMP_FIELD_UNSAFE (a, b, is_tombstone);
+ /* meta-data is more important. */
+ NM_CMP_FIELD_UNSAFE (a, b, is_meta_data);
- /* newer files are more important. */
- NM_CMP_FIELD (a, b, stat_mtime.tv_sec);
- NM_CMP_FIELD (a, b, stat_mtime.tv_nsec);
+ if (a->is_meta_data) {
+ nm_assert (nm_streq (nms_keyfile_storage_get_filename (a), nms_keyfile_storage_get_filename (b)));
+ NM_CMP_FIELD_UNSAFE (a, b, u.meta_data.is_tombstone);
+ } else {
+ /* newer files are more important. */
+ NM_CMP_FIELD (a, b, u.conn_data.stat_mtime.tv_sec);
+ NM_CMP_FIELD (a, b, u.conn_data.stat_mtime.tv_nsec);
- NM_CMP_DIRECT_STRCMP (nms_keyfile_storage_get_filename (a), nms_keyfile_storage_get_filename (b));
+ NM_CMP_DIRECT_STRCMP (nms_keyfile_storage_get_filename (a), nms_keyfile_storage_get_filename (b));
+ }
return 0;
}
@@ -99,17 +110,27 @@ nms_keyfile_storage_init (NMSKeyfileStorage *self)
static NMSKeyfileStorage *
_storage_new (NMSKeyfilePlugin *plugin,
const char *uuid,
- const char *filename)
+ const char *filename,
+ gboolean is_meta_data,
+ NMSKeyfileStorageType storage_type)
+
{
+ NMSKeyfileStorage *self;
+
nm_assert (NMS_IS_KEYFILE_PLUGIN (plugin));
nm_assert (nm_utils_is_uuid (uuid));
nm_assert (filename && filename[0] == '/');
- return g_object_new (NMS_TYPE_KEYFILE_STORAGE,
+ self = g_object_new (NMS_TYPE_KEYFILE_STORAGE,
NM_SETTINGS_STORAGE_PLUGIN, plugin,
NM_SETTINGS_STORAGE_UUID, uuid,
NM_SETTINGS_STORAGE_FILENAME, filename,
NULL);
+
+ *((bool *) &self->is_meta_data) = is_meta_data;
+ *((NMSKeyfileStorageType *) &self->storage_type) = storage_type;
+
+ return self;
}
NMSKeyfileStorage *
@@ -126,12 +147,8 @@ nms_keyfile_storage_new_tombstone (NMSKeyfilePlugin *plugin,
nm_assert (NM_IN_SET (storage_type, NMS_KEYFILE_STORAGE_TYPE_ETC,
NMS_KEYFILE_STORAGE_TYPE_RUN));
- self = _storage_new (plugin, uuid, filename);
-
- self->is_tombstone = TRUE;
-
- self->storage_type = storage_type;
-
+ self = _storage_new (plugin, uuid, filename, TRUE, storage_type);
+ self->u.meta_data.is_tombstone = TRUE;
return self;
}
@@ -154,19 +171,17 @@ nms_keyfile_storage_new_connection (NMSKeyfilePlugin *plugin,
&& storage_type <= _NMS_KEYFILE_STORAGE_TYPE_LIB_LAST);
nmtst_connection_assert_unchanging (connection_take);
- self = _storage_new (plugin, nm_connection_get_uuid (connection_take), filename);
-
- self->connection = connection_take; /* take reference. */
+ self = _storage_new (plugin, nm_connection_get_uuid (connection_take), filename, FALSE, storage_type);
- if (storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN) {
- self->is_nm_generated = (is_nm_generated_opt == NM_TERNARY_TRUE);
- self->is_volatile = (is_volatile_opt == NM_TERNARY_TRUE);
- }
+ self->u.conn_data.connection = connection_take; /* take reference. */
if (stat_mtime)
- self->stat_mtime = *stat_mtime;
+ self->u.conn_data.stat_mtime = *stat_mtime;
- self->storage_type = storage_type;
+ if (storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN) {
+ self->u.conn_data.is_nm_generated = (is_nm_generated_opt == NM_TERNARY_TRUE);
+ self->u.conn_data.is_volatile = (is_volatile_opt == NM_TERNARY_TRUE);
+ }
return self;
}
@@ -176,7 +191,8 @@ _storage_clear (NMSKeyfileStorage *self)
{
c_list_unlink (&self->parent._storage_lst);
c_list_unlink (&self->parent._storage_by_uuid_lst);
- g_clear_object (&self->connection);
+ if (!self->is_meta_data)
+ g_clear_object (&self->u.conn_data.connection);
}
static void
@@ -226,12 +242,15 @@ nm_settings_storage_load_sett_flags (NMSettingsStorage *self,
return;
s = NMS_KEYFILE_STORAGE (self);
+
+ if (s->is_meta_data)
+ return;
if (s->storage_type != NMS_KEYFILE_STORAGE_TYPE_RUN)
return;
- if (s->is_nm_generated)
+ if (s->u.conn_data.is_nm_generated)
*sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED;
- if (s->is_volatile)
+ if (s->u.conn_data.is_volatile)
*sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE;
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.h b/src/settings/plugins/keyfile/nms-keyfile-storage.h
index 0cc537b7bf..7968da09ac 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.h
@@ -34,6 +34,11 @@
#define NMS_KEYFILE_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_KEYFILE_STORAGE, NMSKeyfileStorageClass))
typedef struct {
+ /* whether this is a tombstone to hide a UUID (via symlink to /dev/null). */
+ bool is_tombstone:1;
+} NMSettingsMetaData;
+
+typedef struct {
NMSettingsStorage parent;
/* The connection. Note that there are tombstones (loaded-uuid files to /dev/null)
@@ -42,35 +47,45 @@ typedef struct {
* Also, we don't actually remember the loaded connection after returning it
* to NMSettings. So, also for regular storages (non-tombstones) this field
* is often cleared. */
- NMConnection *connection;
-
- NMSKeyfileStorageType storage_type;
-
- /* the timestamp (stat's mtime) of the keyfile. For tombstones this
- * is irrelevant. The purpose is that if the same storage type (directory) has
- * multiple files with the same UUID, then the newer file gets preferred. */
- struct timespec stat_mtime;
-
- /* these flags are only relevant for storages with %NMS_KEYFILE_STORAGE_TYPE_RUN
- * (and non-tombstones). This is to persist and reload these settings flags to
- * /run. */
- bool is_nm_generated:1;
- bool is_volatile:1;
-
- /* whether this is a tombstone to hide a UUID (via the loaded uuid symlinks).
- * If this is falls, the storage contains a profile, though note that
- * the connection field will be cleared when it's not used. So, a non-tombstone
- * has a connection in principle, but the connection field may still be %NULL.
- *
- * Note that a tombstone instance doesn't have a connection, but NMSettings
- * considers it alive because is_tombstone is %TRUE. That means, once a tombstone
- * gets removed, this flag is cleared. Then the storage instance has no connnection
- * and is no longer a tombstone, and NMSettings considers it ready for deletion.
- */
- bool is_tombstone:1;
+ union {
+ struct {
+ NMConnection *connection;
+
+ /* the timestamp (stat's mtime) of the keyfile. For meta-data this
+ * is irrelevant. The purpose is that if the same storage type (directory) has
+ * multiple files with the same UUID, then the newer file gets preferred. */
+ struct timespec stat_mtime;
+
+ /* these flags are only relevant for storages with %NMS_KEYFILE_STORAGE_TYPE_RUN
+ * (and non-metadata). This is to persist and reload these settings flags to
+ * /run.
+ *
+ * Note that these flags are not stored in as meta-data. The reason is that meta-data
+ * is per UUID. But these flags are only relevant for a particular keyfile on disk.
+ * That is, it must be tied to the actual keyfile, and not to the UUID. */
+ bool is_nm_generated:1;
+ bool is_volatile:1;
+
+ } conn_data;
+
+ /* the content from the .nmmeta file. Note that the nmmeta file has the UUID
+ * in the filename, that means there can be only two variants of this file:
+ * in /etc and in /run. As such, this is really meta-data about the entire profile
+ * (the UUID), and not about the individual keyfile. */
+ NMSettingsMetaData meta_data;
+
+ } u;
+
+ /* The storage type. This is directly related to the filename. Since
+ * the filename cannot change, this value is unchanging. */
+ const NMSKeyfileStorageType storage_type;
+
+ /* whether union "u" has meta_data or conn_data. Since the type of the storage
+ * depends on the (immutable) filename, this is also const. */
+ const bool is_meta_data;
/* this flag is only used during reload to mark and prune old entries. */
- bool dirty:1;
+ bool is_dirty:1;
} NMSKeyfileStorage;
@@ -132,18 +147,45 @@ nm_settings_storage_is_keyfile_lib (const NMSettingsStorage *self)
&& (((NMSKeyfileStorage *) self)->storage_type >= NMS_KEYFILE_STORAGE_TYPE_LIB_BASE);
}
-static inline gboolean
-nm_settings_storage_is_keyfile_tombstone (const NMSettingsStorage *self)
+static inline const NMSettingsMetaData *
+nm_settings_storage_is_meta_data (const NMSettingsStorage *storage)
+{
+ const NMSKeyfileStorage *self;
+
+ if (!NMS_IS_KEYFILE_STORAGE (storage))
+ return NULL;
+
+ self = (NMSKeyfileStorage *) storage;
+
+ if (!self->is_meta_data)
+ return NULL;
+
+ return &self->u.meta_data;
+}
+
+static inline const NMSettingsMetaData *
+nm_settings_storage_is_meta_data_alive (const NMSettingsStorage *storage)
{
- /* Only keyfile storage supports tombstones. They indicate that a uuid
- * is shadowed via a symlink to /dev/null.
+ const NMSettingsMetaData *meta_data;
+
+ meta_data = nm_settings_storage_is_meta_data (storage);
+
+ if (!meta_data)
+ return NULL;
+
+ /* Regular (all other) storages are alive as long as they report a NMConnection, and
+ * they will be dropped, once they have no more connection.
*
- * Note that tombstones don't have a NMConnection instead they shadow
- * a UUID. As such, NMSettings considers them alive also if they have
- * not profile. That means, when a tombstone gets removed for good,
- * the is_tombstone must be cleared (so that it becomes truly dead). */
- return NMS_IS_KEYFILE_STORAGE (self)
- && ((NMSKeyfileStorage *) self)->is_tombstone;
+ * Meta-data storages are special: they never report a NMConnection.
+ * So, a meta-data storage is alive as long as it is tracked by the
+ * settings plugin.
+ *
+ * This function is used to ckeck for that. */
+
+ if (c_list_is_empty (&storage->_storage_lst))
+ return NULL;
+
+ return meta_data;
}
/*****************************************************************************/