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);
|
queue_id_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDeviceBond *self = NM_DEVICE_BOND(device);
|
NMDeviceBond *self = NM_DEVICE_BOND(device);
|
||||||
NMSettingBondPort *s_port;
|
NMSettingBondPort *s_port;
|
||||||
|
@@ -974,8 +974,14 @@ deactivate(NMDevice *device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE(device);
|
NMDeviceBridge *self = NM_DEVICE_BRIDGE(device);
|
||||||
NMConnection *master_connection;
|
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);
|
g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDeviceVrf *self = NM_DEVICE_VRF(device);
|
NMDeviceVrf *self = NM_DEVICE_VRF(device);
|
||||||
gboolean success = TRUE;
|
gboolean success = TRUE;
|
||||||
|
@@ -122,6 +122,7 @@ typedef enum _nm_packed {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
CList lst_slave;
|
CList lst_slave;
|
||||||
NMDevice *slave;
|
NMDevice *slave;
|
||||||
|
GCancellable *cancellable;
|
||||||
gulong watch_id;
|
gulong watch_id;
|
||||||
bool slave_is_enslaved;
|
bool slave_is_enslaved;
|
||||||
bool configure;
|
bool configure;
|
||||||
@@ -5927,43 +5928,16 @@ find_slave_info(NMDevice *self, NMDevice *slave)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* nm_device_master_enslave_slave:
|
attach_port_done(NMDevice *self, NMDevice *slave, gboolean success)
|
||||||
* @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)
|
|
||||||
{
|
{
|
||||||
SlaveInfo *info;
|
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);
|
info = find_slave_info(self, slave);
|
||||||
if (!info)
|
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);
|
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)
|
if (success)
|
||||||
nm_device_activate_schedule_stage3_ip_config(self, FALSE);
|
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);
|
g_return_if_fail(self == slave_priv->master);
|
||||||
nm_assert(slave == info->slave);
|
nm_assert(slave == info->slave);
|
||||||
|
nm_clear_g_cancellable(&info->cancellable);
|
||||||
|
|
||||||
/* first, let subclasses handle the release ... */
|
/* first, let subclasses handle the release ... */
|
||||||
if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave)
|
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(self), FALSE);
|
||||||
g_return_val_if_fail(NM_IS_DEVICE(slave), 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);
|
priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
slave_priv = NM_DEVICE_GET_PRIVATE(slave);
|
slave_priv = NM_DEVICE_GET_PRIVATE(slave);
|
||||||
|
@@ -163,6 +163,7 @@ typedef enum {
|
|||||||
} NMDeviceCheckDevAvailableFlags;
|
} NMDeviceCheckDevAvailableFlags;
|
||||||
|
|
||||||
typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data);
|
typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data);
|
||||||
|
typedef void (*NMDeviceAttachPortCallback)(NMDevice *self, GError *error, gpointer user_data);
|
||||||
|
|
||||||
typedef struct _NMDeviceClass {
|
typedef struct _NMDeviceClass {
|
||||||
NMDBusObjectClass parent;
|
NMDBusObjectClass parent;
|
||||||
@@ -373,11 +374,17 @@ typedef struct _NMDeviceClass {
|
|||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean (*attach_port)(NMDevice *self,
|
/* 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,
|
NMDevice *port,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
gboolean configure);
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
void (*detach_port)(NMDevice *self, NMDevice *port, gboolean configure);
|
void (*detach_port)(NMDevice *self, NMDevice *port, gboolean configure);
|
||||||
|
|
||||||
void (*parent_changed_notify)(NMDevice *self,
|
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);
|
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if (!configure)
|
if (!configure)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@@ -115,8 +115,14 @@ set_mtu_cb(GError *error, gpointer user_data)
|
|||||||
g_object_unref(self);
|
g_object_unref(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceEnslaveSlaveCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device);
|
NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device);
|
||||||
NMActiveConnection *ac_port = NULL;
|
NMActiveConnection *ac_port = NULL;
|
||||||
|
@@ -790,8 +790,14 @@ deactivate(NMDevice *device)
|
|||||||
teamd_cleanup(self, TRUE);
|
teamd_cleanup(self, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMTernary
|
||||||
attach_port(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
attach_port(NMDevice *device,
|
||||||
|
NMDevice *port,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean configure,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
NMDeviceAttachPortCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDeviceTeam *self = NM_DEVICE_TEAM(device);
|
NMDeviceTeam *self = NM_DEVICE_TEAM(device);
|
||||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
||||||
|
Reference in New Issue
Block a user