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; - if (!nm_settings_storage_is_keyfile_tombstone (sd->storage)) + meta_data = nm_settings_storage_is_meta_data_alive (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_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); - 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; + 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 = _storage_new (plugin, nm_connection_get_uuid (connection_take), filename, FALSE, storage_type); - self->connection = connection_take; /* take reference. */ - - 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 @@ -33,6 +33,11 @@ #define NMS_IS_KEYFILE_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_KEYFILE_STORAGE)) #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; @@ -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; + union { + struct { + NMConnection *connection; - NMSKeyfileStorageType storage_type; + /* 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; - /* 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-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; - /* 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; + } conn_data; - /* 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; + /* 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) { - /* Only keyfile storage supports tombstones. They indicate that a uuid - * is shadowed via a symlink to /dev/null. + 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) +{ + 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; } /*****************************************************************************/