checkpoint: fix port reactivation when controller is deactivating
Problem: Given a OVS port with `autoconnect-ports` set to default or false, when reactivation required for checkpoint rollback, previous activated OVS interface will be in deactivate state after checkpoint rollback. The root cause: The `activate_stage1_device_prepare()` will mark the device as failed when controller is deactivating or deactivated. In `activate_stage1_device_prepare()`, the controller device is retrieved from NMActiveConnection, it will be NULL when NMActiveConnection is in deactivated state. This will cause device been set to `NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED` which prevent all follow up `autoconnect` actions. Fix: When noticing controller is deactivating or deactivated with reason `NM_DEVICE_STATE_REASON_NEW_ACTIVATION`, use new function `nm_active_connection_set_controller_dev()` to wait on controller device state between NM_DEVICE_STATE_PREPARE and NM_DEVICE_STATE_ACTIVATED. After that, use existing `nm_active_connection_set_controller()` to use new NMActiveConnection of controller to move on. Resolves: https://issues.redhat.com/browse/RHEL-31972 Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
@@ -17205,6 +17205,14 @@ nm_device_get_state(NMDevice *self)
|
|||||||
return NM_DEVICE_GET_PRIVATE(self)->state;
|
return NM_DEVICE_GET_PRIVATE(self)->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NMDeviceStateReason
|
||||||
|
nm_device_get_state_reason(NMDevice *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_STATE_REASON_NONE);
|
||||||
|
|
||||||
|
return NM_DEVICE_GET_PRIVATE(self)->state_reason;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -561,7 +561,8 @@ int nm_device_spec_match_list_full(NMDevice *self, const GSList *specs, int
|
|||||||
gboolean nm_device_is_activating(NMDevice *dev);
|
gboolean nm_device_is_activating(NMDevice *dev);
|
||||||
gboolean nm_device_autoconnect_allowed(NMDevice *self);
|
gboolean nm_device_autoconnect_allowed(NMDevice *self);
|
||||||
|
|
||||||
NMDeviceState nm_device_get_state(NMDevice *device);
|
NMDeviceState nm_device_get_state(NMDevice *device);
|
||||||
|
NMDeviceStateReason nm_device_get_state_reason(NMDevice *device);
|
||||||
|
|
||||||
gboolean nm_device_get_enabled(NMDevice *device);
|
gboolean nm_device_get_enabled(NMDevice *device);
|
||||||
|
|
||||||
|
@@ -50,6 +50,7 @@ typedef struct _NMActiveConnectionPrivate {
|
|||||||
|
|
||||||
NMAuthSubject *subject;
|
NMAuthSubject *subject;
|
||||||
NMActiveConnection *controller;
|
NMActiveConnection *controller;
|
||||||
|
NMDevice *controller_dev;
|
||||||
|
|
||||||
NMActiveConnection *parent;
|
NMActiveConnection *parent;
|
||||||
|
|
||||||
@@ -826,6 +827,31 @@ master_state_cb(NMActiveConnection *master, GParamSpec *pspec, gpointer user_dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
controller_dev_state_cb(NMDevice *controller_dev,
|
||||||
|
NMDeviceState new_state,
|
||||||
|
NMDeviceState old_state,
|
||||||
|
NMDeviceStateReason reason,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION(user_data);
|
||||||
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self);
|
||||||
|
NMActRequest *controller_act_request;
|
||||||
|
NMActiveConnection *controller_ac;
|
||||||
|
|
||||||
|
if (new_state >= NM_DEVICE_STATE_PREPARE && new_state <= NM_DEVICE_STATE_ACTIVATED) {
|
||||||
|
controller_act_request = nm_device_get_act_request(controller_dev);
|
||||||
|
if (controller_act_request) {
|
||||||
|
controller_ac = NM_ACTIVE_CONNECTION(controller_act_request);
|
||||||
|
g_signal_handlers_disconnect_by_func(controller_dev,
|
||||||
|
G_CALLBACK(controller_dev_state_cb),
|
||||||
|
self);
|
||||||
|
g_clear_object(&priv->controller_dev);
|
||||||
|
nm_active_connection_set_controller(self, controller_ac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_active_connection_set_controller:
|
* nm_active_connection_set_controller:
|
||||||
* @self: the #NMActiveConnection
|
* @self: the #NMActiveConnection
|
||||||
@@ -867,6 +893,36 @@ nm_active_connection_set_controller(NMActiveConnection *self, NMActiveConnection
|
|||||||
check_controller_ready(self);
|
check_controller_ready(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_active_connection_set_controller_dev(NMActiveConnection *self, NMDevice *controller_dev)
|
||||||
|
{
|
||||||
|
NMActiveConnectionPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self));
|
||||||
|
g_return_if_fail(NM_IS_DEVICE(controller_dev));
|
||||||
|
|
||||||
|
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->device) {
|
||||||
|
g_return_if_fail(priv->device != controller_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGD("set controller device %p, %s(%s), state %s",
|
||||||
|
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)));
|
||||||
|
|
||||||
|
priv->controller_dev = g_object_ref(controller_dev);
|
||||||
|
g_signal_connect(priv->controller_dev,
|
||||||
|
NM_DEVICE_STATE_CHANGED,
|
||||||
|
G_CALLBACK(controller_dev_state_cb),
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
NMActivationType
|
NMActivationType
|
||||||
nm_active_connection_get_activation_type(NMActiveConnection *self)
|
nm_active_connection_get_activation_type(NMActiveConnection *self)
|
||||||
{
|
{
|
||||||
@@ -1533,7 +1589,13 @@ dispose(GObject *object)
|
|||||||
if (priv->controller) {
|
if (priv->controller) {
|
||||||
g_signal_handlers_disconnect_by_func(priv->controller, G_CALLBACK(master_state_cb), self);
|
g_signal_handlers_disconnect_by_func(priv->controller, G_CALLBACK(master_state_cb), self);
|
||||||
}
|
}
|
||||||
|
if (priv->controller_dev) {
|
||||||
|
g_signal_handlers_disconnect_by_func(priv->controller_dev,
|
||||||
|
G_CALLBACK(controller_dev_state_cb),
|
||||||
|
self);
|
||||||
|
}
|
||||||
g_clear_object(&priv->controller);
|
g_clear_object(&priv->controller);
|
||||||
|
g_clear_object(&priv->controller_dev);
|
||||||
|
|
||||||
if (priv->parent)
|
if (priv->parent)
|
||||||
unwatch_parent(self, TRUE);
|
unwatch_parent(self, TRUE);
|
||||||
|
@@ -175,6 +175,7 @@ NMActiveConnection *nm_active_connection_get_controller(NMActiveConnection *self
|
|||||||
gboolean nm_active_connection_get_controller_ready(NMActiveConnection *self);
|
gboolean nm_active_connection_get_controller_ready(NMActiveConnection *self);
|
||||||
|
|
||||||
void nm_active_connection_set_controller(NMActiveConnection *self, NMActiveConnection *controller);
|
void nm_active_connection_set_controller(NMActiveConnection *self, NMActiveConnection *controller);
|
||||||
|
void nm_active_connection_set_controller_dev(NMActiveConnection *self, NMDevice *controller_dev);
|
||||||
|
|
||||||
void nm_active_connection_set_parent(NMActiveConnection *self, NMActiveConnection *parent);
|
void nm_active_connection_set_parent(NMActiveConnection *self, NMActiveConnection *parent);
|
||||||
|
|
||||||
|
@@ -5943,7 +5943,20 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_active_connection_set_controller(active, master_ac);
|
/* If controller NMActiveConnection is deactivating, we should wait on
|
||||||
|
* controller's NMDevice to have new NMActiveConnection after
|
||||||
|
* controller device state change to between NM_DEVICE_STATE_PREPARE and
|
||||||
|
* NM_DEVICE_STATE_ACTIVATED.
|
||||||
|
*/
|
||||||
|
if ((nm_active_connection_get_state(master_ac) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
|
||||||
|
&& master_device
|
||||||
|
&& (nm_device_get_state_reason(master_device)
|
||||||
|
== NM_DEVICE_STATE_REASON_NEW_ACTIVATION)) {
|
||||||
|
nm_active_connection_set_controller_dev(active, master_device);
|
||||||
|
} else {
|
||||||
|
nm_active_connection_set_controller(active, master_ac);
|
||||||
|
}
|
||||||
|
|
||||||
_LOGD(LOGD_CORE,
|
_LOGD(LOGD_CORE,
|
||||||
"Activation of '%s' depends on active connection %p %s",
|
"Activation of '%s' depends on active connection %p %s",
|
||||||
nm_settings_connection_get_id(sett_conn),
|
nm_settings_connection_get_id(sett_conn),
|
||||||
|
Reference in New Issue
Block a user