diff options
author | Thomas Haller <thaller@redhat.com> | 2015-10-01 16:48:32 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-10-02 16:43:41 +0200 |
commit | 79ab3f2b23a88fbcf5a98714802e556f0f0744ef (patch) | |
tree | 083e989a913867ea51d2134b190d98d8e071ebea | |
parent | e427d32ec3a12071cb9e5b61433bd65ff4a89682 (diff) | |
download | NetworkManager-th/enslave-team-rh1183444.tar.gz |
device: fix activating slave device when stage1 delays actionth/enslave-team-rh1183444
When activating for example a team device that is 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 parent
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
-rw-r--r-- | src/devices/nm-device.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index beba09b2f7..2d66e5ee56 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -335,6 +335,7 @@ typedef struct { /* master interface for bridge/bond/team slave */ NMDevice * master; gboolean enslaved; + gboolean master_ready_handled; guint master_ready_id; /* slave management */ @@ -2855,19 +2856,21 @@ 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_assert (!priv->master_ready_handled); /* Notify a master device that it has a new slave */ g_assert (nm_active_connection_get_master_ready (active)); master = nm_active_connection_get_master (active); + priv->master_ready_handled = TRUE; + priv->master = g_object_ref (nm_active_connection_get_device (master)); nm_device_master_add_slave (priv->master, self, @@ -2877,7 +2880,14 @@ master_ready_cb (NMActiveConnection *active, 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); } @@ -2925,23 +2935,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."); @@ -2995,6 +2989,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); @@ -6182,6 +6198,7 @@ clear_act_request (NMDevice *self) nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id); + priv->master_ready_handled = FALSE; g_clear_object (&priv->act_request); g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); |