From c87688a05a8b49479ee10127470cc60acebead4a Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Fri, 4 Oct 2013 20:27:45 +0200 Subject: Fix mtab translator leak The node structure for the `mounts' entry is created and destroyed on each access, despite the fact a translator is activated on it. Fix the issue by caching it. * rootdir.c (rootdir_mounts_node): New variable. (rootdir_mounts_node_lock): Likewise. (rootdir_mounts_make_node): New function. (rootdir_translator_make_node): Remove function. (rootdir_entries): Replace `rootdir_translator_make_node' with `rootdir_mounts_make_node'. --- rootdir.c | 55 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/rootdir.c b/rootdir.c index 34bf91c..94b0ddb 100644 --- a/rootdir.c +++ b/rootdir.c @@ -407,6 +407,47 @@ rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) /* The mtab translator to use by default for the "mounts" node. */ #define MTAB_TRANSLATOR "/hurd/mtab" +static struct node *rootdir_mounts_node; +static pthread_spinlock_t rootdir_mounts_node_lock = + PTHREAD_SPINLOCK_INITIALIZER; + +static struct node * +rootdir_mounts_make_node (void *dir_hook, const void *entry_hook) +{ + struct node *np, *prev; + + pthread_spin_lock (&rootdir_mounts_node_lock); + np = rootdir_mounts_node; + pthread_spin_unlock (&rootdir_mounts_node_lock); + + if (np != NULL) + { + netfs_nref (np); + return np; + } + + np = procfs_make_node (entry_hook, dir_hook); + if (np == NULL) + return NULL; + + procfs_node_chtype (np, S_IFREG | S_IPTRANS); + procfs_node_chmod (np, 0444); + + pthread_spin_lock (&rootdir_mounts_node_lock); + prev = rootdir_mounts_node; + if (rootdir_mounts_node == NULL) + rootdir_mounts_node = np; + pthread_spin_unlock (&rootdir_mounts_node_lock); + + if (prev != NULL) + { + procfs_cleanup (np); + np = prev; + } + + return np; +} + static error_t rootdir_mounts_get_translator (void *hook, char **argz, size_t *argz_len) { @@ -451,18 +492,6 @@ rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) return np; } -static struct node * -rootdir_translator_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np = procfs_make_node (entry_hook, dir_hook); - if (np) - { - procfs_node_chtype (np, S_IFREG | S_IPTRANS); - procfs_node_chmod (np, 0444); - } - return np; -} - static const struct procfs_dir_entry rootdir_entries[] = { { .name = "self", @@ -530,7 +559,7 @@ static const struct procfs_dir_entry rootdir_entries[] = { .get_translator = rootdir_mounts_get_translator, }, .ops = { - .make_node = rootdir_translator_make_node, + .make_node = rootdir_mounts_make_node, .exists = rootdir_mounts_exists, } }, -- cgit v1.2.3