[PATCH 6/8] bonding: Postpone auto-activation of a slave until master is present



For a slave to be activatetable the master connection must be present.
Activation of the slave is postponed until this condition is met.

Once the slave is being activated, a reference to the master connection
is acquired and held for the lifetime of the bond.

Changes v2:
 - Made check_master_dependency() return TRUE/FALSE

Signed-off-by: Thomas Graf <tgraf redhat com>
---
 src/nm-device.c  |   27 +++++++++++++++++++++++++++
 src/nm-device.h  |    3 +++
 src/nm-manager.c |   18 ++++++++++++++++++
 src/nm-manager.h |    4 ++++
 src/nm-policy.c  |   34 ++++++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/src/nm-device.c b/src/nm-device.c
index 89b3385..da980e0 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -150,6 +150,8 @@ typedef struct {
 
 	/* inhibit autoconnect feature */
 	gboolean	autoconnect_inhibit;
+
+	NMDevice *	master;
 } NMDevicePrivate;
 
 static gboolean check_connection_compatible (NMDeviceInterface *device,
@@ -494,6 +496,28 @@ nm_device_get_type_desc (NMDevice *self)
 	return NM_DEVICE_GET_PRIVATE (self)->type_desc;
 }
 
+NMDevice *
+nm_device_get_master (NMDevice *self)
+{
+	g_return_val_if_fail (self != NULL, NULL);
+
+	return NM_DEVICE_GET_PRIVATE (self)->master;
+}
+
+void
+nm_device_set_master (NMDevice *self, NMDevice *master)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+	if (priv->master)
+		g_object_unref (priv->master);
+	
+	if (master)
+		g_object_ref (master);
+
+	priv->master = master;
+}
+
 /*
  * nm_device_get_act_request
  *
@@ -3388,6 +3412,9 @@ finalize (GObject *object)
 	if (priv->dhcp_anycast_address)
 		g_byte_array_free (priv->dhcp_anycast_address, TRUE);
 
+	/* release master reference it still exists */
+	nm_device_set_master (self, NULL);
+
 	G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
 }
 
diff --git a/src/nm-device.h b/src/nm-device.h
index 1d080ed..eda00bf 100644
--- a/src/nm-device.h
+++ b/src/nm-device.h
@@ -154,6 +154,9 @@ NMIP6Config *	nm_device_get_ip6_config	(NMDevice *dev);
 
 void *		nm_device_get_system_config_data	(NMDevice *dev);
 
+NMDevice *	nm_device_get_master (NMDevice *self);
+void		nm_device_set_master (NMDevice *self, NMDevice *master);
+
 NMActRequest *	nm_device_get_act_request	(NMDevice *dev);
 
 gboolean		nm_device_is_available (NMDevice *dev);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index fbeb8a9..2f4ca5e 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -366,6 +366,24 @@ nm_manager_get_device_by_path (NMManager *manager, const char *path)
 	return NULL;
 }
 
+NMDevice *
+nm_manager_get_device_by_master (NMManager *manager, const char *master, const char *driver)
+{
+	GSList *iter;
+
+	g_return_val_if_fail (master != NULL, NULL);
+
+	for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
+		NMDevice *device = NM_DEVICE (iter->data);
+
+		if (!strcmp (nm_device_get_iface (device), master) &&
+		    (!driver || !strcmp (nm_device_get_driver (device), driver)))
+			return device;
+	}
+
+	return NULL;
+}
+
 static gboolean
 manager_sleeping (NMManager *self)
 {
diff --git a/src/nm-manager.h b/src/nm-manager.h
index b044971..4e8d67e 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -84,6 +84,10 @@ void nm_manager_start (NMManager *manager);
 
 GSList *nm_manager_get_devices (NMManager *manager);
 
+NMDevice *nm_manager_get_device_by_master (NMManager *manager,
+					   const char *master,
+					   const char *driver);
+
 const char * nm_manager_activate_connection (NMManager *manager,
                                              NMConnection *connection,
                                              const char *specific_object,
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 02292f7..2ed0c5e 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -708,6 +708,33 @@ activate_data_free (ActivateData *data)
 	g_free (data);
 }
 
+static NMActStageReturn
+check_master_dependency (NMManager *manager, NMDevice *device, NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+	NMDevice *master_device;
+	const char *master;
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+
+	master = nm_setting_connection_get_master (s_con);
+
+	/* no master defined, proceed with activation */
+	if (!master)
+		return TRUE;
+
+	master_device = nm_manager_get_device_by_master (manager, master, NULL);
+
+	/* If master device is not yet present, postpone activation until later */
+	if (!master_device)
+		return FALSE;
+
+	nm_device_set_master (device, master_device);
+
+	return TRUE;
+}
+
 static gboolean
 auto_activate_device (gpointer user_data)
 {
@@ -764,6 +791,12 @@ auto_activate_device (gpointer user_data)
 	if (best_connection) {
 		GError *error = NULL;
 
+		if (!check_master_dependency (data->policy->manager, data->device, best_connection)) {
+			nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation postponed: master not available",
+			             nm_connection_get_id (best_connection));
+			goto postpone;
+		}
+
 		nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.",
 		             nm_connection_get_id (best_connection));
 		if (!nm_manager_activate_connection (policy->manager,
@@ -778,6 +811,7 @@ auto_activate_device (gpointer user_data)
 		}
 	}
 
+ postpone:
 	g_slist_free (connections);
 
  out:
-- 
1.7.6.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]