summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-10-04 20:27:45 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2013-10-05 23:45:09 +0200
commitc87688a05a8b49479ee10127470cc60acebead4a (patch)
tree26cd19e3cf64bc150c6da3a0b7a33220d50e106a
parent969078c9755b7e28dcabe277629f757e20a19f1a (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.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/rootdir.c b/rootdir.c
index 34bf91ce..94b0ddb2 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,
}
},