From a93807c288743f499362f7edfe0674020762811c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 20 Apr 2016 09:16:41 +0200 Subject: [PATCH] infiniband: remove the partitions on unrealizing The infiniband drivers don't implement the rtnetlink link deletions. Therefore we unrealize the NMDevice instance but the backing resources stay around, preventing us from ever realizing the device again. --- src/devices/nm-device-infiniband.c | 42 +++++++++++++++++++++++++----- src/devices/nm-device.c | 6 ++++- src/devices/nm-device.h | 8 ++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 0465ae36b..ae9543e4e 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -42,6 +42,7 @@ G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE) typedef struct { gboolean is_partition; + int parent_ifindex, p_key; } NMDeviceInfinibandPrivate; enum { @@ -235,16 +236,16 @@ create_and_realize (NMDevice *device, const NMPlatformLink **out_plink, GError **error) { + NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); NMSettingInfiniband *s_infiniband; - int parent_ifindex, p_key; NMPlatformError plerr; s_infiniband = nm_connection_get_setting_infiniband (connection); g_assert (s_infiniband); /* Can only create partitions at this time */ - p_key = nm_setting_infiniband_get_p_key (s_infiniband); - if (p_key < 0) { + priv->p_key = nm_setting_infiniband_get_p_key (s_infiniband); + if (priv->p_key < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "only InfiniBand partitions can be created"); return FALSE; @@ -263,15 +264,15 @@ create_and_realize (NMDevice *device, return FALSE; } - parent_ifindex = nm_device_get_ifindex (parent); - if (parent_ifindex <= 0) { + priv->parent_ifindex = nm_device_get_ifindex (parent); + if (priv->parent_ifindex <= 0) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "failed to get InfiniBand parent %s ifindex", nm_device_get_iface (parent)); return FALSE; } - plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink); + plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, priv->parent_ifindex, priv->p_key, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create InfiniBand P_Key interface '%s' for '%s': %s", @@ -281,7 +282,33 @@ create_and_realize (NMDevice *device, return FALSE; } - NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->is_partition = TRUE; + priv->is_partition = TRUE; + return TRUE; +} + +static gboolean +unrealize (NMDevice *device, GError **error) +{ + NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (device); + NMPlatformError plerr; + + g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), FALSE); + + if (priv->p_key < 0) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Only InfiniBand partitions can be removed"); + return FALSE; + } + + plerr = nm_platform_link_infiniband_delete (NM_PLATFORM_GET, priv->parent_ifindex, priv->p_key); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to remove InfiniBand P_Key interface '%s': %s", + nm_device_get_iface (device), + nm_platform_error_to_string (plerr)); + return FALSE; + } + return TRUE; } @@ -335,6 +362,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) object_class->set_property = set_property; parent_class->create_and_realize = create_and_realize; + parent_class->unrealize = unrealize; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 1c6612df8..499a624c8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2138,8 +2138,12 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) _LOGD (LOGD_DEVICE, "unrealize (ifindex %d)", ifindex > 0 ? ifindex : 0); if (remove_resources) { - if (ifindex > 0) + if (NM_DEVICE_GET_CLASS (self)->unrealize) { + if (!NM_DEVICE_GET_CLASS (self)->unrealize (self, error)) + return FALSE; + } else if (ifindex > 0) { nm_platform_link_delete (NM_PLATFORM_GET, ifindex); + } } NM_DEVICE_GET_CLASS (self)->unrealize_notify (self); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 368e77f74..2221ede12 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -179,6 +179,14 @@ typedef struct { */ void (*realize_start_notify) (NMDevice *self, const NMPlatformLink *plink); + /** + * unrealize(): + * @self: the #NMDevice + * + * Remove the device backing resources. + */ + gboolean (*unrealize) (NMDevice *self, GError **error); + /** * unrealize_notify(): * @self: the #NMDevice