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.
This commit is contained in:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user