mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-04 13:00:31 +01:00
platform: warn about growing sysctl logging cache and clear it
When debug-logging for platform is enabled, every access to sysctl is cached (to log the last values). This cache can grow quite large if the system has a large number of interfaces (e.g. docker creating veth pairs for each container). We already used to clear the cache, when we were about to access sysctl *and* logging was disabled in the meantime. Now, when logging setup changes, immediately clear the cache. Having "nm-logging.c" call into platform code is a bit of a hack and a better design would be to have logging code emit a signal to which platform would subscribe. But that seems to involve much more code (especially, as no other users care about such a signal and because nm-logging is not a GObject). Also, log a warning when the cache grows large to inform the user about the cache and what he can do to clear it. The extra effort to clear the cache when changing logging setup is done so that we do what we tell the user: changing the logging level, will clear the cache -- right away, not some time later when the next message is logged.
This commit is contained in:
parent
fd87ce503c
commit
98e34208bd
3 changed files with 44 additions and 12 deletions
|
|
@ -40,6 +40,7 @@
|
|||
#include "nm-default.h"
|
||||
#include "nm-errors.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-linux-platform.h"
|
||||
|
||||
static void
|
||||
nm_log_handler (const gchar *log_domain,
|
||||
|
|
@ -169,6 +170,7 @@ nm_logging_setup (const char *level,
|
|||
NMLogLevel new_log_level = log_level;
|
||||
char **tmp, **iter;
|
||||
int i;
|
||||
gboolean had_platform_debug;
|
||||
|
||||
g_return_val_if_fail (!bad_domains || !*bad_domains, FALSE);
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
|
@ -276,10 +278,20 @@ nm_logging_setup (const char *level,
|
|||
|
||||
g_clear_pointer (&logging_domains_to_string, g_free);
|
||||
|
||||
had_platform_debug = nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM);
|
||||
|
||||
log_level = new_log_level;
|
||||
for (i = 0; i < G_N_ELEMENTS (new_logging); i++)
|
||||
logging[i] = new_logging[i];
|
||||
|
||||
if ( had_platform_debug
|
||||
&& !nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
||||
/* when debug logging is enabled, platform will cache all access to
|
||||
* sysctl. When the user disables debug-logging, we want to clear that
|
||||
* cache right away. */
|
||||
_nm_linux_platform_sysctl_clear_cache ();
|
||||
}
|
||||
|
||||
if (unrecognized)
|
||||
*bad_domains = g_string_free (unrecognized, FALSE);
|
||||
|
||||
|
|
|
|||
|
|
@ -731,6 +731,7 @@ struct _NMLinuxPlatformPrivate {
|
|||
GIOChannel *event_channel;
|
||||
guint event_id;
|
||||
|
||||
gboolean sysctl_get_warned;
|
||||
GHashTable *sysctl_get_prev_values;
|
||||
|
||||
GUdevClient *udev_client;
|
||||
|
|
@ -2546,15 +2547,32 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
|
|||
return (nwrote == len);
|
||||
}
|
||||
|
||||
static GSList *sysctl_clear_cache_list;
|
||||
|
||||
void
|
||||
_nm_linux_platform_sysctl_clear_cache (void)
|
||||
{
|
||||
while (sysctl_clear_cache_list) {
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (sysctl_clear_cache_list->data);
|
||||
|
||||
sysctl_clear_cache_list = g_slist_delete_link (sysctl_clear_cache_list, sysctl_clear_cache_list);
|
||||
|
||||
g_hash_table_destroy (priv->sysctl_get_prev_values);
|
||||
priv->sysctl_get_prev_values = NULL;
|
||||
priv->sysctl_get_warned = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *contents)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
const char *prev_value = NULL;
|
||||
|
||||
if (!priv->sysctl_get_prev_values)
|
||||
if (!priv->sysctl_get_prev_values) {
|
||||
sysctl_clear_cache_list = g_slist_prepend (sysctl_clear_cache_list, platform);
|
||||
priv->sysctl_get_prev_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
else
|
||||
} else
|
||||
prev_value = g_hash_table_lookup (priv->sysctl_get_prev_values, path);
|
||||
|
||||
if (prev_value) {
|
||||
|
|
@ -2574,20 +2592,18 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co
|
|||
g_free (contents_escaped);
|
||||
g_hash_table_insert (priv->sysctl_get_prev_values, g_strdup (path), g_strdup (contents));
|
||||
}
|
||||
|
||||
if ( !priv->sysctl_get_warned
|
||||
&& g_hash_table_size (priv->sysctl_get_prev_values) > 50000) {
|
||||
_LOGW ("sysctl: the internal cache for debug-logging of sysctl values grew pretty large. You can clear it by disabling debug-logging: `nmcli general logging level KEEP domains PLATFORM:INFO`.");
|
||||
priv->sysctl_get_warned = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#define _log_dbg_sysctl_get(platform, path, contents) \
|
||||
G_STMT_START { \
|
||||
if (_LOGD_ENABLED ()) { \
|
||||
if (_LOGD_ENABLED ()) \
|
||||
_log_dbg_sysctl_get_impl (platform, path, contents); \
|
||||
} else { \
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); \
|
||||
\
|
||||
if (priv->sysctl_get_prev_values) { \
|
||||
g_hash_table_destroy (priv->sysctl_get_prev_values); \
|
||||
priv->sysctl_get_prev_values = NULL; \
|
||||
} \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
static char *
|
||||
|
|
@ -5029,8 +5045,10 @@ nm_linux_platform_finalize (GObject *object)
|
|||
g_object_unref (priv->udev_client);
|
||||
g_hash_table_unref (priv->wifi_data);
|
||||
|
||||
if (priv->sysctl_get_prev_values)
|
||||
if (priv->sysctl_get_prev_values) {
|
||||
sysctl_clear_cache_list = g_slist_remove (sysctl_clear_cache_list, object);
|
||||
g_hash_table_destroy (priv->sysctl_get_prev_values);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_linux_platform_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,4 +50,6 @@ GType nm_linux_platform_get_type (void);
|
|||
|
||||
void nm_linux_platform_setup (void);
|
||||
|
||||
void _nm_linux_platform_sysctl_clear_cache (void);
|
||||
|
||||
#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue