From 79c81fc06ab891f9cc7ffe20bafc47210586e7aa Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Fri, 12 Jul 2024 16:58:20 +0800 Subject: [PATCH] activation: Allow changing controller of exposed active connection When activating a port with its controller deactivating by new activation, NM will register `state-change` signal waiting controller to have new active connections. Once controller got new active connection, the port will invoke `nm_active_connection_set_controller()` which lead to assert error on g_return_if_fail(!nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))) because this active connection is already exposed as DBUS object. To fix the problem, we remove the restriction on controller been write-only and notify DBUS object changes for controller property. Signed-off-by: Gris Ge (cherry picked from commit 83a259597000a88217f3ccbdfe71c8114242e7a6) (cherry picked from commit 3f3d1a4f5493581c052b7eb486def907044624ec) --- src/core/nm-active-connection.c | 33 +++++++++++++++++++++++---------- src/core/nm-manager.c | 18 ++++++++++++------ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/core/nm-active-connection.c b/src/core/nm-active-connection.c index df7d1bc075..ce135497c9 100644 --- a/src/core/nm-active-connection.c +++ b/src/core/nm-active-connection.c @@ -870,20 +870,28 @@ nm_active_connection_set_master(NMActiveConnection *self, NMActiveConnection *ma priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - /* Master is write-once, and must be set before exporting the object */ - g_return_if_fail(priv->master == NULL); - g_return_if_fail(!nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))); + if (priv->master != NULL) { + _LOGD("releasing previous controller " NM_HASH_OBFUSCATE_PTR_FMT " %s, state %s", + NM_HASH_OBFUSCATE_PTR(priv->master), + nm_active_connection_get_settings_connection_id(priv->master), + state_to_string_a(nm_active_connection_get_state(priv->master))); + g_clear_object(&priv->master); + } + if (priv->device) { /* Note, the master ActiveConnection may not yet have a device */ g_return_if_fail(priv->device != nm_active_connection_get_device(master)); } - _LOGD("set master %p, %s, state %s", - master, + _LOGD("set master " NM_HASH_OBFUSCATE_PTR_FMT ", %s, state %s", + NM_HASH_OBFUSCATE_PTR(master), nm_active_connection_get_settings_connection_id(master), state_to_string_a(nm_active_connection_get_state(master))); priv->master = g_object_ref(master); + + _notify(self, PROP_MASTER); + g_signal_connect(priv->master, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK(master_state_cb), @@ -902,15 +910,20 @@ nm_active_connection_set_controller_dev(NMActiveConnection *self, NMDevice *cont priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - /* Controller device is write-once, and must be set before exporting the object */ - g_return_if_fail(priv->controller_dev == NULL); - g_return_if_fail(!nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))); + if (priv->controller_dev != NULL) { + _LOGD("releasing previous controller device " NM_HASH_OBFUSCATE_PTR_FMT " %s(%s), state %s", + NM_HASH_OBFUSCATE_PTR(priv->controller_dev), + nm_device_get_iface(priv->controller_dev), + nm_device_get_type_desc(priv->controller_dev), + nm_device_state_to_string(nm_device_get_state(priv->controller_dev))); + g_clear_object(&priv->controller_dev); + } if (priv->device) { g_return_if_fail(priv->device != controller_dev); } - _LOGD("set controller device %p, %s(%s), state %s", - controller_dev, + _LOGD("set controller device " NM_HASH_OBFUSCATE_PTR_FMT ", %s(%s), state %s", + NM_HASH_OBFUSCATE_PTR(controller_dev), nm_device_get_iface(controller_dev), nm_device_get_type_desc(controller_dev), nm_device_state_to_string(nm_device_get_state(controller_dev))); diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 3f20cab728..1913844fbf 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -5953,15 +5953,21 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError ** && (nm_device_get_state_reason(master_device) == NM_DEVICE_STATE_REASON_NEW_ACTIVATION)) { nm_active_connection_set_controller_dev(active, master_device); + _LOGD(LOGD_CORE, + "Activation of '%s'(%s) depends on controller device %p %s", + nm_settings_connection_get_id(sett_conn), + nm_settings_connection_get_connection_type(sett_conn), + master_device, + nm_dbus_object_get_path(NM_DBUS_OBJECT(master_device)) ?: ""); } else { nm_active_connection_set_master(active, master_ac); + _LOGD(LOGD_CORE, + "Activation of '%s'(%s) depends on active connection %p %s", + nm_settings_connection_get_id(sett_conn), + nm_settings_connection_get_connection_type(sett_conn), + master_ac, + nm_dbus_object_get_path(NM_DBUS_OBJECT(master_ac)) ?: ""); } - - _LOGD(LOGD_CORE, - "Activation of '%s' depends on active connection %p %s", - nm_settings_connection_get_id(sett_conn), - master_ac, - nm_dbus_object_get_path(NM_DBUS_OBJECT(master_ac)) ?: ""); } /* Check slaves for master connection and possibly activate them */