diff options
author | Thomas Haller <thaller@redhat.com> | 2020-08-11 15:34:59 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-08-12 08:32:08 +0200 |
commit | e6418f03d3b2de0c8d9ed37c8594b699183eba7b (patch) | |
tree | b4f0e874351a61bd968cf974455fef7e44319b07 /src/nm-manager.c | |
parent | 698c4ae35efbfce105c399300c413350682b9aac (diff) | |
download | NetworkManager-th/settings-wait-device-timeout.tar.gz |
settings: rework wait-device-timeout handling and consider device compatibilityth/settings-wait-device-timeout
A profile can configure "connection.wait-device-timeout" to indicate
that startup complete is blocked until a suitable device around.
This is useful for NetworkManager-wait-online and initrd mode.
Previously, we looked at NMPlatform whether a link with matching
interface-name was present. That is wrong because it cannot handle
profiles that rely on "ethernet.mac-address" setting or other "match"
settings. Also, the mere presence of the link does not yet mean
that the NMDevice was created and ready. In fact, there is a race here:
NMPlatform indicates that the device is ready (unblocking NMSettings),
but there is no corresponding NMDevice yet which keeps NetworkManager
busy to block startup complete.
Rework this. Now, only check whether there is a compatible device for
the profile.
Since we wait for compatible devices, it works now not only for the
interface name. Note that we do some optimizations so that we don't have
to re-evaluate all profiles (w.r.t. all devices) whenever something on the
device changes: we only care about this when all devices finally become
ready.
Also, we no longer start the timeout for "connection.wait-device-timeout"
when the profile appears. Instead, there is one system-wide start time
(NMSettingsPrivate.startup_complete_start_timestamp_msec). That simplifies
code and makes sense: we start waiting when NetworkManager is starting, not
when the profile gets added. Also, we wait for all profiles to become
ready together.
Diffstat (limited to 'src/nm-manager.c')
-rw-r--r-- | src/nm-manager.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 487446d541..8e8723349a 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1561,13 +1561,6 @@ check_if_startup_complete (NMManager *self) if (!priv->devices_inited) return; - reason = nm_settings_get_startup_complete_blocked_reason (priv->settings); - if (reason) { - _LOGD (LOGD_CORE, "startup complete is waiting for connection (%s)", - reason); - return; - } - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { reason = nm_device_has_pending_action_reason (device); if (reason) { @@ -1578,6 +1571,31 @@ check_if_startup_complete (NMManager *self) } } + /* All NMDevice must be ready. But also NMSettings tracks profiles that wait for + * ready devices via "connection.wait-device-timeout". + * + * Note that we only re-check nm_settings_get_startup_complete_blocked_reason() when + * all of the devices become ready (again). + * + * For example, assume we have device "eth1" and "profile-eth2" which waits for "eth2". + * If "eth1" is ready (no pending action), we only need to re-evaluate "profile-eth2" + * if we have another device ("eth2"), that becomes non-ready (had pending actions) + * and again become ready. We don't need to check "profile-eth2" until "eth2" becomes + * non-ready. + * That is why nm_settings_get_startup_complete_blocked_reason() only has any significance + * if all devices are ready too. It allows us to cut down the number of checks whether + * NMSettings is ready. That's because we don't need to re-evaluate on minor changes of + * a device, only when all devices become managed and ready. */ + + g_signal_handlers_block_by_func (priv->settings, settings_startup_complete_changed, self); + reason = nm_settings_get_startup_complete_blocked_reason (priv->settings, TRUE); + g_signal_handlers_unblock_by_func (priv->settings, settings_startup_complete_changed, self); + if (reason) { + _LOGD (LOGD_CORE, "startup complete is waiting for connection (%s)", + reason); + return; + } + _LOGI (LOGD_CORE, "startup complete"); priv->startup = FALSE; |