diff options
author | Richard Braun <rbraun@sceen.net> | 2013-10-04 20:27:45 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-10-05 23:45:09 +0200 |
commit | c87688a05a8b49479ee10127470cc60acebead4a (patch) | |
tree | 26cd19e3cf64bc150c6da3a0b7a33220d50e106a | |
parent | 969078c9755b7e28dcabe277629f757e20a19f1a (diff) |
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'.
-rw-r--r-- | rootdir.c | 55 |
1 files changed, 42 insertions, 13 deletions
@@ -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, } }, |