about summary refs log tree commit diff
path: root/src/settings
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-08-19 10:13:49 +0200
committerMichael Biebl <biebl@debian.org>2020-08-19 10:13:49 +0200
commite7b44ef4c80907346ec7492a09c45277459924fc (patch)
treeb1388af193ca205f73336eca47e81815e43a61ca /src/settings
parent136d191f1c96dbae1489fed7c2565f5e1b1f8d40 (diff)
New upstream version 1.26.2 upstream/1.26.2
Diffstat (limited to 'src/settings')
-rw-r--r--src/settings/nm-settings.c384
-rw-r--r--src/settings/nm-settings.h6
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.c1
3 files changed, 227 insertions, 164 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 0a1e7b47..4573d5f7 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -60,6 +60,7 @@
 #include "plugins/keyfile/nms-keyfile-storage.h"
 #include "nm-agent-manager.h"
 #include "nm-config.h"
+#include "nm-manager.h"
 #include "nm-audit-manager.h"
 #include "NetworkManagerUtils.h"
 #include "nm-dispatcher.h"
@@ -324,6 +325,7 @@ _sett_conn_entry_find_shadowed_storage (SettConnEntry *sett_conn_entry,
 /*****************************************************************************/
 
 NM_GOBJECT_PROPERTIES_DEFINE (NMSettings,
+	PROP_MANAGER,
 	PROP_UNMANAGED_SPECS,
 	PROP_HOSTNAME,
 	PROP_CAN_MODIFY,
@@ -348,6 +350,8 @@ typedef struct {
 
 	NMPlatform *platform;
 
+	NMManager *manager;
+
 	NMHostnameManager *hostname_manager;
 
 	NMSessionMonitor *session_monitor;
@@ -372,9 +376,9 @@ typedef struct {
 	GSList *unmanaged_specs;
 	GSList *unrecognized_specs;
 
+	gint64 startup_complete_start_timestamp_msec;
 	GHashTable *startup_complete_idx;
-	NMSettingsConnection *startup_complete_blocked_by;
-	gulong startup_complete_platform_change_id;
+	CList startup_complete_scd_lst_head;
 	guint startup_complete_timeout_id;
 
 	guint connections_len;
@@ -423,7 +427,7 @@ static void default_wired_clear_tag (NMSettings *self,
 static void _clear_connections_cached_list (NMSettingsPrivate *priv);
 
 static void _startup_complete_check (NMSettings *self,
-                                     gint64 now_us);
+                                     gint64 now_msec);
 
 /*****************************************************************************/
 
@@ -461,34 +465,53 @@ _emit_connection_flags_changed (NMSettings *self,
 
 typedef struct {
 	NMSettingsConnection *sett_conn;
-	gint64 start_at;
-	gint64 timeout;
+	CList scd_lst;
+	gint64 timeout_msec;
 } StartupCompleteData;
 
 static void
 _startup_complete_data_destroy (StartupCompleteData *scd)
 {
+	c_list_unlink_stale (&scd->scd_lst);
 	g_object_unref (scd->sett_conn);
-	g_slice_free (StartupCompleteData, scd);
+	nm_g_slice_free (scd);
 }
 
 static gboolean
-_startup_complete_check_is_ready (NMPlatform *platform,
-                                  NMSettingsConnection *sett_conn)
+_startup_complete_check_is_ready (NMSettings *self,
+                                  NMSettingsConnection *sett_conn,
+                                  gboolean ignore_pending_actions)
 {
-	const NMPlatformLink *plink;
-	const char *ifname;
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+	NMConnection *conn;
+	const CList *tmp_lst;
+	NMDevice *device;
 
-	/* FIXME: instead of just looking for the interface name, it would be better
-	 *        to wait for a device that is compatible with the profile. */
+	if (!priv->manager)
+		return TRUE;
 
-	ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (sett_conn));
+	conn = nm_settings_connection_get_connection (sett_conn);
+
+	nm_manager_for_each_device (priv->manager, device, tmp_lst) {
+
+		if (!nm_device_is_real (device))
+			continue;
+
+		if (   nm_device_get_state (device) < NM_DEVICE_STATE_UNAVAILABLE
+		    || (   !ignore_pending_actions
+		        && nm_device_has_pending_action (device))) {
+			/* while a device is not yet available and still has a pending
+			 * action itself, it's not a suitable candidate. */
+			continue;
+		}
+
+		if (!nm_device_check_connection_compatible (device, conn, NULL))
+			continue;
 
-	if (!ifname)
 		return TRUE;
+	}
 
-	plink = nm_platform_link_get_by_ifname (platform, ifname);
-	return plink && plink->initialized;
+	return FALSE;
 }
 
 static gboolean
@@ -503,116 +526,97 @@ _startup_complete_timeout_cb (gpointer user_data)
 }
 
 static void
-_startup_complete_platform_change_cb (NMPlatform *platform,
-                                      int obj_type_i,
-                                      int ifindex,
-                                      const NMPlatformLink *link,
-                                      int change_type_i,
-                                      NMSettings *self)
-{
-	const NMPlatformSignalChangeType change_type = change_type_i;
-	NMSettingsPrivate *priv;
-	const char *ifname;
-
-	if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
-		return;
-
-	if (!link->initialized)
-		return;
-
-	priv = NM_SETTINGS_GET_PRIVATE (self);
-
-	ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by));
-	if (   ifname
-	    && !nm_streq (ifname, link->name))
-		return;
-
-	nm_assert (priv->startup_complete_timeout_id > 0);
-
-	nm_clear_g_source (&priv->startup_complete_timeout_id);
-	priv->startup_complete_timeout_id = g_idle_add (_startup_complete_timeout_cb, self);
-}
-
-static void
 _startup_complete_check (NMSettings *self,
-                         gint64 now_us)
+                         gint64 now_msec)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	gint64 next_expiry;
+	StartupCompleteData *scd_not_ready;
+	StartupCompleteData *scd_safe;
 	StartupCompleteData *scd;
-	NMSettingsConnection *next_sett_conn = NULL;
-	GHashTableIter iter;
+	gint64 elapsed_msec;
+	CList ready_lst;
+
+	if (priv->startup_complete_start_timestamp_msec == 0) {
+		/* we are already done for good or didn't start yet. */
+		return;
+	}
 
 	if (!priv->started) {
-		/* before we are started, we don't setup the timers... */
+		/* before we are started there is no need to evaluate our list because
+		 * we are anyway blocking startup-complete. */
 		return;
 	}
 
-	if (!priv->startup_complete_idx)
+	if (c_list_is_empty (&priv->startup_complete_scd_lst_head))
 		goto ready;
 
-	if (!now_us)
-		now_us = nm_utils_get_monotonic_timestamp_usec ();
+	nm_utils_get_monotonic_timestamp_msec_cached (&now_msec);
 
-	next_expiry = 0;
+	elapsed_msec = now_msec - priv->startup_complete_start_timestamp_msec;
 
-	g_hash_table_iter_init (&iter, priv->startup_complete_idx);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &scd, NULL)) {
-		gint64 expiry;
-
-		if (scd->start_at == 0) {
-			/* once ready, the decision is remembered and there is nothing
-			 * left to check. */
-			continue;
-		}
+	/* We search the entire list whether they all timed-out or found a compatible device.
+	 * We do that by appending elements that are ready to the end of the list, so that
+	 * we hopefully keep testing the elements that are ready already (and can shortcut
+	 * the test in common cases).
+	 *
+	 * Note that all profiles that we wait for need to have their dependencies satisfied
+	 * at the same time. For example, consider connection A is waiting for device A' which is ready.
+	 * Connection B waits for device B', which isn't ready. Once B'/B becomes ready, A/A' must
+	 * still be ready. Otherwise, we would wait for A/A' to become ready again. */
+	scd_not_ready = NULL;
+	c_list_init (&ready_lst);
+	c_list_for_each_entry_safe (scd, scd_safe, &priv->startup_complete_scd_lst_head, scd_lst) {
 
-		expiry = scd->start_at + scd->timeout;
-		if (expiry <= now_us) {
-			scd->start_at = 0;
-			continue;
-		}
+		if (scd->timeout_msec <= elapsed_msec)
+			goto next_with_ready;
 
-		if (_startup_complete_check_is_ready (priv->platform, scd->sett_conn)) {
-			scd->start_at = 0;
-			continue;
-		}
+		if (_startup_complete_check_is_ready (self, scd->sett_conn, FALSE))
+			goto next_with_ready;
 
-		next_expiry = expiry;
-		next_sett_conn = scd->sett_conn;
-		/* we found one timeout for which to wait. that's good enough. */
+		scd_not_ready = scd;
 		break;
+
+next_with_ready:
+		/* this element is ready. We move it to a temporary list, so that we
+		 * can reorder the list (to next time evaluate the non-ready element first). */
+		nm_c_list_move_tail (&ready_lst, &scd->scd_lst);
 	}
+	c_list_splice (&priv->startup_complete_scd_lst_head, &ready_lst);
 
 	nm_clear_g_source (&priv->startup_complete_timeout_id);
-	nm_g_object_ref_set (&priv->startup_complete_blocked_by, next_sett_conn);
-	if (next_expiry > 0) {
-		nm_assert (priv->startup_complete_blocked_by);
-		if (priv->startup_complete_platform_change_id == 0) {
-			priv->startup_complete_platform_change_id = g_signal_connect (priv->platform,
-			                                                              NM_PLATFORM_SIGNAL_LINK_CHANGED,
-			                                                              G_CALLBACK (_startup_complete_platform_change_cb),
-			                                                              self);
-		}
-		priv->startup_complete_timeout_id = g_timeout_add (NM_MIN (3600u*1000u, (next_expiry - now_us) / 1000u),
+
+	if (scd_not_ready) {
+		gint64 timeout_msec;
+
+		timeout_msec = priv->startup_complete_start_timestamp_msec + scd_not_ready->timeout_msec - nm_utils_get_monotonic_timestamp_msec ();
+		priv->startup_complete_timeout_id = g_timeout_add (NM_CLAMP (0, timeout_msec, 60000),
 		                                                   _startup_complete_timeout_cb,
 		                                                   self);
-		_LOGT ("startup-complete: wait for device \"%s\" due to connection %s (%s)",
-		       nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by)),
-		       nm_settings_connection_get_uuid (priv->startup_complete_blocked_by),
-		       nm_settings_connection_get_id (priv->startup_complete_blocked_by));
+		_LOGT ("startup-complete: wait for suitable device for connection \"%s\" (%s) which has \"connection.wait-device-timeout\" set",
+		       nm_settings_connection_get_id (scd_not_ready->sett_conn),
+		       nm_settings_connection_get_uuid (scd_not_ready->sett_conn));
 		return;
 	}
 
-	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
-	nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
+	if (_LOGW_ENABLED ()) {
+		c_list_for_each_entry (scd, &priv->startup_complete_scd_lst_head, scd_lst) {
+			if (!_startup_complete_check_is_ready (self, scd->sett_conn, TRUE)) {
+				_LOGW ("startup-complete: profile \"%s\" (%s) was waiting for non-existing device (with timeout \"connection.wait-device-timeout=%"G_GINT64_FORMAT"\")",
+				       nm_settings_connection_get_id (scd->sett_conn),
+				       nm_settings_connection_get_uuid (scd->sett_conn),
+				       scd->timeout_msec);
+			}
+		}
+	}
 
 ready:
-	_LOGT ("startup-complete: ready, no profiles to wait for");
+	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
+	nm_assert (c_list_is_empty (&priv->startup_complete_scd_lst_head));
 	nm_assert (priv->started);
-	nm_assert (!priv->startup_complete_blocked_by);
+	_LOGT ("startup-complete: ready, no more profiles to wait for");
+	priv->startup_complete_start_timestamp_msec = 0;
 	nm_assert (!priv->startup_complete_idx);
 	nm_assert (priv->startup_complete_timeout_id == 0);
-	nm_assert (priv->startup_complete_platform_change_id == 0);
 	_notify (self, PROP_STARTUP_COMPLETE);
 }
 
@@ -622,75 +626,95 @@ _startup_complete_notify_connection (NMSettings *self,
                                      gboolean forget)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	gint64 timeout;
-	gint64 now_us = 0;
-
-	nm_assert (   !priv->started
-	           || priv->startup_complete_idx);
-
-	timeout = 0;
-	if (!forget) {
-		NMSettingConnection *s_con;
-		gint32 v;
-
-		s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn));
-		v = nm_setting_connection_get_wait_device_timeout (s_con);
-		if (v > 0) {
-			nm_assert (nm_setting_connection_get_interface_name (s_con));
-			timeout = ((gint64) v) * 1000;
-		}
+	StartupCompleteData *scd;
+	gint64 timeout_msec;
+	gint64 now_msec = 0;
+	NMSettingConnection *s_con;
+	gint32 v;
+
+	nm_assert (priv->startup_complete_start_timestamp_msec != 0);
+
+	if (forget) {
+		if (!priv->startup_complete_idx)
+			return;
+		if (!g_hash_table_remove (priv->startup_complete_idx, &sett_conn))
+			return;
+		goto check;
 	}
 
-	if (timeout == 0) {
-		if (   !priv->startup_complete_idx
-		    || !g_hash_table_remove (priv->startup_complete_idx, &sett_conn))
+	s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn));
+	v = nm_setting_connection_get_wait_device_timeout (s_con);
+	if (v > 0)
+		timeout_msec = v;
+	else
+		timeout_msec = 0;
+
+	if (!priv->startup_complete_idx) {
+		nm_assert (!priv->started);
+
+		if (timeout_msec == 0)
+			return;
+
+		priv->startup_complete_idx = g_hash_table_new_full (nm_pdirect_hash,
+		                                                    nm_pdirect_equal,
+		                                                    NULL,
+		                                                    (GDestroyNotify) _startup_complete_data_destroy);
+		scd = NULL;
+	} else
+		scd = g_hash_table_lookup (priv->startup_complete_idx, &sett_conn);
+
+	if (!scd) {
+		if (timeout_msec == 0)
 			return;
+		scd = g_slice_new (StartupCompleteData);
+		*scd = (StartupCompleteData) {
+			.sett_conn    = g_object_ref (sett_conn),
+			.timeout_msec = timeout_msec,
+		};
+		g_hash_table_add (priv->startup_complete_idx, scd);
+		c_list_link_tail (&priv->startup_complete_scd_lst_head, &scd->scd_lst);
 	} else {
-		StartupCompleteData *scd;
-
-		if (!priv->startup_complete_idx) {
-			nm_assert (!priv->started);
-			priv->startup_complete_idx = g_hash_table_new_full (nm_pdirect_hash,
-			                                                    nm_pdirect_equal,
-			                                                    NULL,
-			                                                    (GDestroyNotify) _startup_complete_data_destroy);
-			scd = NULL;
-		} else
-			scd = g_hash_table_lookup (priv->startup_complete_idx, &sett_conn);
-		if (!scd) {
-			now_us = nm_utils_get_monotonic_timestamp_usec ();
-			scd = g_slice_new (StartupCompleteData);
-			*scd = (StartupCompleteData) {
-				.sett_conn = g_object_ref (sett_conn),
-				.start_at  = now_us,
-				.timeout   = timeout,
-			};
-			g_hash_table_add (priv->startup_complete_idx, scd);
-		} else {
-			if (scd->start_at == 0) {
-				/* the entry already is ready and no longer relevant. Ignore it. */
-				return;
-			}
-			scd->timeout = timeout;
-		}
+		scd->timeout_msec = timeout_msec;
+		nm_c_list_move_front (&priv->startup_complete_scd_lst_head, &scd->scd_lst);
 	}
 
-	_startup_complete_check (self, now_us);
+check:
+	_startup_complete_check (self, now_msec);
 }
 
 const char *
-nm_settings_get_startup_complete_blocked_reason (NMSettings *self)
+nm_settings_get_startup_complete_blocked_reason (NMSettings *self,
+                                                 gboolean force_reload)
 {
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
-	const char *uuid = NULL;
+	StartupCompleteData *scd;
+	const char *uuid;
 
-	if (priv->started) {
-		if (!priv->startup_complete_idx)
-			return NULL;
-		if (priv->startup_complete_blocked_by)
-			uuid = nm_settings_connection_get_uuid (priv->startup_complete_blocked_by);
-	}
-	return uuid ?: "unknown";
+	if (priv->startup_complete_start_timestamp_msec == 0)
+		goto out_done;
+
+	if (force_reload)
+		_startup_complete_check (self, 0);
+
+	if (c_list_is_empty (&priv->startup_complete_scd_lst_head))
+		goto out_done;
+
+	scd = c_list_first_entry (&priv->startup_complete_scd_lst_head, StartupCompleteData, scd_lst);
+
+	nm_assert (scd);
+	nm_assert (NM_IS_SETTINGS_CONNECTION (scd->sett_conn));
+	nm_assert (scd == nm_g_hash_table_lookup (priv->startup_complete_idx, &scd->sett_conn));
+
+	uuid = nm_settings_connection_get_uuid (scd->sett_conn);
+	if (uuid)
+		return uuid;
+
+	g_return_val_if_reached ("settings-starting");
+
+out_done:
+	if (!priv->started)
+		return "settings-starting";
+	return NULL;
 }
 
 /*****************************************************************************/
@@ -1138,8 +1162,7 @@ _connection_changed_update (NMSettings *self,
 		_emit_connection_updated (self, sett_conn, update_reason);
 	}
 
-	if (   !priv->started
-	    || priv->startup_complete_idx) {
+	if (priv->startup_complete_start_timestamp_msec != 0) {
 		if (nm_settings_has_connection (self, sett_conn))
 			_startup_complete_notify_connection (self, sett_conn, FALSE);
 	}
@@ -1213,8 +1236,7 @@ _connection_changed_delete (NMSettings *self,
 	nm_key_file_db_remove_key (priv->kf_db_timestamps, uuid);
 	nm_key_file_db_remove_key (priv->kf_db_seen_bssids, uuid);
 
-	if (   !priv->started
-	    || priv->startup_complete_idx)
+	if (priv->startup_complete_start_timestamp_msec != 0)
 		_startup_complete_notify_connection (self, sett_conn, TRUE);
 }
 
@@ -3711,6 +3733,8 @@ nm_settings_start (NMSettings *self, GError **error)
 
 	nm_assert (!priv->started);
 
+	priv->startup_complete_start_timestamp_msec = nm_utils_get_monotonic_timestamp_msec ();
+
 	priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
 
 	priv->kf_db_timestamps = nm_key_file_db_new (NMSTATEDIR "/timestamps",
@@ -3797,7 +3821,27 @@ get_property (GObject *object, guint prop_id,
 		g_value_take_boxed (value, nm_utils_strv_make_deep_copied (strv));
 		break;
 	case PROP_STARTUP_COMPLETE:
-		g_value_set_boolean (value, !nm_settings_get_startup_complete_blocked_reason (self));
+		g_value_set_boolean (value, !nm_settings_get_startup_complete_blocked_reason (self, FALSE));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettings *self = NM_SETTINGS (object);
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+
+	switch (prop_id) {
+	case PROP_MANAGER:
+		/* construct-only */
+		priv->manager = g_value_get_pointer (value);
+		nm_assert (NM_IS_MANAGER (priv->manager));
+		g_object_add_weak_pointer (G_OBJECT (priv->manager), (gpointer *) &priv->manager);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -3814,6 +3858,7 @@ nm_settings_init (NMSettings *self)
 
 	c_list_init (&priv->auth_lst_head);
 	c_list_init (&priv->connections_lst_head);
+	c_list_init (&priv->startup_complete_scd_lst_head);
 
 	c_list_init (&priv->sce_dirty_lst_head);
 	priv->sce_idx = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
@@ -3833,9 +3878,13 @@ nm_settings_init (NMSettings *self)
 }
 
 NMSettings *
-nm_settings_new (void)
+nm_settings_new (NMManager *manager)
 {
-	return g_object_new (NM_TYPE_SETTINGS, NULL);
+	nm_assert (NM_IS_MANAGER (manager));
+
+	return g_object_new (NM_TYPE_SETTINGS,
+	                     NM_SETTINGS_MANAGER, manager,
+	                     NULL);
 }
 
 static void
@@ -3849,9 +3898,8 @@ dispose (GObject *object)
 	nm_assert (g_hash_table_size (priv->sce_idx) == 0);
 
 	nm_clear_g_source (&priv->startup_complete_timeout_id);
-	nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
 	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
-	g_clear_object (&priv->startup_complete_blocked_by);
+	nm_assert (c_list_is_empty (&priv->startup_complete_scd_lst_head));
 
 	while ((iter = c_list_first (&priv->auth_lst_head)))
 		nm_auth_chain_destroy (nm_auth_chain_parent_lst_entry (iter));
@@ -3915,6 +3963,11 @@ finalize (GObject *object)
 	g_clear_object (&priv->config);
 
 	g_clear_object (&priv->platform);
+
+	if (priv->manager) {
+		g_object_remove_weak_pointer (G_OBJECT (priv->manager), (gpointer *) &priv->manager);
+		priv->manager = NULL;
+	}
 }
 
 static const GDBusSignalInfo signal_info_new_connection = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
@@ -4051,9 +4104,16 @@ nm_settings_class_init (NMSettingsClass *class)
 	dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_settings);
 
 	object_class->get_property = get_property;
+	object_class->set_property = set_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 
+	obj_properties[PROP_MANAGER] =
+	    g_param_spec_pointer (NM_SETTINGS_MANAGER, "", "",
+	                          G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_WRITABLE |
+	                          G_PARAM_STATIC_STRINGS);
+
 	obj_properties[PROP_UNMANAGED_SPECS] =
 	    g_param_spec_boxed (NM_SETTINGS_UNMANAGED_SPECS, "", "",
 	                        G_TYPE_STRV,
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index aa7e36e0..35c62ff7 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -26,6 +26,7 @@
 #define NM_SETTINGS_CAN_MODIFY       "can-modify"
 #define NM_SETTINGS_CONNECTIONS      "connections"
 #define NM_SETTINGS_STARTUP_COMPLETE "startup-complete"
+#define NM_SETTINGS_MANAGER          "manager"
 
 #define NM_SETTINGS_SIGNAL_CONNECTION_ADDED              "connection-added"
 #define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED            "connection-updated"
@@ -53,7 +54,7 @@ GType nm_settings_get_type (void);
 NMSettings *nm_settings_get (void);
 #define NM_SETTINGS_GET (nm_settings_get ())
 
-NMSettings *nm_settings_new (void);
+NMSettings *nm_settings_new (NMManager *manager);
 
 gboolean nm_settings_start (NMSettings *self, GError **error);
 
@@ -122,7 +123,8 @@ void nm_settings_device_added (NMSettings *self, NMDevice *device);
 
 void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting);
 
-const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self);
+const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self,
+                                                             gboolean force_reload);
 
 void nm_settings_kf_db_write (NMSettings *settings);
 
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c
index 577709d8..0e9ad5fa 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c
@@ -171,6 +171,7 @@ nms_keyfile_reader_from_file (const char *full_filename,
 	NM_SET_OUT (out_is_nm_generated, NM_TERNARY_DEFAULT);
 	NM_SET_OUT (out_is_volatile, NM_TERNARY_DEFAULT);
 	NM_SET_OUT (out_is_external, NM_TERNARY_DEFAULT);
+	NM_SET_OUT (out_shadowed_owned, NM_TERNARY_DEFAULT);
 
 	if (!nms_keyfile_utils_check_file_permissions (NMS_KEYFILE_FILETYPE_KEYFILE,
 	                                               full_filename,