Blob Blame History Raw
From 2e6d8e23b7ee032217d94c7d2dad2a57ace42ba1 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Thu, 1 Oct 2015 16:41:09 +0200
Subject: [PATCH 1/3] macros: add nm_clear_g_signal_handler() helper

(cherry picked from commit 720c53f9f14ee3d12cb0a2bf68da938949544275)
---
 include/nm-macros-internal.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/nm-macros-internal.h b/include/nm-macros-internal.h
index 170fb46..c4a60fa 100644
--- a/include/nm-macros-internal.h
+++ b/include/nm-macros-internal.h
@@ -24,6 +24,7 @@
 
 
 #include <glib.h>
+#include <glib-object.h>
 
 /********************************************************/
 
@@ -256,6 +257,19 @@ nm_clear_g_source (guint *id)
 	return FALSE;
 }
 
+static inline gboolean
+nm_clear_g_signal_handler (gpointer self, guint *id)
+{
+	g_return_val_if_fail (G_IS_OBJECT (self), FALSE);
+
+	if (id && *id) {
+		g_signal_handler_disconnect (self, *id);
+		*id = 0;
+		return TRUE;
+	}
+	return FALSE;
+}
+
 /*****************************************************************************/
 
 /* Determine whether @x is a power of two (@x being an integer type).
-- 
2.4.3


From 5167b6a409ee7b150be181aef7a88f8162118902 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Thu, 1 Oct 2015 16:43:06 +0200
Subject: [PATCH 2/3] device: use nm_clear_g_signal_handler() to clear
 master-ready signal handler

(cherry picked from commit 86b6b6ed32c5128a4879238e10a7a1e9cda18be5)
---
 src/devices/nm-device.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 36603a6..4c2ac97 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -2679,10 +2679,7 @@ master_ready_cb (NMActiveConnection *active,
 	_LOGD (LOGD_DEVICE, "master connection ready; master device %s",
 	       nm_device_get_iface (priv->master));
 
-	if (priv->master_ready_id) {
-		g_signal_handler_disconnect (active, priv->master_ready_id);
-		priv->master_ready_id = 0;
-	}
+	nm_clear_g_signal_handler (active, &priv->master_ready_id);
 
 	nm_device_activate_schedule_stage2_device_config (self);
 }
@@ -6031,10 +6028,7 @@ clear_act_request (NMDevice *self)
 
 	nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
 
-	if (priv->master_ready_id) {
-		g_signal_handler_disconnect (priv->act_request, priv->master_ready_id);
-		priv->master_ready_id = 0;
-	}
+	nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
 
 	g_clear_object (&priv->act_request);
 	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
-- 
2.4.3


From b3a02417af7f66e228b970f7306a9865e146ba06 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Thu, 1 Oct 2015 16:48:32 +0200
Subject: [PATCH 3/3] device: fix activating slave device when stage1 delays
 action

When activating for example a team device which is to be enslaved to a
bridge, nm_device_activate_stage1_device_prepare() will postpone
stage 2.

In that case, we didn't register the "master-ready" of the team
device and thus never progressed the slave from stage2.

Reproduce:

  # nmcli connection delete t-br0
  # nmcli connection delete t-team0
  nmcli connection add type bridge con-name t-br0   autoconnect no ifname i-br0 ip4 192.168.177.100/24 gw4 192.168.177.1
  nmcli connection add type team   con-name t-team0 autoconnect no ifname i-team0
  nmcli connection modify id t-team0 connection.master i-br0 connection.slave-type bridge
  nmcli connection up t-team0

(cherry picked from commit 5f8aa51e6358a200feb83378877a4e9cd12cb222)
---
 src/devices/nm-device.c | 63 +++++++++++++++++++++++++++++++------------------
 1 file changed, 40 insertions(+), 23 deletions(-)

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 4c2ac97..148bef4 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -343,6 +343,7 @@ typedef struct {
 	/* master interface for bridge/bond/team slave */
 	NMDevice *      master;
 	gboolean        enslaved;
+	gboolean        master_ready_handled;
 	guint           master_ready_id;
 
 	/* slave management */
@@ -2658,19 +2659,22 @@ get_ip_config_may_fail (NMDevice *self, int family)
 }
 
 static void
-master_ready_cb (NMActiveConnection *active,
-                 GParamSpec *pspec,
-                 NMDevice *self)
+master_ready (NMDevice *self,
+              NMActiveConnection *active)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMActiveConnection *master;
 
-	g_assert (priv->state == NM_DEVICE_STATE_PREPARE);
+	g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE);
+	g_return_if_fail (!priv->master_ready_handled);
 
 	/* Notify a master device that it has a new slave */
-	g_assert (nm_active_connection_get_master_ready (active));
+	g_return_if_fail (nm_active_connection_get_master_ready (active));
 	master = nm_active_connection_get_master (active);
 
+	priv->master_ready_handled = TRUE;
+	nm_clear_g_signal_handler (active, &priv->master_ready_id);
+
 	priv->master = g_object_ref (nm_active_connection_get_device (master));
 	nm_device_master_add_slave (priv->master,
 	                            self,
@@ -2679,8 +2683,14 @@ master_ready_cb (NMActiveConnection *active,
 	_LOGD (LOGD_DEVICE, "master connection ready; master device %s",
 	       nm_device_get_iface (priv->master));
 
-	nm_clear_g_signal_handler (active, &priv->master_ready_id);
+}
 
+static void
+master_ready_cb (NMActiveConnection *active,
+                 GParamSpec *pspec,
+                 NMDevice *self)
+{
+	master_ready (self, active);
 	nm_device_activate_schedule_stage2_device_config (self);
 }
 
@@ -2728,23 +2738,7 @@ nm_device_activate_stage1_device_prepare (gpointer user_data)
 		g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
 	}
 
-	if (nm_active_connection_get_master (active)) {
-		/* If the master connection is ready for slaves, attach ourselves */
-		if (nm_active_connection_get_master_ready (active))
-			master_ready_cb (active, NULL, self);
-		else {
-			_LOGD (LOGD_DEVICE, "waiting for master connection to become ready");
-
-			/* Attach a signal handler and wait for the master connection to begin activating */
-			g_assert (priv->master_ready_id == 0);
-			priv->master_ready_id = g_signal_connect (active,
-			                                          "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
-			                                          (GCallback) master_ready_cb,
-			                                          self);
-			/* Postpone */
-		}
-	} else
-		nm_device_activate_schedule_stage2_device_config (self);
+	nm_device_activate_schedule_stage2_device_config (self);
 
 out:
 	_LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) complete.");
@@ -2798,6 +2792,28 @@ nm_device_activate_stage2_device_config (gpointer user_data)
 	NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
 	GSList *iter;
 
+	if (!priv->master_ready_handled) {
+		if (!nm_active_connection_get_master (active))
+			priv->master_ready_handled = TRUE;
+		else {
+			/* If the master connection is ready for slaves, attach ourselves */
+			if (nm_active_connection_get_master_ready (active))
+				master_ready (self, active);
+			else {
+				_LOGD (LOGD_DEVICE, "waiting for master connection to become ready");
+
+				if (priv->master_ready_id == 0) {
+					priv->master_ready_id = g_signal_connect (active,
+					                                          "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
+					                                          (GCallback) master_ready_cb,
+					                                          self);
+				}
+				/* Postpone */
+				return FALSE;
+			}
+		}
+	}
+
 	/* Clear the activation source ID now that this stage has run */
 	activation_source_clear (self, FALSE, 0);
 
@@ -6028,6 +6044,7 @@ clear_act_request (NMDevice *self)
 
 	nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
 
+	priv->master_ready_handled = FALSE;
 	nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
 
 	g_clear_object (&priv->act_request);
-- 
2.4.3