manager: remove a connection from device if we're activating it on another device

The connection now might be being activated on another device. Defer the
removal until we're sure the activation request will proceed and only add the
active connection afterwards.

https://bugzilla.gnome.org/show_bug.cgi?id=730492
This commit is contained in:
Lubomir Rintel
2015-02-03 16:15:37 +01:00
parent 6fc3736c7a
commit 4cb97cf66f
3 changed files with 48 additions and 30 deletions

View File

@@ -5908,6 +5908,26 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
return TRUE;
}
void
nm_device_steal_connection (NMDevice *self, NMConnection *connection)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
_LOGW (LOGD_DEVICE, "disconnecting connection '%s' for new activation request.",
nm_connection_get_id (connection));
if ( priv->queued_act_request
&& connection == nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request)))
_clear_queued_act_request (priv);
if ( priv->act_request
&& connection == nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request))
&& priv->state < NM_DEVICE_STATE_DEACTIVATING)
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
void
nm_device_queue_activation (NMDevice *self, NMActRequest *req)
{
@@ -5929,8 +5949,8 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
_LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
if (priv->act_request) {
/* Deactivate existing activation request first */
if (priv->act_request) {
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
@@ -7390,10 +7410,9 @@ _cleanup_ip_pre (NMDevice *self, gboolean deconfigure)
}
static void
_cleanup_generic_pre (NMDevice *self, gboolean deconfigure)
_cancel_activation (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnection *connection;
/* Clean up when device was deactivated during call to firewall */
if (priv->fw_call) {
@@ -7401,6 +7420,20 @@ _cleanup_generic_pre (NMDevice *self, gboolean deconfigure)
priv->fw_call = NULL;
}
ip_check_gw_ping_cleanup (self);
/* Break the activation chain */
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
}
static void
_cleanup_generic_pre (NMDevice *self, gboolean deconfigure)
{
NMConnection *connection;
_cancel_activation (self);
connection = nm_device_get_connection (self);
if ( deconfigure
&& connection
@@ -7410,12 +7443,6 @@ _cleanup_generic_pre (NMDevice *self, gboolean deconfigure)
NULL);
}
ip_check_gw_ping_cleanup (self);
/* Break the activation chain */
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
/* Clear any queued transitions */
nm_device_queued_state_clear (self);
@@ -7951,6 +7978,8 @@ _set_state_full (NMDevice *self,
}
break;
case NM_DEVICE_STATE_DEACTIVATING:
_cancel_activation (self);
if (quitting) {
nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN,
nm_act_request_get_connection (req),

View File

@@ -387,6 +387,8 @@ void nm_device_queue_state (NMDevice *self,
gboolean nm_device_get_firmware_missing (NMDevice *self);
void nm_device_steal_connection (NMDevice *device, NMConnection *connection);
void nm_device_queue_activation (NMDevice *device, NMActRequest *req);
gboolean nm_device_supports_vlans (NMDevice *device);

View File

@@ -2684,7 +2684,7 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er
static gboolean
_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error)
{
NMDevice *device, *master_device = NULL;
NMDevice *device, *existing, *master_device = NULL;
NMConnection *connection;
NMConnection *master_connection = NULL;
NMActiveConnection *master_ac = NULL;
@@ -2836,6 +2836,11 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
nm_active_connection_get_path (master_ac));
}
/* Disconnect the connection if connected or queued on another device */
existing = nm_manager_get_connection_device (self, connection);
if (existing)
nm_device_steal_connection (existing, connection);
/* Export the new ActiveConnection to clients and start it on the device */
nm_active_connection_export (active);
g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
@@ -2873,6 +2878,7 @@ _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError
* is exported, make sure the manager's activating-connection property
* is up-to-date.
*/
active_connection_add (self, active);
policy_activating_device_changed (G_OBJECT (priv->policy), NULL, self);
}
@@ -2942,18 +2948,6 @@ _new_active_connection (NMManager *self,
return NULL;
}
if (existing_ac) {
NMDevice *existing_device = nm_active_connection_get_device (existing_ac);
if (existing_device != device) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
"Connection '%s' is already active on %s",
nm_connection_get_id (connection),
nm_device_get_iface (existing_device));
return NULL;
}
}
/* Normalize the specific object */
if (specific_object && g_strcmp0 (specific_object, "/") == 0)
specific_object = NULL;
@@ -2985,7 +2979,6 @@ _internal_activation_failed (NMManager *self,
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING);
nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
}
active_connection_remove (self, active);
}
static void
@@ -3063,10 +3056,8 @@ nm_manager_activate_connection (NMManager *self,
device,
subject,
error);
if (active) {
if (active)
nm_active_connection_authorize (active, _internal_activation_auth_done, self, NULL);
active_connection_add (self, active);
}
return active;
}
@@ -3313,7 +3304,6 @@ impl_manager_activate_connection (NMManager *self,
goto error;
nm_active_connection_authorize (active, _activation_auth_done, self, context);
active_connection_add (self, active);
g_clear_object (&subject);
return;
@@ -3391,8 +3381,6 @@ _add_and_activate_auth_done (NMActiveConnection *active,
activation_add_done,
info);
} else {
active_connection_remove (self, active);
g_assert (error_desc);
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -3499,7 +3487,6 @@ impl_manager_add_and_activate_connection (NMManager *self,
goto error;
nm_active_connection_authorize (active, _add_and_activate_auth_done, self, context);
active_connection_add (self, active);
g_object_unref (connection);
g_object_unref (subject);
return;