From 95d2da5da90dad6dce1161486976e827f79b1f34 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 (cherry picked from commit 0b03614b682ff0e44caf3803abe29f6e8927cbd6) (cherry picked from commit 1f23bb18adc34fb1849b9233ac3450923c99253a) --- 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 dee160ed90..d0c2f24fb7 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -14641,13 +14641,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 @@ -14655,7 +14657,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. @@ -14666,7 +14668,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); @@ -14682,6 +14684,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 @@ -14701,7 +14705,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); + } } } @@ -17464,7 +17470,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: