summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-06-15 12:45:35 +0200
committerThomas Haller <thaller@redhat.com>2021-06-17 17:49:44 +0200
commit252e4a676b80da3a4ea383517bd90cf7824554ea (patch)
tree925c9300b49182cfbe06139ed2ff249db8ce1b65 /src
parentcea52c7cbdf4c71311e9a680f6ccf8c1c6ddce9d (diff)
core: cache GVariant for result of GetSettings()
The GetSettings() call is not the only place where we convert a NMConnection to D-Bus. However it is one of the most prominent ones with a measurable performance overhead. The connection seldom changes, so it makes sense to cache it. Note that GetSettings() is the only caller that specifies an option, thus it's the only caller that converts a NMConnection to variant in this particular way. That means, other callers don't benefit from this caching and we could not cache the variant in the NMConnection instance itself, because those callers use different parameters.
Diffstat (limited to 'src')
-rw-r--r--src/core/settings/nm-settings-connection.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c
index 520dcc24a0..71431f29d9 100644
--- a/src/core/settings/nm-settings-connection.c
+++ b/src/core/settings/nm-settings-connection.c
@@ -80,6 +80,11 @@ typedef struct _NMSettingsConnectionPrivate {
NMConnection *connection;
+ struct {
+ NMConnectionSerializationOptions options;
+ GVariant * variant;
+ } getsettings_cached;
+
NMSettingsStorage *storage;
char *filename;
@@ -249,6 +254,57 @@ _seen_bssids_hash_new(void)
/*****************************************************************************/
+static void
+_getsettings_cached_clear(NMSettingsConnectionPrivate *priv)
+{
+ if (nm_clear_pointer(&priv->getsettings_cached.variant, g_variant_unref)) {
+ priv->getsettings_cached.options.timestamp.has = FALSE;
+ priv->getsettings_cached.options.timestamp.val = 0;
+ nm_clear_g_free((gpointer *) &priv->getsettings_cached.options.seen_bssids);
+ }
+}
+
+static GVariant *
+_getsettings_cached_get(NMSettingsConnection *self, const NMConnectionSerializationOptions *options)
+{
+ NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
+ GVariant * variant;
+
+ if (priv->getsettings_cached.variant) {
+ if (nm_connection_serialization_options_equal(&priv->getsettings_cached.options, options)) {
+#if NM_MORE_ASSERTS > 10
+ gs_unref_variant GVariant *variant2 = NULL;
+
+ variant = nm_connection_to_dbus_full(priv->connection,
+ NM_CONNECTION_SERIALIZE_WITH_NON_SECRET,
+ options);
+ nm_assert(variant);
+ variant2 = g_variant_new("(@a{sa{sv}})", variant);
+ nm_assert(g_variant_equal(priv->getsettings_cached.variant, variant2));
+#endif
+ return priv->getsettings_cached.variant;
+ }
+ _getsettings_cached_clear(priv);
+ }
+
+ nm_assert(!priv->getsettings_cached.options.seen_bssids);
+
+ variant = nm_connection_to_dbus_full(priv->connection,
+ NM_CONNECTION_SERIALIZE_WITH_NON_SECRET,
+ options);
+ nm_assert(variant);
+
+ priv->getsettings_cached.variant = g_variant_ref_sink(g_variant_new("(@a{sa{sv}})", variant));
+
+ priv->getsettings_cached.options = *options;
+ priv->getsettings_cached.options.seen_bssids =
+ nm_utils_strv_dup_packed(priv->getsettings_cached.options.seen_bssids, -1);
+
+ return priv->getsettings_cached.variant;
+}
+
+/*****************************************************************************/
+
NMConnection *
nm_settings_connection_get_connection(NMSettingsConnection *self)
{
@@ -280,6 +336,8 @@ _nm_settings_connection_set_connection(NMSettingsConnection * self,
priv->connection = g_object_ref(new_connection);
nmtst_connection_assert_unchanging(priv->connection);
+ _getsettings_cached_clear(priv);
+
/* note that we only return @connection_old if the new connection actually differs from
* before.
*
@@ -1243,7 +1301,6 @@ get_settings_auth_cb(NMSettingsConnection * self,
{
gs_free const char ** seen_bssids = NULL;
NMConnectionSerializationOptions options = {};
- GVariant * settings;
if (error) {
g_dbus_method_invocation_return_gerror(context, error);
@@ -1270,10 +1327,8 @@ get_settings_auth_cb(NMSettingsConnection * self,
* get returned by the GetSecrets method which can be better
* protected against leakage of secrets to unprivileged callers.
*/
- settings = nm_connection_to_dbus_full(nm_settings_connection_get_connection(self),
- NM_CONNECTION_SERIALIZE_WITH_NON_SECRET,
- &options);
- g_dbus_method_invocation_return_value(context, g_variant_new("(@a{sa{sv}})", settings));
+
+ g_dbus_method_invocation_return_value(context, _getsettings_cached_get(self, &options));
}
static void
@@ -2620,6 +2675,8 @@ dispose(GObject *object)
g_clear_object(&priv->connection);
+ _getsettings_cached_clear(priv);
+
nm_clear_pointer(&priv->kf_db_timestamps, nm_key_file_db_unref);
nm_clear_pointer(&priv->kf_db_seen_bssids, nm_key_file_db_unref);