From b3d304167929bc199e6789fd67ffea035e7fdbf1 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 20:43:16 +0000 Subject: 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. --- dircat.c | 5 +++-- netfs.c | 6 ++++++ procfs.c | 19 +++++++++---------- procfs.h | 13 +++++-------- proclist.c | 1 - 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/dircat.c b/dircat.c index d043486..d24e834 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 e41e062..02a4bf5 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 6d15e4f..f7b2834 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 e8ef18b..a9665f9 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 38368fe..fe5d0cf 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); } -- cgit v1.2.3