devices: fix up parent/peer tracking in some virtual devices

NMDeviceGre and NMDeviceMacvlan didn't deal with the possibility that
the virtual device might be created before its parent's NMDevice is
created. Mostly fix this by having them put off the call to
nm_manager_get_device_by_ifindex() until someone actually requests the
device.

This is not perfect; if someone listening to notify::parent checks
right away, they may find that the parent property is still NULL, and
notify::parent will not be emitted again when it gets filled in. But
it's better than what's there now, when parent would remain NULL
forever in this case.

NMDeviceVeth did not have this problem, but it did have another
possible problem because it wasn't cleaning up its weak references
properly.
This commit is contained in:
Dan Winship
2014-02-26 13:32:30 -05:00
parent 18f35ec1d8
commit 2bc903aaf1
3 changed files with 23 additions and 19 deletions

View File

@@ -36,7 +36,6 @@ G_DEFINE_TYPE (NMDeviceGre, nm_device_gre, NM_TYPE_DEVICE_GENERIC)
#define NM_DEVICE_GRE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GRE, NMDeviceGrePrivate))
typedef struct {
NMDevice *parent;
NMPlatformGreProperties props;
} NMDeviceGrePrivate;
@@ -73,15 +72,8 @@ update_properties (NMDevice *device)
g_object_freeze_notify (object);
if (priv->props.parent_ifindex != props.parent_ifindex) {
if (priv->props.parent_ifindex != props.parent_ifindex)
g_object_notify (object, NM_DEVICE_GRE_PARENT);
if (priv->parent)
g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
priv->parent = nm_manager_get_device_by_ifindex (nm_manager_get (), props.parent_ifindex);
if (priv->parent)
g_object_add_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
}
if (priv->props.input_flags != props.input_flags)
g_object_notify (object, NM_DEVICE_GRE_INPUT_FLAGS);
if (priv->props.output_flags != props.output_flags)
@@ -146,10 +138,12 @@ get_property (GObject *object, guint prop_id,
{
NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (object);
char buf[INET_ADDRSTRLEN];
NMDevice *parent;
switch (prop_id) {
case PROP_PARENT:
g_value_set_boxed (value, priv->parent ? nm_device_get_path (priv->parent) : "/");
parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex);
g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/");
break;
case PROP_INPUT_FLAGS:
g_value_set_uint (value, priv->props.input_flags);

View File

@@ -36,7 +36,6 @@ G_DEFINE_TYPE (NMDeviceMacvlan, nm_device_macvlan, NM_TYPE_DEVICE_GENERIC)
#define NM_DEVICE_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanPrivate))
typedef struct {
NMDevice *parent;
NMPlatformMacvlanProperties props;
} NMDeviceMacvlanPrivate;
@@ -68,14 +67,8 @@ update_properties (NMDevice *device)
g_object_freeze_notify (object);
if (priv->props.parent_ifindex != props.parent_ifindex) {
if (priv->props.parent_ifindex != props.parent_ifindex)
g_object_notify (object, NM_DEVICE_MACVLAN_PARENT);
if (priv->parent)
g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
priv->parent = nm_manager_get_device_by_ifindex (nm_manager_get (), props.parent_ifindex);
if (priv->parent)
g_object_add_weak_pointer (G_OBJECT (priv->parent), (gpointer *) &priv->parent);
}
if (g_strcmp0 (priv->props.mode, props.mode) != 0)
g_object_notify (object, NM_DEVICE_MACVLAN_MODE);
if (priv->props.no_promisc != props.no_promisc)
@@ -125,10 +118,12 @@ get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object);
NMDevice *parent;
switch (prop_id) {
case PROP_PARENT:
g_value_set_boxed (value, priv->parent ? nm_device_get_path (priv->parent) : "/");
parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex);
g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/");
break;
case PROP_MODE:
g_value_set_string (value, priv->props.mode);

View File

@@ -113,6 +113,20 @@ nm_device_veth_init (NMDeviceVeth *self)
{
}
static void
dispose (GObject *object)
{
NMDeviceVeth *self = NM_DEVICE_VETH (object);
NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self);
if (priv->peer) {
g_object_remove_weak_pointer (G_OBJECT (priv->peer), (gpointer *) &priv->peer);
priv->peer = NULL;
}
G_OBJECT_CLASS (nm_device_veth_parent_class)->dispose (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -139,6 +153,7 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate));
object_class->get_property = get_property;
object_class->dispose = dispose;
/* properties */
g_object_class_install_property