From f245b49ae731c75cfa68872a4218aeaeb65ff0aa Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 23 Jun 2015 20:52:04 +0200 Subject: [PATCH] manager: reuse an active connection, if the same activation is pending When a master & slaves get activated at the same time, they all submit separate active connections which race for the device after activation. (cherry picked from commit 7a066a35ad8c48aac669dce286be499663eb9cd8) --- src/nm-manager.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index f69b5cd7d8..a438345e90 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -157,6 +157,7 @@ typedef struct { char *state_file; GSList *active_connections; + GSList *authorizing_connections; guint ac_cleanup_id; NMActiveConnection *primary_connection; NMActiveConnection *activating_connection; @@ -2873,8 +2874,11 @@ _internal_activation_auth_done (NMActiveConnection *active, gpointer user_data2) { NMManager *self = user_data1; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; + priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active); + if (success) { if (_internal_activate_generic (self, active, &error)) { g_object_unref (active); @@ -2914,8 +2918,10 @@ nm_manager_activate_connection (NMManager *self, NMAuthSubject *subject, GError **error) { + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnection *active; char *error_desc = NULL; + GSList *iter; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); @@ -2935,14 +2941,32 @@ nm_manager_activate_connection (NMManager *self, return NULL; } + /* Look for a active connection that's equivalent and is already pending authorization + * and eventual activation. This is used to de-duplicate concurrent activations which would + * otherwise race and cause the device to disconnect and reconnect repeatedly. + * In particular, this allows the master and multiple slaves to concurrently auto-activate + * while all the slaves would use the same active-connection. */ + for (iter = priv->authorizing_connections; iter; iter = g_slist_next (iter)) { + active = iter->data; + + if ( connection == nm_active_connection_get_connection (active) + && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0 + && nm_active_connection_get_device (active) == device + && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) + && nm_auth_subject_is_internal (subject)) + return active; + } + active = _new_active_connection (self, connection, specific_object, device, subject, error); - if (active) + if (active) { + priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); nm_active_connection_authorize (active, _internal_activation_auth_done, self, NULL); + } return active; }