From 0b03614b682ff0e44caf3803abe29f6e8927cbd6 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 21 Aug 2025 15:43:35 +0200 Subject: [PATCH] device: ensure that sw devices are unrealized after connection deletion When a software device becomes deactivated, we check whether it can be unrealized (= deleted in kernel), by calling function delete_on_deactivate_check_and_schedule(). The function returns without doing anything if there is a new activation enqueued on the device (priv->queued_act_request), because in that case the device will be reused for the next activation. This commit fixes a problem seen in NMCI test @ovs_delete_connecting_interface: sometimes the device is not unrealized after deleting the connection. That happens because if the queued activation fails, we never try again to unrealize the device. Fix that by calling delete_on_deactivate_check_and_schedule() when there is a failure starting the queued activation. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2258 --- src/core/devices/nm-device.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 7cacd5ff3f..63a29c2df6 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -14751,13 +14751,15 @@ impl_device_delete(NMDBusObject *obj, NULL); } -static void +static gboolean _device_activate(NMDevice *self, NMActRequest *req) { NMConnection *connection; - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_IS_ACT_REQUEST(req)); + /* Returns TRUE on success, FALSE if the activation request could not be started */ + + g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); + g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE); nm_assert(nm_device_is_real(self)); /* Ensure the activation request is still valid; the controller may have @@ -14765,7 +14767,7 @@ _device_activate(NMDevice *self, NMActRequest *req) */ if (nm_active_connection_get_state(NM_ACTIVE_CONNECTION(req)) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) - return; + return FALSE; if (!nm_device_get_managed(self, FALSE)) { /* It's unclear why the device would be unmanaged at this point. @@ -14776,7 +14778,7 @@ _device_activate(NMDevice *self, NMActRequest *req) nm_active_connection_set_state_fail((NMActiveConnection *) req, NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, NULL); - return; + return FALSE; } connection = nm_act_request_get_applied_connection(req); @@ -14792,6 +14794,8 @@ _device_activate(NMDevice *self, NMActRequest *req) act_request_set(self, req); nm_device_activate_schedule_stage1_device_prepare(self, FALSE); + + return TRUE; } static void @@ -14811,7 +14815,9 @@ _carrier_wait_check_queued_act_request(NMDevice *self) _LOGD(LOGD_DEVICE, "Activate queued activation request as we now have carrier"); queued_req = g_steal_pointer(&priv->queued_act_request); - _device_activate(self, queued_req); + if (!_device_activate(self, queued_req)) { + delete_on_deactivate_check_and_schedule(self); + } } } @@ -17599,7 +17605,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gs_unref_object NMActRequest *queued_req = NULL; queued_req = g_steal_pointer(&priv->queued_act_request); - _device_activate(self, queued_req); + if (!_device_activate(self, queued_req)) + delete_on_deactivate_check_and_schedule(self); } break; case NM_DEVICE_STATE_ACTIVATED: