summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2023-04-03 10:26:03 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2023-04-04 08:21:22 +0200
commit07dc237e5ccb4bbe51a5c1e3fd232446a3b98ade (patch)
tree695747d10ce206c5de14e2a58b411b4c44ca6f46
parent82d0fa2a87c5621c9b0412cf1914bb02130e4de5 (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.c31
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;