diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2022-04-27 16:27:24 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2022-05-03 13:19:24 +0200 |
commit | 9fcbc6b37deccaa0bfcc9bddec726e41d5df5ced (patch) | |
tree | 6582cc920c0bbd1c4ac2d724541c89874dc216e8 | |
parent | bcc958c411287ccc650cd04bc77ac22c8fecb08c (diff) | |
download | NetworkManager-9fcbc6b37deccaa0bfcc9bddec726e41d5df5ced.tar.gz |
device: make attach_port() asynchronous
For some device types the attach-port operation doesn't complete
immediately. NMDevice needs to wait that the operation completes
before proceeding (for example, before starting stage3 for the port).
Change attach_port() so that it can return TERNARY_DEFAULT to indicate
that the operation will complete asynchronously. Most of devices are
not affected by this and can continue returning TRUE/FALSE as before
without callback.
-rw-r--r-- | src/core/devices/nm-device-bond.c | 10 | ||||
-rw-r--r-- | src/core/devices/nm-device-bridge.c | 10 | ||||
-rw-r--r-- | src/core/devices/nm-device-vrf.c | 10 | ||||
-rw-r--r-- | src/core/devices/nm-device.c | 114 | ||||
-rw-r--r-- | src/core/devices/nm-device.h | 17 | ||||
-rw-r--r-- | src/core/devices/ovs/nm-device-ovs-bridge.c | 10 | ||||
-rw-r--r-- | src/core/devices/ovs/nm-device-ovs-port.c | 10 | ||||
-rw-r--r-- | src/core/devices/team/nm-device-team.c | 10 |
8 files changed, 136 insertions, 55 deletions
diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 80400afcc4..d5cb158a1b 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -424,8 +424,14 @@ commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_ queue_id_str); } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceBond *self = NM_DEVICE_BOND(device); NMSettingBondPort *s_port; diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 796e58c650..7b7053296c 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -974,8 +974,14 @@ deactivate(NMDevice *device) } } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); NMConnection *master_connection; diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 6454d4d30d..2aef0e3d1e 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -206,8 +206,14 @@ update_connection(NMDevice *device, NMConnection *connection) g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL); } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceVrf *self = NM_DEVICE_VRF(device); gboolean success = TRUE; diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 93f9e7fd2f..a1a024cef3 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -120,11 +120,12 @@ typedef enum _nm_packed { } AddrMethodState; typedef struct { - CList lst_slave; - NMDevice *slave; - gulong watch_id; - bool slave_is_enslaved; - bool configure; + CList lst_slave; + NMDevice *slave; + GCancellable *cancellable; + gulong watch_id; + bool slave_is_enslaved; + bool configure; } SlaveInfo; typedef struct { @@ -5927,43 +5928,16 @@ find_slave_info(NMDevice *self, NMDevice *slave) return NULL; } -/** - * nm_device_master_enslave_slave: - * @self: the master device - * @slave: the slave device to enslave - * @connection: (allow-none): the slave device's connection - * - * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, - * etc) then this function enslaves @slave. - * - * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave - * other devices. - */ -static gboolean -nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection) +static void +attach_port_done(NMDevice *self, NMDevice *slave, gboolean success) { SlaveInfo *info; - gboolean success = FALSE; - gboolean configure; - - g_return_val_if_fail(self != NULL, FALSE); - g_return_val_if_fail(slave != NULL, FALSE); - g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port != NULL, FALSE); info = find_slave_info(self, slave); if (!info) - return FALSE; - - if (info->slave_is_enslaved) - success = TRUE; - else { - configure = (info->configure && connection != NULL); - if (configure) - g_return_val_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + return; - success = NM_DEVICE_GET_CLASS(self)->attach_port(self, slave, connection, configure); - info->slave_is_enslaved = success; - } + info->slave_is_enslaved = success; nm_device_slave_notify_enslave(info->slave, success); @@ -5983,8 +5957,71 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co */ if (success) nm_device_activate_schedule_stage3_ip_config(self, FALSE); +} - return success; +static void +attach_port_cb(NMDevice *self, GError *error, gpointer user_data) +{ + NMDevice *slave = user_data; + SlaveInfo *info; + + if (nm_utils_error_is_cancelled(error)) + return; + + info = find_slave_info(self, slave); + if (!info) + return; + + nm_clear_g_cancellable(&info->cancellable); + attach_port_done(self, slave, !error); +} + +/** + * nm_device_master_enslave_slave: + * @self: the master device + * @slave: the slave device to enslave + * @connection: (allow-none): the slave device's connection + * + * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, + * etc) then this function enslaves @slave. + */ +static void +nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection) +{ + SlaveInfo *info; + NMTernary success; + gboolean configure; + + g_return_if_fail(self); + g_return_if_fail(slave); + g_return_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port); + + info = find_slave_info(self, slave); + if (!info) + return; + + if (info->slave_is_enslaved) + success = TRUE; + else { + configure = (info->configure && connection != NULL); + if (configure) + g_return_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED); + + nm_clear_g_cancellable(&info->cancellable); + info->cancellable = g_cancellable_new(); + success = NM_DEVICE_GET_CLASS(self)->attach_port(self, + slave, + connection, + configure, + info->cancellable, + attach_port_cb, + slave); + + if (success == NM_TERNARY_DEFAULT) + return; + } + + attach_port_done(self, slave, success); } /** @@ -6038,6 +6075,7 @@ nm_device_master_release_slave(NMDevice *self, g_return_if_fail(self == slave_priv->master); nm_assert(slave == info->slave); + nm_clear_g_cancellable(&info->cancellable); /* first, let subclasses handle the release ... */ if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave) @@ -7609,7 +7647,7 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure) g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); g_return_val_if_fail(NM_IS_DEVICE(slave), FALSE); - g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port != NULL, FALSE); + g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port, FALSE); priv = NM_DEVICE_GET_PRIVATE(self); slave_priv = NM_DEVICE_GET_PRIVATE(slave); diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index bfa274d69e..377c2fb6b8 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -163,6 +163,7 @@ typedef enum { } NMDeviceCheckDevAvailableFlags; typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data); +typedef void (*NMDeviceAttachPortCallback)(NMDevice *self, GError *error, gpointer user_data); typedef struct _NMDeviceClass { NMDBusObjectClass parent; @@ -373,11 +374,17 @@ typedef struct _NMDeviceClass { NMConnection *connection, GError **error); - gboolean (*attach_port)(NMDevice *self, - NMDevice *port, - NMConnection *connection, - gboolean configure); - + /* Attachs a port asynchronously. Returns TRUE/FALSE on immediate + * success/error; in such cases, the callback is not invoked. If the + * action couldn't be completed immediately, DEFAULT is returned and + * the callback will always be invoked asynchronously. */ + NMTernary (*attach_port)(NMDevice *self, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data); void (*detach_port)(NMDevice *self, NMDevice *port, gboolean configure); void (*parent_changed_notify)(NMDevice *self, diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index da0a830e5d..bea6e77bc8 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -78,8 +78,14 @@ act_stage3_ip_config(NMDevice *device, int addr_family) nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { if (!configure) return TRUE; diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index 72c534ebf0..86f5e6bec6 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -115,8 +115,14 @@ set_mtu_cb(GError *error, gpointer user_data) g_object_unref(self); } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceEnslaveSlaveCallback callback, + gpointer user_data) { NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); NMActiveConnection *ac_port = NULL; diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 77a259d413..1f098806d3 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -790,8 +790,14 @@ deactivate(NMDevice *device) teamd_cleanup(self, TRUE); } -static gboolean -attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); |