summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2014-08-05 20:08:34 +0200
committerDan Williams <dcbw@redhat.com>2015-01-21 17:58:50 -0600
commitf3efdbcdf21762f1db23249b78cf4fa521c19ef7 (patch)
tree46bb18c0c067d4ffa6b1de799d751009147cbca4
parent6bb0cffba32ec925743c4d491b75474d4e855198 (diff)
downloadNetworkManager-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.c71
-rw-r--r--src/devices/nm-device.h11
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);