libnm: rework caching of virtual-iface-name for infiniband setting

We cache the virtual-iface-name. The caching is also part of the API as
nm_setting_infiniband_get_virtual_interface_name() returns a const
string.

As the value is computed and based on the parent and the p-key, we must
clear the cache when the parent or p-key changes (or detect that it's
invalid).

Previously, we were simply clearing the value in the set_property() function,
which is the only setter of these two properties. If we make these
properties "direct properties", then they will be directly set via
from_dbus_fcn() which bypasses the GObject setter. Which is a problem
for the cache invalidation.

We could either not make those properties direct properties. The problem
is that direct properties are nice, and they will in the future
implement further optimizations for them. Also, they are the default
implementation, and it seems clearer to build something on top of that,
instead of deviating from the default.

Instead, let the caching detect when the value needs to be regenerated.
This commit is contained in:
Thomas Haller
2022-01-13 10:34:20 +01:00
parent 1ed46739c0
commit 99d898cf1f

View File

@@ -36,6 +36,8 @@ typedef struct {
char *transport_mode; char *transport_mode;
char *parent; char *parent;
char *virtual_iface_name; char *virtual_iface_name;
gsize virtual_iface_name_parent_length;
int virtual_iface_name_p_key;
int p_key; int p_key;
guint32 mtu; guint32 mtu;
} NMSettingInfinibandPrivate; } NMSettingInfinibandPrivate;
@@ -156,14 +158,24 @@ const char *
nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting) nm_setting_infiniband_get_virtual_interface_name(NMSettingInfiniband *setting)
{ {
NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting); NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE(setting);
gsize len;
if (priv->p_key == -1 || !priv->parent) if (priv->p_key == -1 || !priv->parent) {
nm_clear_g_free(&priv->virtual_iface_name);
return NULL; return NULL;
}
if (!priv->virtual_iface_name) len = strlen(priv->parent);
if (!priv->virtual_iface_name || priv->virtual_iface_name_p_key != priv->p_key
|| priv->virtual_iface_name_parent_length != len
|| memcmp(priv->parent, priv->virtual_iface_name, len) != 0) {
priv->virtual_iface_name_p_key = priv->p_key;
priv->virtual_iface_name_parent_length = len;
g_free(priv->virtual_iface_name);
priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key); priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key);
}
return NM_SETTING_INFINIBAND_GET_PRIVATE(setting)->virtual_iface_name; return priv->virtual_iface_name;
} }
static gboolean static gboolean
@@ -237,10 +249,12 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
const char *interface_name = nm_setting_connection_get_interface_name(s_con); const char *interface_name = nm_setting_connection_get_interface_name(s_con);
if (interface_name && priv->p_key != -1) { if (interface_name && priv->p_key != -1) {
if (!priv->virtual_iface_name) const char *virtual_iface_name;
priv->virtual_iface_name = g_strdup_printf("%s.%04x", priv->parent, priv->p_key);
if (strcmp(interface_name, priv->virtual_iface_name) != 0) { virtual_iface_name =
nm_setting_infiniband_get_virtual_interface_name(NM_SETTING_INFINIBAND(setting));
if (!nm_streq(interface_name, virtual_iface_name)) {
/* We don't support renaming software infiniband devices. Later we might, but /* We don't support renaming software infiniband devices. Later we might, but
* for now just reject such connections. * for now just reject such connections.
**/ **/
@@ -249,7 +263,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
NM_CONNECTION_ERROR_INVALID_PROPERTY, NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("interface name of software infiniband device must be '%s' or unset " _("interface name of software infiniband device must be '%s' or unset "
"(instead it is '%s')"), "(instead it is '%s')"),
priv->virtual_iface_name, virtual_iface_name,
interface_name); interface_name);
g_prefix_error(error, g_prefix_error(error,
"%s.%s: ", "%s.%s: ",
@@ -337,12 +351,10 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
break; break;
case PROP_P_KEY: case PROP_P_KEY:
priv->p_key = g_value_get_int(value); priv->p_key = g_value_get_int(value);
nm_clear_g_free(&priv->virtual_iface_name);
break; break;
case PROP_PARENT: case PROP_PARENT:
g_free(priv->parent); g_free(priv->parent);
priv->parent = g_value_dup_string(value); priv->parent = g_value_dup_string(value);
nm_clear_g_free(&priv->virtual_iface_name);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);