diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2014-08-05 20:08:34 +0200 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2015-01-21 17:58:50 -0600 |
commit | f3efdbcdf21762f1db23249b78cf4fa521c19ef7 (patch) | |
tree | 46bb18c0c067d4ffa6b1de799d751009147cbca4 | |
parent | 6bb0cffba32ec925743c4d491b75474d4e855198 (diff) | |
download | NetworkManager-f3efdbcdf21762f1db23249b78cf4fa521c19ef7.tar.gz |
device: new deactivate_async() method to be run during DEACTIVATING phase
This method isn't run if NM is quitting; so the deactivate() method still needs
to be implemented to handle sync disconnection requests.
-rw-r--r-- | src/devices/nm-device.c | 71 | ||||
-rw-r--r-- | src/devices/nm-device.h | 11 |
2 files changed, 80 insertions, 2 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 4c514b4a15..f11266556d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -205,6 +205,8 @@ typedef struct { gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ + GCancellable *deactivating_cancellable; + guint32 ip4_address; NMActRequest * queued_act_request; @@ -7389,6 +7391,69 @@ ip6_managed_setup (NMDevice *self) } static void +deactivate_async_ready (NMDevice *self, + GAsyncResult *res, + gpointer user_data) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceStateReason reason = GPOINTER_TO_UINT (user_data); + GError *error = NULL; + + NM_DEVICE_GET_CLASS (self)->deactivate_async_finish (self, res, &error); + + /* If operation cancelled, just return */ + if ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) + || (priv->deactivating_cancellable && g_cancellable_is_cancelled (priv->deactivating_cancellable))) { + nm_log_warn (LOGD_DEVICE, "Deactivation (%s) cancelled", + nm_device_get_iface (self)); + } + /* In every other case, transition to the DISCONNECTED state */ + else { + if (error) + nm_log_warn (LOGD_DEVICE, "Deactivation (%s) failed: %s", + nm_device_get_iface (self), + error->message); + nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason); + } + + g_clear_object (&priv->deactivating_cancellable); + g_clear_error (&error); +} + +static void +deactivate_dispatcher_complete (guint call_id, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceStateReason reason; + + g_return_if_fail (call_id == priv->dispatcher.call_id); + g_return_if_fail (priv->dispatcher.post_state == NM_DEVICE_STATE_DISCONNECTED); + + reason = priv->dispatcher.post_state_reason; + + priv->dispatcher.call_id = 0; + priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; + priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; + + if (priv->deactivating_cancellable) { + g_warn_if_reached (); + g_cancellable_cancel (priv->deactivating_cancellable); + g_clear_object (&priv->deactivating_cancellable); + } + + if ( NM_DEVICE_GET_CLASS (self)->deactivate_async + && NM_DEVICE_GET_CLASS (self)->deactivate_async_finish) { + priv->deactivating_cancellable = g_cancellable_new (); + NM_DEVICE_GET_CLASS (self)->deactivate_async (self, + priv->deactivating_cancellable, + (GAsyncReadyCallback) deactivate_async_ready, + GUINT_TO_POINTER (reason)); + } else + nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason); +} + +static void _set_state_full (NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, @@ -7432,6 +7497,8 @@ _set_state_full (NMDevice *self, nm_device_queued_state_clear (self); dispatcher_cleanup (self); + if (priv->deactivating_cancellable) + g_cancellable_cancel (priv->deactivating_cancellable); /* Cache the activation request for the dispatcher */ req = priv->act_request ? g_object_ref (priv->act_request) : NULL; @@ -7556,11 +7623,11 @@ _set_state_full (NMDevice *self, if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, nm_act_request_get_connection (req), self, - dispatcher_complete_proceed_state, + deactivate_dispatcher_complete, self, &priv->dispatcher.call_id)) { /* Just proceed on errors */ - dispatcher_complete_proceed_state (0, self); + deactivate_dispatcher_complete (0, self); } } break; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index b3855c7446..e6f07f2ef3 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -23,6 +23,7 @@ #define __NETWORKMANAGER_DEVICE_H__ #include <glib-object.h> +#include <gio/gio.h> #include <dbus/dbus-glib.h> #include <netinet/in.h> @@ -174,6 +175,16 @@ typedef struct { void (* ip4_config_pre_commit) (NMDevice *self, NMIP4Config *config); void (* ip6_config_pre_commit) (NMDevice *self, NMIP6Config *config); + /* Async deactivating (in the DEACTIVATING phase) */ + void (* deactivate_async) (NMDevice *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* deactivate_async_finish) (NMDevice *self, + GAsyncResult *res, + GError **error); + + /* Sync deactivating (in the DISCONNECTED phase) */ void (* deactivate) (NMDevice *self); gboolean (* spec_match_list) (NMDevice *self, const GSList *specs); |