diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2023-04-03 10:26:03 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2023-04-04 08:21:22 +0200 |
commit | 07dc237e5ccb4bbe51a5c1e3fd232446a3b98ade (patch) | |
tree | 695747d10ce206c5de14e2a58b411b4c44ca6f46 | |
parent | 82d0fa2a87c5621c9b0412cf1914bb02130e4de5 (diff) |
device: wait port detach before leaving the DEACTIVATING state
The device shouldn't change state from DEACTIVATING to DISCONNECTED
until its detached from its controller; otherwise, the port detach
that is in progress can conflict with the following activation.
-rw-r--r-- | src/core/devices/nm-device.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 8f697d5731..304bacaf3e 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -749,6 +749,9 @@ typedef struct _NMDevicePrivate { guint check_delete_unrealized_id; guint32 interface_flags; + guint32 port_detach_count; + NMDeviceStateReason port_detach_reason; + struct { SriovOp *pending; /* SR-IOV operation currently running */ SriovOp *next; /* next SR-IOV operation scheduled */ @@ -869,6 +872,7 @@ static void sriov_op_cb(GError *error, gpointer user_data); static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self); static gboolean device_link_changed(gpointer user_data); static gboolean _get_maybe_ipv6_disabled(NMDevice *self); +static void deactivate_ready(NMDevice *self, NMDeviceStateReason reason); /*****************************************************************************/ @@ -6346,6 +6350,21 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co attach_port_done(self, slave, success); } +static void +detach_port_cb(NMDevice *self, GError *error, gpointer user_data) +{ + nm_auto_unref_object NMDevice *slave = user_data; + NMDevicePrivate *slave_priv = NM_DEVICE_GET_PRIVATE(slave); + + nm_assert(slave_priv->port_detach_count > 0); + + if (--slave_priv->port_detach_count == 0) { + if (slave_priv->state == NM_DEVICE_STATE_DEACTIVATING) { + deactivate_ready(slave, slave_priv->port_detach_reason); + } + } +} + /** * nm_device_master_release_slave: * @self: the master device @@ -6409,9 +6428,12 @@ nm_device_master_release_slave(NMDevice *self, slave, release_type >= RELEASE_SLAVE_TYPE_CONFIG, NULL, - NULL, - NULL); - nm_assert(NM_IN_SET(ret, TRUE, FALSE)); + detach_port_cb, + g_object_ref(slave)); + if (ret == NM_TERNARY_DEFAULT) { + slave_priv->port_detach_count++; + slave_priv->port_detach_reason = reason; + } } /* raise notifications about the release, including clearing is_enslaved. */ @@ -15818,6 +15840,9 @@ deactivate_ready(NMDevice *self, NMDeviceStateReason reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + if (priv->port_detach_count > 0) + return; + if (priv->dispatcher.call_id) return; |