summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Koenig <jk@jk.fr.eu.org>2010-08-23 20:43:16 +0000
committerJeremie Koenig <jk@jk.fr.eu.org>2010-08-30 14:31:32 +0200
commitc9bfe14f2e5e09b1692ae4a120de1df2cf835d05 (patch)
tree197c1f3acfccdd1e51b9ea098fac59ef24678d3b
parent59b3864bbd09e81df1a5934a02d8af7f4eec0b28 (diff)
Refresh nodes when they're read from the start.
This is necessary for top, for instance, which keeps some files open and re-reads them regularly. As an extra bonus we can drop the refresh hack. * procfs.c, procfs.h: Remove the refresh hack. (procfs_refresh): New function, invalidates the cached contents. * netfs.c (netfs_attempt_read, netfs_get_dirents): Call procfs_refresh when the read is from offset 0. * proclist.c (proclist_make_node): Remove the refresh hack. * dircat.c (dircat_make_node): Likewise. (dircat_get_contents): Use procfs_refresh to avoid keeping old data from the component nodes.
-rw-r--r--dircat.c5
-rw-r--r--netfs.c6
-rw-r--r--procfs.c19
-rw-r--r--procfs.h13
-rw-r--r--proclist.c1
5 files changed, 23 insertions, 21 deletions
diff --git a/dircat.c b/dircat.c
index d043486d..d24e8345 100644
--- a/dircat.c
+++ b/dircat.c
@@ -23,6 +23,9 @@ dircat_get_contents (void *hook, char **contents, ssize_t *contents_len)
char *subcon;
ssize_t sublen;
+ /* Make sure we're not getting some old stuff. */
+ procfs_refresh (dcn->dirs[i]);
+
err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen);
if (err)
{
@@ -83,8 +86,6 @@ dircat_make_node (struct node *const *dirs, int num_dirs)
.cleanup_contents = procfs_cleanup_contents_with_free,
.lookup = dircat_lookup,
.cleanup = dircat_cleanup,
- /* necessary so that it propagates to proclist */
- .enable_refresh_hack_and_break_readdir = 1,
};
struct dircat_node *dcn;
int i;
diff --git a/netfs.c b/netfs.c
index e41e0623..02a4bf54 100644
--- a/netfs.c
+++ b/netfs.c
@@ -57,6 +57,9 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np,
ssize_t contents_len;
error_t err;
+ if (offset == 0)
+ procfs_refresh (np);
+
err = procfs_get_contents (np, &contents, &contents_len);
if (err)
return err;
@@ -139,6 +142,9 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir,
char *contents;
ssize_t contents_len;
error_t err;
+
+ if (entry == 0)
+ procfs_refresh (dir);
err = procfs_get_contents (dir, &contents, &contents_len);
if (err)
diff --git a/procfs.c b/procfs.c
index 6d15e4fd..f7b28347 100644
--- a/procfs.c
+++ b/procfs.c
@@ -111,14 +111,6 @@ procfs_make_ino (struct node *np, const char *filename)
error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len)
{
- if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents)
- {
- if (np->nn->ops->cleanup_contents)
- np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents,
- np->nn->contents_len);
- np->nn->contents = NULL;
- }
-
if (! np->nn->contents && np->nn->ops->get_contents)
{
char *contents;
@@ -141,6 +133,14 @@ error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len)
return 0;
}
+void procfs_refresh (struct node *np)
+{
+ if (np->nn->contents && np->nn->ops->cleanup_contents)
+ np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len);
+
+ np->nn->contents = NULL;
+}
+
error_t procfs_lookup (struct node *np, const char *name, struct node **npp)
{
error_t err = ENOENT;
@@ -172,8 +172,7 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp)
void procfs_cleanup (struct node *np)
{
- if (np->nn->contents && np->nn->ops->cleanup_contents)
- np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len);
+ procfs_refresh (np);
if (np->nn->ops->cleanup)
np->nn->ops->cleanup (np->nn->hook);
diff --git a/procfs.h b/procfs.h
index e8ef18b3..a9665f97 100644
--- a/procfs.h
+++ b/procfs.h
@@ -32,14 +32,6 @@ struct procfs_node_ops
/* Destroy this node. */
void (*cleanup) (void *hook);
-
- /* FIXME: This is needed because the root node is persistent, and we
- want the list of processes to be updated. However, this means that
- readdir() on the root node runs the risk of returning incoherent
- results if done in multiple runs and processes are added/removed in
- the meantime. The right way to fix this is probably to add a
- getroot() user hook function to libnetfs. */
- int enable_refresh_hack_and_break_readdir;
};
/* These helper functions can be used as procfs_node_ops.cleanup_contents. */
@@ -71,6 +63,11 @@ void procfs_node_chtype (struct node *np, mode_t type);
corresponding child nodes. */
ino64_t procfs_make_ino (struct node *np, const char *filename);
+/* Forget the current cached contents for the node. This is done before reads
+ from offset 0, to ensure that the data are recent even for utilities such as
+ top which keep some nodes open. */
+void procfs_refresh (struct node *np);
+
error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len);
error_t procfs_lookup (struct node *np, const char *name, struct node **npp);
void procfs_cleanup (struct node *np);
diff --git a/proclist.c b/proclist.c
index 38368feb..fe5d0cff 100644
--- a/proclist.c
+++ b/proclist.c
@@ -69,7 +69,6 @@ proclist_make_node (struct ps_context *pc)
.get_contents = proclist_get_contents,
.lookup = proclist_lookup,
.cleanup_contents = procfs_cleanup_contents_with_free,
- .enable_refresh_hack_and_break_readdir = 1,
};
return procfs_make_node (&ops, pc);
}