All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: Alexey Dobriyan <adobriyan@gmail.com>
Cc: dhowells@redhat.com, trond.myklebust@fys.uio.no,
	viro@ZenIV.linux.org.uk, nfsv4@linux-nfs.org,
	linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 11/45] FS-Cache: Add use of /proc and presentation of statistics [ver #41]
Date: Fri, 21 Nov 2008 15:32:16 +0000	[thread overview]
Message-ID: <15505.1227281536@redhat.com> (raw)
In-Reply-To: <20081121001539.GA5889@x200.localdomain>

Alexey Dobriyan <adobriyan@gmail.com> wrote:

> This is overly complex for unclear need. Just set_printf() all these lines
> and drop iterator business. Use single_open()! Ditto for histo stuff.

I disagree with respect to the histogram stuff.  The whole point of having
iterators is to iterate over a lot of things, and the histogram code may
generate several pages worth of data.

Anyway, I've sorted the stats and histogram code and documentation out for both
FS-Cache and CacheFiles and attached it here in one delta patch.  Could you
look it over and see what you think?  I'll merge it into the various patches
later.

David
---
diff --git a/Documentation/filesystems/caching/cachefiles.txt b/Documentation/filesystems/caching/cachefiles.txt
index ed5bb0c..c78a49b 100644
--- a/Documentation/filesystems/caching/cachefiles.txt
+++ b/Documentation/filesystems/caching/cachefiles.txt
@@ -22,6 +22,10 @@ Contents:
 
  (*) A note on security.
 
+ (*) Statistical information.
+
+ (*) Debugging.
+
 
 ========
 OVERVIEW
@@ -439,3 +443,59 @@ file.
 LSM hooks exist that allow SELinux (or Smack or whatever) to reject a request
 for CacheFiles to run in a context of a specific security label, or to create
 files and directories with another security label.
+
+
+=======================
+STATISTICAL INFORMATION
+=======================
+
+If FS-Cache is compiled with the following option enabled:
+
+	CONFIG_CACHEFILES_HISTOGRAM=y
+
+then it will gather certain statistics and display them through a proc file.
+
+ (*) /proc/fs/cachefiles/histogram
+
+	cat /proc/fs/cachefiles/histogram
+	JIFS  SECS  LOOKUPS   MKDIRS    CREATES
+	===== ===== ========= ========= =========
+
+     This shows the breakdown of the number of times each amount of time
+     between 0 jiffies and HZ-1 jiffies a variety of tasks took to run.  The
+     columns are as follows:
+
+	COLUMN		TIME MEASUREMENT
+	=======		=======================================================
+	LOOKUPS		Length of time to perform a lookup on the backing fs
+	MKDIRS		Length of time to perform a mkdir on the backing fs
+	CREATES		Length of time to perform a create on the backing fs
+
+     Each row shows the number of events that took a particular range of times.
+     Each step is 1 jiffy in size.  The JIFS column indicates the particular
+     jiffy range covered, and the SECS field the equivalent number of seconds.
+
+
+=========
+DEBUGGING
+=========
+
+If CONFIG_CACHEFILES_DEBUG is enabled, the CacheFiles facility can have runtime
+debugging enabled by adjusting the value in:
+
+	/sys/module/cachefiles/parameters/debug
+
+This is a bitmask of debugging streams to enable:
+
+	BIT	VALUE	STREAM				POINT
+	=======	=======	===============================	=======================
+	0	1	General				Function entry trace
+	1	2					Function exit trace
+	2	4					General
+
+The appropriate set of values should be OR'd together and the result written to
+the control file.  For example:
+
+	echo $((1|4|8)) >/sys/module/cachefiles/parameters/debug
+
+will turn on all function entry debugging.
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index 8ff2caa..9e94b94 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -200,7 +200,6 @@ STATISTICAL INFORMATION
 
 If FS-Cache is compiled with the following options enabled:
 
-	CONFIG_FSCACHE_PROC=y (implied by the following two)
 	CONFIG_FSCACHE_STATS=y
 	CONFIG_FSCACHE_HISTOGRAM=y
 
@@ -280,7 +279,7 @@ proc files.
  (*) /proc/fs/fscache/histogram
 
 	cat /proc/fs/fscache/histogram
-	+HZ   +TIME OBJ INST  OP RUNS   OBJ RUNS  RETRV DLY RETRIEVLS
+	JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS  RETRV DLY RETRIEVLS
 	===== ===== ========= ========= ========= ========= =========
 
      This shows the breakdown of the number of times each amount of time
@@ -296,16 +295,16 @@ proc files.
 	RETRIEVLS	Time between beginning and end of a retrieval
 
      Each row shows the number of events that took a particular range of times.
-     Each step is 1 jiffy in size.  The +HZ column indicates the particular
-     jiffy range covered, and the +TIME field the equivalent number of seconds.
+     Each step is 1 jiffy in size.  The JIFS column indicates the particular
+     jiffy range covered, and the SECS field the equivalent number of seconds.
 
 
 =========
 DEBUGGING
 =========
 
-The FS-Cache facility can have runtime debugging enabled by adjusting the value
-in:
+If CONFIG_FSCACHE_DEBUG is enabled, the FS-Cache facility can have runtime
+debugging enabled by adjusting the value in:
 
 	/sys/module/fscache/parameters/debug
 
@@ -332,4 +331,3 @@ the control file.  For example:
 	echo $((1|8|64)) >/sys/module/fscache/parameters/debug
 
 will turn on all function entry debugging.
-
diff --git a/fs/cachefiles/Kconfig b/fs/cachefiles/Kconfig
index ddbdd85..11f54c3 100644
--- a/fs/cachefiles/Kconfig
+++ b/fs/cachefiles/Kconfig
@@ -21,13 +21,19 @@ config CACHEFILES_DEBUG
 
 config CACHEFILES_HISTOGRAM
 	bool "Gather latency information on CacheFiles"
-	depends on CACHEFILES && FSCACHE_PROC
+	depends on CACHEFILES && PROC_FS
 	help
 
 	  This option causes latency information to be gathered on CacheFiles
 	  operation and exported through file:
 
-		/proc/fs/fscache/cachefiles/histogram
+		/proc/fs/cachefiles/histogram
+
+	  The generation of this histogram adds a certain amount of overhead to
+	  execution as there are a number of points at which data is gathered,
+	  and on a multi-CPU system these may be on cachelines that keep
+	  bouncing between CPUs.  On the other hand, the histogram may be
+	  useful for debugging purposes.  Saying 'N' here is recommended.
 
 	  See Documentation/filesystems/caching/cachefiles.txt for more
 	  information.
diff --git a/fs/cachefiles/cf-proc.c b/fs/cachefiles/cf-proc.c
index c0d5444..d09beb5 100644
--- a/fs/cachefiles/cf-proc.c
+++ b/fs/cachefiles/cf-proc.c
@@ -14,104 +14,47 @@
 #include <linux/seq_file.h>
 #include "cf-internal.h"
 
-struct cachefiles_proc {
-	unsigned			nlines;
-	const struct seq_operations	*ops;
-};
-
 atomic_t cachefiles_lookup_histogram[HZ];
 atomic_t cachefiles_mkdir_histogram[HZ];
 atomic_t cachefiles_create_histogram[HZ];
 
-static struct proc_dir_entry *proc_cachefiles;
-
-static int cachefiles_proc_open(struct inode *inode, struct file *file);
-static void *cachefiles_proc_start(struct seq_file *m, loff_t *pos);
-static void cachefiles_proc_stop(struct seq_file *m, void *v);
-static void *cachefiles_proc_next(struct seq_file *m, void *v, loff_t *pos);
-static int cachefiles_histogram_show(struct seq_file *m, void *v);
-
-static const struct file_operations cachefiles_proc_fops = {
-	.open		= cachefiles_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static const struct seq_operations cachefiles_histogram_ops = {
-	.start		= cachefiles_proc_start,
-	.stop		= cachefiles_proc_stop,
-	.next		= cachefiles_proc_next,
-	.show		= cachefiles_histogram_show,
-};
-
-static const struct cachefiles_proc cachefiles_histogram = {
-	.nlines		= HZ + 1,
-	.ops		= &cachefiles_histogram_ops,
-};
-
 /*
- * initialise the /proc/fs/fscache/cachefiles/ directory
+ * display the latency histogram
  */
-int __init cachefiles_proc_init(void)
+static int cachefiles_histogram_show(struct seq_file *m, void *v)
 {
-	struct proc_dir_entry *p;
-
-	_enter("");
-
-	proc_cachefiles = proc_mkdir("cachefiles", proc_fscache);
-	if (!proc_cachefiles)
-		goto error_dir;
-	proc_cachefiles->owner = THIS_MODULE;
-
-	p = create_proc_entry("histogram", 0, proc_cachefiles);
-	if (!p)
-		goto error_histogram;
-	p->proc_fops = &cachefiles_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &cachefiles_histogram;
-
-	_leave(" = 0");
-	return 0;
+	unsigned long index;
+	unsigned x, y, z, t;
 
-error_histogram:
-	remove_proc_entry("fs/cachefiles", NULL);
-error_dir:
-	_leave(" = -ENOMEM");
-	return -ENOMEM;
-}
+	switch ((unsigned long) v) {
+	case 1:
+		seq_puts(m, "JIFS  SECS  LOOKUPS   MKDIRS    CREATES\n");
+		return 0;
+	case 2:
+		seq_puts(m, "===== ===== ========= ========= =========\n");
+		return 0;
+	default:
+		index = (unsigned long) v - 3;
+		x = atomic_read(&cachefiles_lookup_histogram[index]);
+		y = atomic_read(&cachefiles_mkdir_histogram[index]);
+		z = atomic_read(&cachefiles_create_histogram[index]);
+		if (x == 0 && y == 0 && z == 0)
+			return 0;
 
-/*
- * clean up the /proc/fs/fscache/cachefiles/ directory
- */
-void cachefiles_proc_cleanup(void)
-{
-	remove_proc_entry("histogram", proc_cachefiles);
-	remove_proc_entry("cachefiles", proc_fscache);
-}
+		t = (index * 1000) / HZ;
 
-/*
- * open "/proc/fs/fscache/cachefiles/XXX" which provide statistics summaries
- */
-static int cachefiles_proc_open(struct inode *inode, struct file *file)
-{
-	const struct cachefiles_proc *proc = PDE(inode)->data;
-	struct seq_file *m;
-	int ret;
-
-	ret = seq_open(file, proc->ops);
-	if (ret == 0) {
-		m = file->private_data;
-		m->private = (void *) proc;
+		seq_printf(m, "%4lu  0.%03u %9u %9u %9u\n", index, t, x, y, z);
+		return 0;
 	}
-	return ret;
 }
 
 /*
  * set up the iterator to start reading from the first line
  */
-static void *cachefiles_proc_start(struct seq_file *m, loff_t *_pos)
+static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
 {
+	if ((unsigned long long)*_pos >= HZ + 2)
+		return NULL;
 	if (*_pos == 0)
 		*_pos = 1;
 	return (void *)(unsigned long) *_pos;
@@ -120,47 +63,72 @@ static void *cachefiles_proc_start(struct seq_file *m, loff_t *_pos)
 /*
  * move to the next line
  */
-static void *cachefiles_proc_next(struct seq_file *m, void *v, loff_t *pos)
+static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	const struct cachefiles_proc *proc = m->private;
-
 	(*pos)++;
-	return *pos > proc->nlines ? NULL : (void *)(unsigned long) *pos;
+	return (unsigned long long)*pos > HZ + 2 ?
+		NULL : (void *)(unsigned long) *pos;
 }
 
 /*
  * clean up after reading
  */
-static void cachefiles_proc_stop(struct seq_file *m, void *v)
+static void cachefiles_histogram_stop(struct seq_file *m, void *v)
 {
 }
 
+static const struct seq_operations cachefiles_histogram_ops = {
+	.start		= cachefiles_histogram_start,
+	.stop		= cachefiles_histogram_stop,
+	.next		= cachefiles_histogram_next,
+	.show		= cachefiles_histogram_show,
+};
+
 /*
- * display the time-taken histogram
+ * open "/proc/fs/cachefiles/XXX" which provide statistics summaries
  */
-static int cachefiles_histogram_show(struct seq_file *m, void *v)
+static int cachefiles_histogram_open(struct inode *inode, struct file *file)
 {
-	unsigned long index;
-	unsigned x, y, z, t;
+	return seq_open(file, &cachefiles_histogram_ops);
+}
 
-	switch ((unsigned long) v) {
-	case 1:
-		seq_puts(m, "JIFS  SECS  LOOKUPS   MKDIRS    CREATES\n");
-		return 0;
-	case 2:
-		seq_puts(m, "===== ===== ========= ========= =========\n");
-		return 0;
-	default:
-		index = (unsigned long) v - 3;
-		x = atomic_read(&cachefiles_lookup_histogram[index]);
-		y = atomic_read(&cachefiles_mkdir_histogram[index]);
-		z = atomic_read(&cachefiles_create_histogram[index]);
-		if (x == 0 && y == 0 && z == 0)
-			return 0;
+static const struct file_operations cachefiles_histogram_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cachefiles_histogram_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
-		t = (index * 1000) / HZ;
+/*
+ * initialise the /proc/fs/cachefiles/ directory
+ */
+int __init cachefiles_proc_init(void)
+{
+	_enter("");
 
-		seq_printf(m, "%4lu  0.%03u %9u %9u %9u\n", index, t, x, y, z);
-		return 0;
-	}
+	if (!proc_mkdir("fs/cachefiles", NULL))
+		goto error_dir;
+
+	if (!proc_create("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
+			 &cachefiles_histogram_fops))
+		goto error_histogram;
+
+	_leave(" = 0");
+	return 0;
+
+error_histogram:
+	remove_proc_entry("fs/cachefiles", NULL);
+error_dir:
+	_leave(" = -ENOMEM");
+	return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/cachefiles/ directory
+ */
+void cachefiles_proc_cleanup(void)
+{
+	remove_proc_entry("fs/cachefiles/histogram", NULL);
+	remove_proc_entry("fs/cachefiles", NULL);
 }
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig
index b9ff04a..9bbb8ce 100644
--- a/fs/fscache/Kconfig
+++ b/fs/fscache/Kconfig
@@ -11,31 +11,38 @@ config FSCACHE
 
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
-config FSCACHE_PROC
-	bool "Provide /proc interface for local caching statistics"
-	depends on FSCACHE && PROC_FS
-
 config FSCACHE_STATS
 	bool "Gather statistical information on local caching"
-	depends on FSCACHE_PROC
+	depends on FSCACHE && PROC_FS
 	help
 	  This option causes statistical information to be gathered on local
 	  caching and exported through file:
 
 		/proc/fs/fscache/stats
 
+	  The gathering of statistics adds a certain amount of overhead to
+	  execution as there are a quite a few stats gathered, and on a
+	  multi-CPU system these may be on cachelines that keep bouncing
+	  between CPUs.  On the other hand, the stats are very useful for
+	  debugging purposes.  Saying 'Y' here is recommended.
+
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
 config FSCACHE_HISTOGRAM
 	bool "Gather latency information on local caching"
-	depends on FSCACHE_PROC
+	depends on FSCACHE && PROC_FS
 	help
-
 	  This option causes latency information to be gathered on local
 	  caching and exported through file:
 
 		/proc/fs/fscache/histogram
 
+	  The generation of this histogram adds a certain amount of overhead to
+	  execution as there are a number of points at which data is gathered,
+	  and on a multi-CPU system these may be on cachelines that keep
+	  bouncing between CPUs.  On the other hand, the histogram may be
+	  useful for debugging purposes.  Saying 'N' here is recommended.
+
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
 config FSCACHE_DEBUG
diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile
index 572b012..3f6a198 100644
--- a/fs/fscache/Makefile
+++ b/fs/fscache/Makefile
@@ -10,8 +10,10 @@ fscache-y := \
 	fsc-netfs.o \
 	fsc-object.o \
 	fsc-operation.o \
-	fsc-page.o \
-	fsc-proc.o \
-	fsc-stats.o
+	fsc-page.o
+
+fscache-$(CONFIG_PROC_FS) += fsc-proc.o
+fscache-$(CONFIG_FSCACHE_STATS) += fsc-stats.o
+fscache-$(CONFIG_FSCACHE_HISTOGRAM) += fsc-histogram.o
 
 obj-$(CONFIG_FSCACHE) := fscache.o
diff --git a/fs/fscache/fsc-histogram.c b/fs/fscache/fsc-histogram.c
new file mode 100644
index 0000000..d1cbbc3
--- /dev/null
+++ b/fs/fscache/fsc-histogram.c
@@ -0,0 +1,109 @@
+/* FS-Cache latency histogram
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define FSCACHE_DEBUG_LEVEL THREAD
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include "fsc-internal.h"
+
+atomic_t fscache_obj_instantiate_histogram[HZ];
+atomic_t fscache_objs_histogram[HZ];
+atomic_t fscache_ops_histogram[HZ];
+atomic_t fscache_retrieval_delay_histogram[HZ];
+atomic_t fscache_retrieval_histogram[HZ];
+
+/*
+ * display the time-taken histogram
+ */
+static int fscache_histogram_show(struct seq_file *m, void *v)
+{
+	unsigned long index;
+	unsigned n[5], t;
+
+	switch ((unsigned long) v) {
+	case 1:
+		seq_puts(m, "JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS "
+			 " RETRV DLY RETRIEVLS\n");
+		return 0;
+	case 2:
+		seq_puts(m, "===== ===== ========= ========= ========="
+			 " ========= =========\n");
+		return 0;
+	default:
+		index = (unsigned long) v - 3;
+		n[0] = atomic_read(&fscache_obj_instantiate_histogram[index]);
+		n[1] = atomic_read(&fscache_ops_histogram[index]);
+		n[2] = atomic_read(&fscache_objs_histogram[index]);
+		n[3] = atomic_read(&fscache_retrieval_delay_histogram[index]);
+		n[4] = atomic_read(&fscache_retrieval_histogram[index]);
+		if (!(n[0] | n[1] | n[2] | n[3] | n[4]))
+			return 0;
+
+		t = (index * 1000) / HZ;
+
+		seq_printf(m, "%4lu  0.%03u %9u %9u %9u %9u %9u\n",
+			   index, t, n[0], n[1], n[2], n[3], n[4]);
+		return 0;
+	}
+}
+
+/*
+ * set up the iterator to start reading from the first line
+ */
+static void *fscache_histogram_start(struct seq_file *m, loff_t *_pos)
+{
+	if ((unsigned long long)*_pos >= HZ + 2)
+		return NULL;
+	if (*_pos == 0)
+		*_pos = 1;
+	return (void *)(unsigned long) *_pos;
+}
+
+/*
+ * move to the next line
+ */
+static void *fscache_histogram_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return (unsigned long long)*pos > HZ + 2 ?
+		NULL : (void *)(unsigned long) *pos;
+}
+
+/*
+ * clean up after reading
+ */
+static void fscache_histogram_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations fscache_histogram_ops = {
+	.start		= fscache_histogram_start,
+	.stop		= fscache_histogram_stop,
+	.next		= fscache_histogram_next,
+	.show		= fscache_histogram_show,
+};
+
+/*
+ * open "/proc/fs/fscache/histogram" to provide latency data
+ */
+static int fscache_histogram_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &fscache_histogram_ops);
+}
+
+const struct file_operations fscache_histogram_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fscache_histogram_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
diff --git a/fs/fscache/fsc-internal.h b/fs/fscache/fsc-internal.h
index f2ff86b..e5eb297 100644
--- a/fs/fscache/fsc-internal.h
+++ b/fs/fscache/fsc-internal.h
@@ -51,6 +51,30 @@ extern struct fscache_cookie fscache_fsdef_index;
 extern struct fscache_cookie_def fscache_fsdef_netfs_def;
 
 /*
+ * fsc-histogram.c
+ */
+#ifdef CONFIG_FSCACHE_HISTOGRAM
+extern atomic_t fscache_obj_instantiate_histogram[HZ];
+extern atomic_t fscache_objs_histogram[HZ];
+extern atomic_t fscache_ops_histogram[HZ];
+extern atomic_t fscache_retrieval_delay_histogram[HZ];
+extern atomic_t fscache_retrieval_histogram[HZ];
+
+static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif)
+{
+	unsigned long jif = jiffies - start_jif;
+	if (jif >= HZ)
+		jif = HZ - 1;
+	atomic_inc(&histogram[jif]);
+}
+
+extern const struct file_operations fscache_histogram_fops;
+
+#else
+#define fscache_hist(hist, start_jif) do {} while (0)
+#endif
+
+/*
  * fsc-main.c
  */
 extern unsigned fscache_defer_lookup;
@@ -80,6 +104,17 @@ extern void fscache_start_operations(struct fscache_object *);
 extern void fscache_operation_gc(struct work_struct *);
 
 /*
+ * fsc-proc.c
+ */
+#ifdef CONFIG_PROC_FS
+extern int __init fscache_proc_init(void);
+extern void fscache_proc_cleanup(void);
+#else
+#define fscache_proc_init()	(0)
+#define fscache_proc_cleanup()	do {} while (0)
+#endif
+
+/*
  * fsc-stats.c
  */
 #ifdef CONFIG_FSCACHE_STATS
@@ -164,36 +199,11 @@ static inline void fscache_stat(atomic_t *stat)
 {
 	atomic_inc(stat);
 }
-#else
-
-#define fscache_stat(stat) do {} while (0)
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-extern atomic_t fscache_obj_instantiate_histogram[HZ];
-extern atomic_t fscache_objs_histogram[HZ];
-extern atomic_t fscache_ops_histogram[HZ];
-extern atomic_t fscache_retrieval_delay_histogram[HZ];
-extern atomic_t fscache_retrieval_histogram[HZ];
-
-static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif)
-{
-	unsigned long jif = jiffies - start_jif;
-	if (jif >= HZ)
-		jif = HZ - 1;
-	atomic_inc(&histogram[jif]);
-}
 
+extern const struct file_operations fscache_stats_fops;
 #else
-#define fscache_hist(hist, start_jif) do {} while (0)
-#endif
 
-#ifdef CONFIG_FSCACHE_PROC
-extern int __init fscache_proc_init(void);
-extern void fscache_proc_cleanup(void);
-#else
-#define fscache_proc_init()	(0)
-#define fscache_proc_cleanup()	do {} while (0)
+#define fscache_stat(stat) do {} while (0)
 #endif
 
 /*
diff --git a/fs/fscache/fsc-proc.c b/fs/fscache/fsc-proc.c
index dd6daa5..2f549f3 100644
--- a/fs/fscache/fsc-proc.c
+++ b/fs/fscache/fsc-proc.c
@@ -15,94 +15,26 @@
 #include <linux/seq_file.h>
 #include "fsc-internal.h"
 
-struct fscache_proc {
-	unsigned			nlines;
-	const struct seq_operations	*ops;
-};
-
-struct proc_dir_entry *proc_fscache;
-EXPORT_SYMBOL(proc_fscache);
-
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-static int fscache_proc_open(struct inode *inode, struct file *file);
-static void *fscache_proc_start(struct seq_file *m, loff_t *pos);
-static void fscache_proc_stop(struct seq_file *m, void *v);
-static void *fscache_proc_next(struct seq_file *m, void *v, loff_t *pos);
-
-static const struct file_operations fscache_proc_fops = {
-	.open		= fscache_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-#endif
-
-#ifdef CONFIG_FSCACHE_STATS
-static int fscache_stats_show(struct seq_file *m, void *v);
-
-static const struct seq_operations fscache_stats_ops = {
-	.start		= fscache_proc_start,
-	.stop		= fscache_proc_stop,
-	.next		= fscache_proc_next,
-	.show		= fscache_stats_show,
-};
-
-static const struct fscache_proc fscache_stats = {
-	.nlines		= 17,
-	.ops		= &fscache_stats_ops,
-};
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-static int fscache_histogram_show(struct seq_file *m, void *v);
-
-static const struct seq_operations fscache_histogram_ops = {
-	.start		= fscache_proc_start,
-	.stop		= fscache_proc_stop,
-	.next		= fscache_proc_next,
-	.show		= fscache_histogram_show,
-};
-
-static const struct fscache_proc fscache_histogram = {
-	.nlines		= HZ + 1,
-	.ops		= &fscache_histogram_ops,
-};
-#endif
-
-#define FSC_DESC(SELECT, N) ((void *) (unsigned long) (((SELECT) << 16) | (N)))
-
 /*
  * initialise the /proc/fs/fscache/ directory
  */
 int __init fscache_proc_init(void)
 {
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-	struct proc_dir_entry *p;
-#endif
-
 	_enter("");
 
-	proc_fscache = proc_mkdir("fs/fscache", NULL);
-	if (!proc_fscache)
+	if (!proc_mkdir("fs/fscache", NULL))
 		goto error_dir;
-	proc_fscache->owner = THIS_MODULE;
 
 #ifdef CONFIG_FSCACHE_STATS
-	p = create_proc_entry("stats", 0, proc_fscache);
-	if (!p)
+	if (!proc_create("fs/fscache/stats", S_IFREG | 0444, NULL,
+			 &fscache_stats_fops))
 		goto error_stats;
-	p->proc_fops = &fscache_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &fscache_stats;
 #endif
 
 #ifdef CONFIG_FSCACHE_HISTOGRAM
-	p = create_proc_entry("histogram", 0, proc_fscache);
-	if (!p)
+	if (!proc_create("fs/fscache/histogram", S_IFREG | 0444, NULL,
+			 &fscache_histogram_fops))
 		goto error_histogram;
-	p->proc_fops = &fscache_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &fscache_histogram;
 #endif
 
 	_leave(" = 0");
@@ -112,7 +44,7 @@ int __init fscache_proc_init(void)
 error_histogram:
 #endif
 #ifdef CONFIG_FSCACHE_STATS
-	remove_proc_entry("stats", proc_fscache);
+	remove_proc_entry("fs/fscache/stats", NULL);
 error_stats:
 #endif
 	remove_proc_entry("fs/fscache", NULL);
@@ -127,244 +59,10 @@ error_dir:
 void fscache_proc_cleanup(void)
 {
 #ifdef CONFIG_FSCACHE_HISTOGRAM
-	remove_proc_entry("histogram", proc_fscache);
+	remove_proc_entry("fs/fscache/histogram", NULL);
 #endif
 #ifdef CONFIG_FSCACHE_STATS
-	remove_proc_entry("stats", proc_fscache);
+	remove_proc_entry("fs/fscache/stats", NULL);
 #endif
 	remove_proc_entry("fs/fscache", NULL);
 }
-
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-/*
- * open "/proc/fs/fscache/XXX" which provide statistics summaries
- */
-static int fscache_proc_open(struct inode *inode, struct file *file)
-{
-	const struct fscache_proc *proc = PDE(inode)->data;
-	struct seq_file *m;
-	int ret;
-
-	ret = seq_open(file, proc->ops);
-	if (ret == 0) {
-		m = file->private_data;
-		m->private = (void *) proc;
-	}
-	return ret;
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *fscache_proc_start(struct seq_file *m, loff_t *_pos)
-{
-	if (*_pos == 0)
-		*_pos = 1;
-	return (void *)(unsigned long) *_pos;
-}
-
-/*
- * move to the next line
- */
-static void *fscache_proc_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	const struct fscache_proc *proc = m->private;
-
-	(*pos)++;
-	return *pos > proc->nlines ? NULL : (void *)(unsigned long) *pos;
-}
-
-/*
- * clean up after reading
- */
-static void fscache_proc_stop(struct seq_file *m, void *v)
-{
-}
-#endif
-
-#ifdef CONFIG_FSCACHE_STATS
-/*
- * display the general statistics
- */
-static int fscache_stats_show(struct seq_file *m, void *v)
-{
-	unsigned long line = (unsigned long) v;
-
-	switch (line) {
-	case 1:
-		seq_puts(m, "FS-Cache statistics\n");
-		break;
-
-	case 2:
-		seq_printf(m, "Cookies: idx=%u dat=%u spc=%u\n",
-			   atomic_read(&fscache_n_cookie_index),
-			   atomic_read(&fscache_n_cookie_data),
-			   atomic_read(&fscache_n_cookie_special));
-		break;
-
-	case 3:
-		seq_printf(m, "Objects: alc=%u nal=%u avl=%u ded=%u\n",
-			   atomic_read(&fscache_n_object_alloc),
-			   atomic_read(&fscache_n_object_no_alloc),
-			   atomic_read(&fscache_n_object_avail),
-			   atomic_read(&fscache_n_object_dead));
-		break;
-
-	case 4:
-		seq_printf(m, "ChkAux : non=%u ok=%u upd=%u obs=%u\n",
-			   atomic_read(&fscache_n_checkaux_none),
-			   atomic_read(&fscache_n_checkaux_okay),
-			   atomic_read(&fscache_n_checkaux_update),
-			   atomic_read(&fscache_n_checkaux_obsolete));
-		break;
-
-	case 5:
-		seq_printf(m, "Pages  : mrk=%u unc=%u\n",
-			   atomic_read(&fscache_n_marks),
-			   atomic_read(&fscache_n_uncaches));
-		break;
-
-	case 6:
-		seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u"
-			   " oom=%u\n",
-			   atomic_read(&fscache_n_acquires),
-			   atomic_read(&fscache_n_acquires_null),
-			   atomic_read(&fscache_n_acquires_no_cache),
-			   atomic_read(&fscache_n_acquires_ok),
-			   atomic_read(&fscache_n_acquires_nobufs),
-			   atomic_read(&fscache_n_acquires_oom));
-		break;
-
-	case 7:
-		seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n",
-			   atomic_read(&fscache_n_object_lookups),
-			   atomic_read(&fscache_n_object_lookups_negative),
-			   atomic_read(&fscache_n_object_lookups_positive),
-			   atomic_read(&fscache_n_object_created));
-		break;
-
-	case 8:
-		seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
-			   atomic_read(&fscache_n_updates),
-			   atomic_read(&fscache_n_updates_null),
-			   atomic_read(&fscache_n_updates_run));
-		break;
-
-	case 9:
-		seq_printf(m, "Relinqs: n=%u nul=%u wcr=%u\n",
-			   atomic_read(&fscache_n_relinquishes),
-			   atomic_read(&fscache_n_relinquishes_null),
-			   atomic_read(&fscache_n_relinquishes_waitcrt));
-		break;
-
-	case 10:
-		seq_printf(m, "AttrChg: n=%u ok=%u nbf=%u oom=%u run=%u\n",
-			   atomic_read(&fscache_n_attr_changed),
-			   atomic_read(&fscache_n_attr_changed_ok),
-			   atomic_read(&fscache_n_attr_changed_nobufs),
-			   atomic_read(&fscache_n_attr_changed_nomem),
-			   atomic_read(&fscache_n_attr_changed_calls));
-		break;
-
-	case 11:
-		seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u\n",
-			   atomic_read(&fscache_n_allocs),
-			   atomic_read(&fscache_n_allocs_ok),
-			   atomic_read(&fscache_n_allocs_wait),
-			   atomic_read(&fscache_n_allocs_nobufs));
-		break;
-	case 12:
-		seq_printf(m, "Allocs : ops=%u owt=%u\n",
-			   atomic_read(&fscache_n_alloc_ops),
-			   atomic_read(&fscache_n_alloc_op_waits));
-		break;
-
-	case 13:
-		seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u"
-			   " int=%u oom=%u\n",
-			   atomic_read(&fscache_n_retrievals),
-			   atomic_read(&fscache_n_retrievals_ok),
-			   atomic_read(&fscache_n_retrievals_wait),
-			   atomic_read(&fscache_n_retrievals_nodata),
-			   atomic_read(&fscache_n_retrievals_nobufs),
-			   atomic_read(&fscache_n_retrievals_intr),
-			   atomic_read(&fscache_n_retrievals_nomem));
-		break;
-	case 14:
-		seq_printf(m, "Retrvls: ops=%u owt=%u\n",
-			   atomic_read(&fscache_n_retrieval_ops),
-			   atomic_read(&fscache_n_retrieval_op_waits));
-		break;
-
-	case 15:
-		seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n",
-			   atomic_read(&fscache_n_stores),
-			   atomic_read(&fscache_n_stores_ok),
-			   atomic_read(&fscache_n_stores_again),
-			   atomic_read(&fscache_n_stores_nobufs),
-			   atomic_read(&fscache_n_stores_oom));
-		break;
-	case 16:
-		seq_printf(m, "Stores : ops=%u run=%u\n",
-			   atomic_read(&fscache_n_store_ops),
-			   atomic_read(&fscache_n_store_calls));
-		break;
-
-	case 17:
-		seq_printf(m, "Ops    : pend=%u run=%u enq=%u\n",
-			   atomic_read(&fscache_n_op_pend),
-			   atomic_read(&fscache_n_op_run),
-			   atomic_read(&fscache_n_op_enqueue));
-		break;
-
-	case 18:
-		seq_printf(m, "Ops    : dfr=%u rel=%u gc=%u\n",
-			   atomic_read(&fscache_n_op_deferred_release),
-			   atomic_read(&fscache_n_op_release),
-			   atomic_read(&fscache_n_op_gc));
-		break;
-
-	default:
-		break;
-	}
-	return 0;
-}
-
-#endif /* end CONFIG_FSCACHE_STATS */
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-/*
- * display the time-taken histogram
- */
-static int fscache_histogram_show(struct seq_file *m, void *v)
-{
-	unsigned long index;
-	unsigned n[5], t;
-
-	switch ((unsigned long) v) {
-	case 1:
-		seq_puts(m, "JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS "
-			 " RETRV DLY RETRIEVLS\n");
-		return 0;
-	case 2:
-		seq_puts(m, "===== ===== ========= ========= ========="
-			 " ========= =========\n");
-		return 0;
-	default:
-		index = (unsigned long) v - 3;
-		n[0] = atomic_read(&fscache_obj_instantiate_histogram[index]);
-		n[1] = atomic_read(&fscache_ops_histogram[index]);
-		n[2] = atomic_read(&fscache_objs_histogram[index]);
-		n[3] = atomic_read(&fscache_retrieval_delay_histogram[index]);
-		n[4] = atomic_read(&fscache_retrieval_histogram[index]);
-		if (!(n[0] | n[1] | n[2] | n[3] | n[4]))
-			return 0;
-
-		t = (index * 1000) / HZ;
-
-		seq_printf(m, "%4lu  0.%03u %9u %9u %9u %9u %9u\n",
-			   index, t, n[0], n[1], n[2], n[3], n[4]);
-		return 0;
-	}
-}
-#endif /* end CONFIG_FSCACHE_HISTOGRAM */
diff --git a/fs/fscache/fsc-stats.c b/fs/fscache/fsc-stats.c
index 8762d43..93ffc8f 100644
--- a/fs/fscache/fsc-stats.c
+++ b/fs/fscache/fsc-stats.c
@@ -18,7 +18,6 @@
 /*
  * operation counters
  */
-#ifdef CONFIG_FSCACHE_STATS
 atomic_t fscache_n_op_pend;
 atomic_t fscache_n_op_run;
 atomic_t fscache_n_op_enqueue;
@@ -93,12 +92,121 @@ atomic_t fscache_n_checkaux_none;
 atomic_t fscache_n_checkaux_okay;
 atomic_t fscache_n_checkaux_update;
 atomic_t fscache_n_checkaux_obsolete;
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-atomic_t fscache_obj_instantiate_histogram[HZ];
-atomic_t fscache_objs_histogram[HZ];
-atomic_t fscache_ops_histogram[HZ];
-atomic_t fscache_retrieval_delay_histogram[HZ];
-atomic_t fscache_retrieval_histogram[HZ];
-#endif
+
+/*
+ * display the general statistics
+ */
+static int fscache_stats_show(struct seq_file *m, void *v)
+{
+	seq_puts(m, "FS-Cache statistics\n");
+
+	seq_printf(m, "Cookies: idx=%u dat=%u spc=%u\n",
+		   atomic_read(&fscache_n_cookie_index),
+		   atomic_read(&fscache_n_cookie_data),
+		   atomic_read(&fscache_n_cookie_special));
+
+	seq_printf(m, "Objects: alc=%u nal=%u avl=%u ded=%u\n",
+		   atomic_read(&fscache_n_object_alloc),
+		   atomic_read(&fscache_n_object_no_alloc),
+		   atomic_read(&fscache_n_object_avail),
+		   atomic_read(&fscache_n_object_dead));
+	seq_printf(m, "ChkAux : non=%u ok=%u upd=%u obs=%u\n",
+		   atomic_read(&fscache_n_checkaux_none),
+		   atomic_read(&fscache_n_checkaux_okay),
+		   atomic_read(&fscache_n_checkaux_update),
+		   atomic_read(&fscache_n_checkaux_obsolete));
+
+	seq_printf(m, "Pages  : mrk=%u unc=%u\n",
+		   atomic_read(&fscache_n_marks),
+		   atomic_read(&fscache_n_uncaches));
+
+	seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u"
+		   " oom=%u\n",
+		   atomic_read(&fscache_n_acquires),
+		   atomic_read(&fscache_n_acquires_null),
+		   atomic_read(&fscache_n_acquires_no_cache),
+		   atomic_read(&fscache_n_acquires_ok),
+		   atomic_read(&fscache_n_acquires_nobufs),
+		   atomic_read(&fscache_n_acquires_oom));
+
+	seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n",
+		   atomic_read(&fscache_n_object_lookups),
+		   atomic_read(&fscache_n_object_lookups_negative),
+		   atomic_read(&fscache_n_object_lookups_positive),
+		   atomic_read(&fscache_n_object_created));
+
+	seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
+		   atomic_read(&fscache_n_updates),
+		   atomic_read(&fscache_n_updates_null),
+		   atomic_read(&fscache_n_updates_run));
+
+	seq_printf(m, "Relinqs: n=%u nul=%u wcr=%u\n",
+		   atomic_read(&fscache_n_relinquishes),
+		   atomic_read(&fscache_n_relinquishes_null),
+		   atomic_read(&fscache_n_relinquishes_waitcrt));
+
+	seq_printf(m, "AttrChg: n=%u ok=%u nbf=%u oom=%u run=%u\n",
+		   atomic_read(&fscache_n_attr_changed),
+		   atomic_read(&fscache_n_attr_changed_ok),
+		   atomic_read(&fscache_n_attr_changed_nobufs),
+		   atomic_read(&fscache_n_attr_changed_nomem),
+		   atomic_read(&fscache_n_attr_changed_calls));
+
+	seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u\n",
+		   atomic_read(&fscache_n_allocs),
+		   atomic_read(&fscache_n_allocs_ok),
+		   atomic_read(&fscache_n_allocs_wait),
+		   atomic_read(&fscache_n_allocs_nobufs));
+	seq_printf(m, "Allocs : ops=%u owt=%u\n",
+		   atomic_read(&fscache_n_alloc_ops),
+		   atomic_read(&fscache_n_alloc_op_waits));
+
+	seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u"
+		   " int=%u oom=%u\n",
+		   atomic_read(&fscache_n_retrievals),
+		   atomic_read(&fscache_n_retrievals_ok),
+		   atomic_read(&fscache_n_retrievals_wait),
+		   atomic_read(&fscache_n_retrievals_nodata),
+		   atomic_read(&fscache_n_retrievals_nobufs),
+		   atomic_read(&fscache_n_retrievals_intr),
+		   atomic_read(&fscache_n_retrievals_nomem));
+	seq_printf(m, "Retrvls: ops=%u owt=%u\n",
+		   atomic_read(&fscache_n_retrieval_ops),
+		   atomic_read(&fscache_n_retrieval_op_waits));
+
+	seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n",
+		   atomic_read(&fscache_n_stores),
+		   atomic_read(&fscache_n_stores_ok),
+		   atomic_read(&fscache_n_stores_again),
+		   atomic_read(&fscache_n_stores_nobufs),
+		   atomic_read(&fscache_n_stores_oom));
+	seq_printf(m, "Stores : ops=%u run=%u\n",
+		   atomic_read(&fscache_n_store_ops),
+		   atomic_read(&fscache_n_store_calls));
+
+	seq_printf(m, "Ops    : pend=%u run=%u enq=%u\n",
+		   atomic_read(&fscache_n_op_pend),
+		   atomic_read(&fscache_n_op_run),
+		   atomic_read(&fscache_n_op_enqueue));
+	seq_printf(m, "Ops    : dfr=%u rel=%u gc=%u\n",
+		   atomic_read(&fscache_n_op_deferred_release),
+		   atomic_read(&fscache_n_op_release),
+		   atomic_read(&fscache_n_op_gc));
+	return 0;
+}
+
+/*
+ * open "/proc/fs/fscache/stats" allowing provision of a statistical summary
+ */
+static int fscache_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fscache_stats_show, NULL);
+}
+
+const struct file_operations fscache_stats_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fscache_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index a31f4c1..0410bd9 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -29,10 +29,6 @@ struct fscache_cache_ops;
 struct fscache_object;
 struct fscache_operation;
 
-#ifdef CONFIG_FSCACHE_PROC
-extern struct proc_dir_entry *proc_fscache;
-#endif
-
 /*
  * cache tag definition
  */


WARNING: multiple messages have this Message-ID (diff)
From: David Howells <dhowells@redhat.com>
To: Alexey Dobriyan <adobriyan@gmail.com>
Cc: nfsv4@linux-nfs.org, linux-kernel@vger.kernel.org,
	dhowells@redhat.com, viro@ZenIV.linux.org.uk,
	linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 11/45] FS-Cache: Add use of /proc and presentation of statistics [ver #41]
Date: Fri, 21 Nov 2008 15:32:16 +0000	[thread overview]
Message-ID: <15505.1227281536@redhat.com> (raw)
In-Reply-To: <20081121001539.GA5889@x200.localdomain>

Alexey Dobriyan <adobriyan@gmail.com> wrote:

> This is overly complex for unclear need. Just set_printf() all these lines
> and drop iterator business. Use single_open()! Ditto for histo stuff.

I disagree with respect to the histogram stuff.  The whole point of having
iterators is to iterate over a lot of things, and the histogram code may
generate several pages worth of data.

Anyway, I've sorted the stats and histogram code and documentation out for both
FS-Cache and CacheFiles and attached it here in one delta patch.  Could you
look it over and see what you think?  I'll merge it into the various patches
later.

David
---
diff --git a/Documentation/filesystems/caching/cachefiles.txt b/Documentation/filesystems/caching/cachefiles.txt
index ed5bb0c..c78a49b 100644
--- a/Documentation/filesystems/caching/cachefiles.txt
+++ b/Documentation/filesystems/caching/cachefiles.txt
@@ -22,6 +22,10 @@ Contents:
 
  (*) A note on security.
 
+ (*) Statistical information.
+
+ (*) Debugging.
+
 
 ========
 OVERVIEW
@@ -439,3 +443,59 @@ file.
 LSM hooks exist that allow SELinux (or Smack or whatever) to reject a request
 for CacheFiles to run in a context of a specific security label, or to create
 files and directories with another security label.
+
+
+=======================
+STATISTICAL INFORMATION
+=======================
+
+If FS-Cache is compiled with the following option enabled:
+
+	CONFIG_CACHEFILES_HISTOGRAM=y
+
+then it will gather certain statistics and display them through a proc file.
+
+ (*) /proc/fs/cachefiles/histogram
+
+	cat /proc/fs/cachefiles/histogram
+	JIFS  SECS  LOOKUPS   MKDIRS    CREATES
+	===== ===== ========= ========= =========
+
+     This shows the breakdown of the number of times each amount of time
+     between 0 jiffies and HZ-1 jiffies a variety of tasks took to run.  The
+     columns are as follows:
+
+	COLUMN		TIME MEASUREMENT
+	=======		=======================================================
+	LOOKUPS		Length of time to perform a lookup on the backing fs
+	MKDIRS		Length of time to perform a mkdir on the backing fs
+	CREATES		Length of time to perform a create on the backing fs
+
+     Each row shows the number of events that took a particular range of times.
+     Each step is 1 jiffy in size.  The JIFS column indicates the particular
+     jiffy range covered, and the SECS field the equivalent number of seconds.
+
+
+=========
+DEBUGGING
+=========
+
+If CONFIG_CACHEFILES_DEBUG is enabled, the CacheFiles facility can have runtime
+debugging enabled by adjusting the value in:
+
+	/sys/module/cachefiles/parameters/debug
+
+This is a bitmask of debugging streams to enable:
+
+	BIT	VALUE	STREAM				POINT
+	=======	=======	===============================	=======================
+	0	1	General				Function entry trace
+	1	2					Function exit trace
+	2	4					General
+
+The appropriate set of values should be OR'd together and the result written to
+the control file.  For example:
+
+	echo $((1|4|8)) >/sys/module/cachefiles/parameters/debug
+
+will turn on all function entry debugging.
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index 8ff2caa..9e94b94 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -200,7 +200,6 @@ STATISTICAL INFORMATION
 
 If FS-Cache is compiled with the following options enabled:
 
-	CONFIG_FSCACHE_PROC=y (implied by the following two)
 	CONFIG_FSCACHE_STATS=y
 	CONFIG_FSCACHE_HISTOGRAM=y
 
@@ -280,7 +279,7 @@ proc files.
  (*) /proc/fs/fscache/histogram
 
 	cat /proc/fs/fscache/histogram
-	+HZ   +TIME OBJ INST  OP RUNS   OBJ RUNS  RETRV DLY RETRIEVLS
+	JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS  RETRV DLY RETRIEVLS
 	===== ===== ========= ========= ========= ========= =========
 
      This shows the breakdown of the number of times each amount of time
@@ -296,16 +295,16 @@ proc files.
 	RETRIEVLS	Time between beginning and end of a retrieval
 
      Each row shows the number of events that took a particular range of times.
-     Each step is 1 jiffy in size.  The +HZ column indicates the particular
-     jiffy range covered, and the +TIME field the equivalent number of seconds.
+     Each step is 1 jiffy in size.  The JIFS column indicates the particular
+     jiffy range covered, and the SECS field the equivalent number of seconds.
 
 
 =========
 DEBUGGING
 =========
 
-The FS-Cache facility can have runtime debugging enabled by adjusting the value
-in:
+If CONFIG_FSCACHE_DEBUG is enabled, the FS-Cache facility can have runtime
+debugging enabled by adjusting the value in:
 
 	/sys/module/fscache/parameters/debug
 
@@ -332,4 +331,3 @@ the control file.  For example:
 	echo $((1|8|64)) >/sys/module/fscache/parameters/debug
 
 will turn on all function entry debugging.
-
diff --git a/fs/cachefiles/Kconfig b/fs/cachefiles/Kconfig
index ddbdd85..11f54c3 100644
--- a/fs/cachefiles/Kconfig
+++ b/fs/cachefiles/Kconfig
@@ -21,13 +21,19 @@ config CACHEFILES_DEBUG
 
 config CACHEFILES_HISTOGRAM
 	bool "Gather latency information on CacheFiles"
-	depends on CACHEFILES && FSCACHE_PROC
+	depends on CACHEFILES && PROC_FS
 	help
 
 	  This option causes latency information to be gathered on CacheFiles
 	  operation and exported through file:
 
-		/proc/fs/fscache/cachefiles/histogram
+		/proc/fs/cachefiles/histogram
+
+	  The generation of this histogram adds a certain amount of overhead to
+	  execution as there are a number of points at which data is gathered,
+	  and on a multi-CPU system these may be on cachelines that keep
+	  bouncing between CPUs.  On the other hand, the histogram may be
+	  useful for debugging purposes.  Saying 'N' here is recommended.
 
 	  See Documentation/filesystems/caching/cachefiles.txt for more
 	  information.
diff --git a/fs/cachefiles/cf-proc.c b/fs/cachefiles/cf-proc.c
index c0d5444..d09beb5 100644
--- a/fs/cachefiles/cf-proc.c
+++ b/fs/cachefiles/cf-proc.c
@@ -14,104 +14,47 @@
 #include <linux/seq_file.h>
 #include "cf-internal.h"
 
-struct cachefiles_proc {
-	unsigned			nlines;
-	const struct seq_operations	*ops;
-};
-
 atomic_t cachefiles_lookup_histogram[HZ];
 atomic_t cachefiles_mkdir_histogram[HZ];
 atomic_t cachefiles_create_histogram[HZ];
 
-static struct proc_dir_entry *proc_cachefiles;
-
-static int cachefiles_proc_open(struct inode *inode, struct file *file);
-static void *cachefiles_proc_start(struct seq_file *m, loff_t *pos);
-static void cachefiles_proc_stop(struct seq_file *m, void *v);
-static void *cachefiles_proc_next(struct seq_file *m, void *v, loff_t *pos);
-static int cachefiles_histogram_show(struct seq_file *m, void *v);
-
-static const struct file_operations cachefiles_proc_fops = {
-	.open		= cachefiles_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static const struct seq_operations cachefiles_histogram_ops = {
-	.start		= cachefiles_proc_start,
-	.stop		= cachefiles_proc_stop,
-	.next		= cachefiles_proc_next,
-	.show		= cachefiles_histogram_show,
-};
-
-static const struct cachefiles_proc cachefiles_histogram = {
-	.nlines		= HZ + 1,
-	.ops		= &cachefiles_histogram_ops,
-};
-
 /*
- * initialise the /proc/fs/fscache/cachefiles/ directory
+ * display the latency histogram
  */
-int __init cachefiles_proc_init(void)
+static int cachefiles_histogram_show(struct seq_file *m, void *v)
 {
-	struct proc_dir_entry *p;
-
-	_enter("");
-
-	proc_cachefiles = proc_mkdir("cachefiles", proc_fscache);
-	if (!proc_cachefiles)
-		goto error_dir;
-	proc_cachefiles->owner = THIS_MODULE;
-
-	p = create_proc_entry("histogram", 0, proc_cachefiles);
-	if (!p)
-		goto error_histogram;
-	p->proc_fops = &cachefiles_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &cachefiles_histogram;
-
-	_leave(" = 0");
-	return 0;
+	unsigned long index;
+	unsigned x, y, z, t;
 
-error_histogram:
-	remove_proc_entry("fs/cachefiles", NULL);
-error_dir:
-	_leave(" = -ENOMEM");
-	return -ENOMEM;
-}
+	switch ((unsigned long) v) {
+	case 1:
+		seq_puts(m, "JIFS  SECS  LOOKUPS   MKDIRS    CREATES\n");
+		return 0;
+	case 2:
+		seq_puts(m, "===== ===== ========= ========= =========\n");
+		return 0;
+	default:
+		index = (unsigned long) v - 3;
+		x = atomic_read(&cachefiles_lookup_histogram[index]);
+		y = atomic_read(&cachefiles_mkdir_histogram[index]);
+		z = atomic_read(&cachefiles_create_histogram[index]);
+		if (x == 0 && y == 0 && z == 0)
+			return 0;
 
-/*
- * clean up the /proc/fs/fscache/cachefiles/ directory
- */
-void cachefiles_proc_cleanup(void)
-{
-	remove_proc_entry("histogram", proc_cachefiles);
-	remove_proc_entry("cachefiles", proc_fscache);
-}
+		t = (index * 1000) / HZ;
 
-/*
- * open "/proc/fs/fscache/cachefiles/XXX" which provide statistics summaries
- */
-static int cachefiles_proc_open(struct inode *inode, struct file *file)
-{
-	const struct cachefiles_proc *proc = PDE(inode)->data;
-	struct seq_file *m;
-	int ret;
-
-	ret = seq_open(file, proc->ops);
-	if (ret == 0) {
-		m = file->private_data;
-		m->private = (void *) proc;
+		seq_printf(m, "%4lu  0.%03u %9u %9u %9u\n", index, t, x, y, z);
+		return 0;
 	}
-	return ret;
 }
 
 /*
  * set up the iterator to start reading from the first line
  */
-static void *cachefiles_proc_start(struct seq_file *m, loff_t *_pos)
+static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
 {
+	if ((unsigned long long)*_pos >= HZ + 2)
+		return NULL;
 	if (*_pos == 0)
 		*_pos = 1;
 	return (void *)(unsigned long) *_pos;
@@ -120,47 +63,72 @@ static void *cachefiles_proc_start(struct seq_file *m, loff_t *_pos)
 /*
  * move to the next line
  */
-static void *cachefiles_proc_next(struct seq_file *m, void *v, loff_t *pos)
+static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	const struct cachefiles_proc *proc = m->private;
-
 	(*pos)++;
-	return *pos > proc->nlines ? NULL : (void *)(unsigned long) *pos;
+	return (unsigned long long)*pos > HZ + 2 ?
+		NULL : (void *)(unsigned long) *pos;
 }
 
 /*
  * clean up after reading
  */
-static void cachefiles_proc_stop(struct seq_file *m, void *v)
+static void cachefiles_histogram_stop(struct seq_file *m, void *v)
 {
 }
 
+static const struct seq_operations cachefiles_histogram_ops = {
+	.start		= cachefiles_histogram_start,
+	.stop		= cachefiles_histogram_stop,
+	.next		= cachefiles_histogram_next,
+	.show		= cachefiles_histogram_show,
+};
+
 /*
- * display the time-taken histogram
+ * open "/proc/fs/cachefiles/XXX" which provide statistics summaries
  */
-static int cachefiles_histogram_show(struct seq_file *m, void *v)
+static int cachefiles_histogram_open(struct inode *inode, struct file *file)
 {
-	unsigned long index;
-	unsigned x, y, z, t;
+	return seq_open(file, &cachefiles_histogram_ops);
+}
 
-	switch ((unsigned long) v) {
-	case 1:
-		seq_puts(m, "JIFS  SECS  LOOKUPS   MKDIRS    CREATES\n");
-		return 0;
-	case 2:
-		seq_puts(m, "===== ===== ========= ========= =========\n");
-		return 0;
-	default:
-		index = (unsigned long) v - 3;
-		x = atomic_read(&cachefiles_lookup_histogram[index]);
-		y = atomic_read(&cachefiles_mkdir_histogram[index]);
-		z = atomic_read(&cachefiles_create_histogram[index]);
-		if (x == 0 && y == 0 && z == 0)
-			return 0;
+static const struct file_operations cachefiles_histogram_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cachefiles_histogram_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
-		t = (index * 1000) / HZ;
+/*
+ * initialise the /proc/fs/cachefiles/ directory
+ */
+int __init cachefiles_proc_init(void)
+{
+	_enter("");
 
-		seq_printf(m, "%4lu  0.%03u %9u %9u %9u\n", index, t, x, y, z);
-		return 0;
-	}
+	if (!proc_mkdir("fs/cachefiles", NULL))
+		goto error_dir;
+
+	if (!proc_create("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
+			 &cachefiles_histogram_fops))
+		goto error_histogram;
+
+	_leave(" = 0");
+	return 0;
+
+error_histogram:
+	remove_proc_entry("fs/cachefiles", NULL);
+error_dir:
+	_leave(" = -ENOMEM");
+	return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/cachefiles/ directory
+ */
+void cachefiles_proc_cleanup(void)
+{
+	remove_proc_entry("fs/cachefiles/histogram", NULL);
+	remove_proc_entry("fs/cachefiles", NULL);
 }
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig
index b9ff04a..9bbb8ce 100644
--- a/fs/fscache/Kconfig
+++ b/fs/fscache/Kconfig
@@ -11,31 +11,38 @@ config FSCACHE
 
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
-config FSCACHE_PROC
-	bool "Provide /proc interface for local caching statistics"
-	depends on FSCACHE && PROC_FS
-
 config FSCACHE_STATS
 	bool "Gather statistical information on local caching"
-	depends on FSCACHE_PROC
+	depends on FSCACHE && PROC_FS
 	help
 	  This option causes statistical information to be gathered on local
 	  caching and exported through file:
 
 		/proc/fs/fscache/stats
 
+	  The gathering of statistics adds a certain amount of overhead to
+	  execution as there are a quite a few stats gathered, and on a
+	  multi-CPU system these may be on cachelines that keep bouncing
+	  between CPUs.  On the other hand, the stats are very useful for
+	  debugging purposes.  Saying 'Y' here is recommended.
+
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
 config FSCACHE_HISTOGRAM
 	bool "Gather latency information on local caching"
-	depends on FSCACHE_PROC
+	depends on FSCACHE && PROC_FS
 	help
-
 	  This option causes latency information to be gathered on local
 	  caching and exported through file:
 
 		/proc/fs/fscache/histogram
 
+	  The generation of this histogram adds a certain amount of overhead to
+	  execution as there are a number of points at which data is gathered,
+	  and on a multi-CPU system these may be on cachelines that keep
+	  bouncing between CPUs.  On the other hand, the histogram may be
+	  useful for debugging purposes.  Saying 'N' here is recommended.
+
 	  See Documentation/filesystems/caching/fscache.txt for more information.
 
 config FSCACHE_DEBUG
diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile
index 572b012..3f6a198 100644
--- a/fs/fscache/Makefile
+++ b/fs/fscache/Makefile
@@ -10,8 +10,10 @@ fscache-y := \
 	fsc-netfs.o \
 	fsc-object.o \
 	fsc-operation.o \
-	fsc-page.o \
-	fsc-proc.o \
-	fsc-stats.o
+	fsc-page.o
+
+fscache-$(CONFIG_PROC_FS) += fsc-proc.o
+fscache-$(CONFIG_FSCACHE_STATS) += fsc-stats.o
+fscache-$(CONFIG_FSCACHE_HISTOGRAM) += fsc-histogram.o
 
 obj-$(CONFIG_FSCACHE) := fscache.o
diff --git a/fs/fscache/fsc-histogram.c b/fs/fscache/fsc-histogram.c
new file mode 100644
index 0000000..d1cbbc3
--- /dev/null
+++ b/fs/fscache/fsc-histogram.c
@@ -0,0 +1,109 @@
+/* FS-Cache latency histogram
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define FSCACHE_DEBUG_LEVEL THREAD
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include "fsc-internal.h"
+
+atomic_t fscache_obj_instantiate_histogram[HZ];
+atomic_t fscache_objs_histogram[HZ];
+atomic_t fscache_ops_histogram[HZ];
+atomic_t fscache_retrieval_delay_histogram[HZ];
+atomic_t fscache_retrieval_histogram[HZ];
+
+/*
+ * display the time-taken histogram
+ */
+static int fscache_histogram_show(struct seq_file *m, void *v)
+{
+	unsigned long index;
+	unsigned n[5], t;
+
+	switch ((unsigned long) v) {
+	case 1:
+		seq_puts(m, "JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS "
+			 " RETRV DLY RETRIEVLS\n");
+		return 0;
+	case 2:
+		seq_puts(m, "===== ===== ========= ========= ========="
+			 " ========= =========\n");
+		return 0;
+	default:
+		index = (unsigned long) v - 3;
+		n[0] = atomic_read(&fscache_obj_instantiate_histogram[index]);
+		n[1] = atomic_read(&fscache_ops_histogram[index]);
+		n[2] = atomic_read(&fscache_objs_histogram[index]);
+		n[3] = atomic_read(&fscache_retrieval_delay_histogram[index]);
+		n[4] = atomic_read(&fscache_retrieval_histogram[index]);
+		if (!(n[0] | n[1] | n[2] | n[3] | n[4]))
+			return 0;
+
+		t = (index * 1000) / HZ;
+
+		seq_printf(m, "%4lu  0.%03u %9u %9u %9u %9u %9u\n",
+			   index, t, n[0], n[1], n[2], n[3], n[4]);
+		return 0;
+	}
+}
+
+/*
+ * set up the iterator to start reading from the first line
+ */
+static void *fscache_histogram_start(struct seq_file *m, loff_t *_pos)
+{
+	if ((unsigned long long)*_pos >= HZ + 2)
+		return NULL;
+	if (*_pos == 0)
+		*_pos = 1;
+	return (void *)(unsigned long) *_pos;
+}
+
+/*
+ * move to the next line
+ */
+static void *fscache_histogram_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return (unsigned long long)*pos > HZ + 2 ?
+		NULL : (void *)(unsigned long) *pos;
+}
+
+/*
+ * clean up after reading
+ */
+static void fscache_histogram_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations fscache_histogram_ops = {
+	.start		= fscache_histogram_start,
+	.stop		= fscache_histogram_stop,
+	.next		= fscache_histogram_next,
+	.show		= fscache_histogram_show,
+};
+
+/*
+ * open "/proc/fs/fscache/histogram" to provide latency data
+ */
+static int fscache_histogram_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &fscache_histogram_ops);
+}
+
+const struct file_operations fscache_histogram_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fscache_histogram_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
diff --git a/fs/fscache/fsc-internal.h b/fs/fscache/fsc-internal.h
index f2ff86b..e5eb297 100644
--- a/fs/fscache/fsc-internal.h
+++ b/fs/fscache/fsc-internal.h
@@ -51,6 +51,30 @@ extern struct fscache_cookie fscache_fsdef_index;
 extern struct fscache_cookie_def fscache_fsdef_netfs_def;
 
 /*
+ * fsc-histogram.c
+ */
+#ifdef CONFIG_FSCACHE_HISTOGRAM
+extern atomic_t fscache_obj_instantiate_histogram[HZ];
+extern atomic_t fscache_objs_histogram[HZ];
+extern atomic_t fscache_ops_histogram[HZ];
+extern atomic_t fscache_retrieval_delay_histogram[HZ];
+extern atomic_t fscache_retrieval_histogram[HZ];
+
+static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif)
+{
+	unsigned long jif = jiffies - start_jif;
+	if (jif >= HZ)
+		jif = HZ - 1;
+	atomic_inc(&histogram[jif]);
+}
+
+extern const struct file_operations fscache_histogram_fops;
+
+#else
+#define fscache_hist(hist, start_jif) do {} while (0)
+#endif
+
+/*
  * fsc-main.c
  */
 extern unsigned fscache_defer_lookup;
@@ -80,6 +104,17 @@ extern void fscache_start_operations(struct fscache_object *);
 extern void fscache_operation_gc(struct work_struct *);
 
 /*
+ * fsc-proc.c
+ */
+#ifdef CONFIG_PROC_FS
+extern int __init fscache_proc_init(void);
+extern void fscache_proc_cleanup(void);
+#else
+#define fscache_proc_init()	(0)
+#define fscache_proc_cleanup()	do {} while (0)
+#endif
+
+/*
  * fsc-stats.c
  */
 #ifdef CONFIG_FSCACHE_STATS
@@ -164,36 +199,11 @@ static inline void fscache_stat(atomic_t *stat)
 {
 	atomic_inc(stat);
 }
-#else
-
-#define fscache_stat(stat) do {} while (0)
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-extern atomic_t fscache_obj_instantiate_histogram[HZ];
-extern atomic_t fscache_objs_histogram[HZ];
-extern atomic_t fscache_ops_histogram[HZ];
-extern atomic_t fscache_retrieval_delay_histogram[HZ];
-extern atomic_t fscache_retrieval_histogram[HZ];
-
-static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif)
-{
-	unsigned long jif = jiffies - start_jif;
-	if (jif >= HZ)
-		jif = HZ - 1;
-	atomic_inc(&histogram[jif]);
-}
 
+extern const struct file_operations fscache_stats_fops;
 #else
-#define fscache_hist(hist, start_jif) do {} while (0)
-#endif
 
-#ifdef CONFIG_FSCACHE_PROC
-extern int __init fscache_proc_init(void);
-extern void fscache_proc_cleanup(void);
-#else
-#define fscache_proc_init()	(0)
-#define fscache_proc_cleanup()	do {} while (0)
+#define fscache_stat(stat) do {} while (0)
 #endif
 
 /*
diff --git a/fs/fscache/fsc-proc.c b/fs/fscache/fsc-proc.c
index dd6daa5..2f549f3 100644
--- a/fs/fscache/fsc-proc.c
+++ b/fs/fscache/fsc-proc.c
@@ -15,94 +15,26 @@
 #include <linux/seq_file.h>
 #include "fsc-internal.h"
 
-struct fscache_proc {
-	unsigned			nlines;
-	const struct seq_operations	*ops;
-};
-
-struct proc_dir_entry *proc_fscache;
-EXPORT_SYMBOL(proc_fscache);
-
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-static int fscache_proc_open(struct inode *inode, struct file *file);
-static void *fscache_proc_start(struct seq_file *m, loff_t *pos);
-static void fscache_proc_stop(struct seq_file *m, void *v);
-static void *fscache_proc_next(struct seq_file *m, void *v, loff_t *pos);
-
-static const struct file_operations fscache_proc_fops = {
-	.open		= fscache_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-#endif
-
-#ifdef CONFIG_FSCACHE_STATS
-static int fscache_stats_show(struct seq_file *m, void *v);
-
-static const struct seq_operations fscache_stats_ops = {
-	.start		= fscache_proc_start,
-	.stop		= fscache_proc_stop,
-	.next		= fscache_proc_next,
-	.show		= fscache_stats_show,
-};
-
-static const struct fscache_proc fscache_stats = {
-	.nlines		= 17,
-	.ops		= &fscache_stats_ops,
-};
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-static int fscache_histogram_show(struct seq_file *m, void *v);
-
-static const struct seq_operations fscache_histogram_ops = {
-	.start		= fscache_proc_start,
-	.stop		= fscache_proc_stop,
-	.next		= fscache_proc_next,
-	.show		= fscache_histogram_show,
-};
-
-static const struct fscache_proc fscache_histogram = {
-	.nlines		= HZ + 1,
-	.ops		= &fscache_histogram_ops,
-};
-#endif
-
-#define FSC_DESC(SELECT, N) ((void *) (unsigned long) (((SELECT) << 16) | (N)))
-
 /*
  * initialise the /proc/fs/fscache/ directory
  */
 int __init fscache_proc_init(void)
 {
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-	struct proc_dir_entry *p;
-#endif
-
 	_enter("");
 
-	proc_fscache = proc_mkdir("fs/fscache", NULL);
-	if (!proc_fscache)
+	if (!proc_mkdir("fs/fscache", NULL))
 		goto error_dir;
-	proc_fscache->owner = THIS_MODULE;
 
 #ifdef CONFIG_FSCACHE_STATS
-	p = create_proc_entry("stats", 0, proc_fscache);
-	if (!p)
+	if (!proc_create("fs/fscache/stats", S_IFREG | 0444, NULL,
+			 &fscache_stats_fops))
 		goto error_stats;
-	p->proc_fops = &fscache_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &fscache_stats;
 #endif
 
 #ifdef CONFIG_FSCACHE_HISTOGRAM
-	p = create_proc_entry("histogram", 0, proc_fscache);
-	if (!p)
+	if (!proc_create("fs/fscache/histogram", S_IFREG | 0444, NULL,
+			 &fscache_histogram_fops))
 		goto error_histogram;
-	p->proc_fops = &fscache_proc_fops;
-	p->owner = THIS_MODULE;
-	p->data = (void *) &fscache_histogram;
 #endif
 
 	_leave(" = 0");
@@ -112,7 +44,7 @@ int __init fscache_proc_init(void)
 error_histogram:
 #endif
 #ifdef CONFIG_FSCACHE_STATS
-	remove_proc_entry("stats", proc_fscache);
+	remove_proc_entry("fs/fscache/stats", NULL);
 error_stats:
 #endif
 	remove_proc_entry("fs/fscache", NULL);
@@ -127,244 +59,10 @@ error_dir:
 void fscache_proc_cleanup(void)
 {
 #ifdef CONFIG_FSCACHE_HISTOGRAM
-	remove_proc_entry("histogram", proc_fscache);
+	remove_proc_entry("fs/fscache/histogram", NULL);
 #endif
 #ifdef CONFIG_FSCACHE_STATS
-	remove_proc_entry("stats", proc_fscache);
+	remove_proc_entry("fs/fscache/stats", NULL);
 #endif
 	remove_proc_entry("fs/fscache", NULL);
 }
-
-#if defined(CONFIG_FSCACHE_STATS) || defined(CONFIG_FSCACHE_HISTOGRAM)
-/*
- * open "/proc/fs/fscache/XXX" which provide statistics summaries
- */
-static int fscache_proc_open(struct inode *inode, struct file *file)
-{
-	const struct fscache_proc *proc = PDE(inode)->data;
-	struct seq_file *m;
-	int ret;
-
-	ret = seq_open(file, proc->ops);
-	if (ret == 0) {
-		m = file->private_data;
-		m->private = (void *) proc;
-	}
-	return ret;
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *fscache_proc_start(struct seq_file *m, loff_t *_pos)
-{
-	if (*_pos == 0)
-		*_pos = 1;
-	return (void *)(unsigned long) *_pos;
-}
-
-/*
- * move to the next line
- */
-static void *fscache_proc_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	const struct fscache_proc *proc = m->private;
-
-	(*pos)++;
-	return *pos > proc->nlines ? NULL : (void *)(unsigned long) *pos;
-}
-
-/*
- * clean up after reading
- */
-static void fscache_proc_stop(struct seq_file *m, void *v)
-{
-}
-#endif
-
-#ifdef CONFIG_FSCACHE_STATS
-/*
- * display the general statistics
- */
-static int fscache_stats_show(struct seq_file *m, void *v)
-{
-	unsigned long line = (unsigned long) v;
-
-	switch (line) {
-	case 1:
-		seq_puts(m, "FS-Cache statistics\n");
-		break;
-
-	case 2:
-		seq_printf(m, "Cookies: idx=%u dat=%u spc=%u\n",
-			   atomic_read(&fscache_n_cookie_index),
-			   atomic_read(&fscache_n_cookie_data),
-			   atomic_read(&fscache_n_cookie_special));
-		break;
-
-	case 3:
-		seq_printf(m, "Objects: alc=%u nal=%u avl=%u ded=%u\n",
-			   atomic_read(&fscache_n_object_alloc),
-			   atomic_read(&fscache_n_object_no_alloc),
-			   atomic_read(&fscache_n_object_avail),
-			   atomic_read(&fscache_n_object_dead));
-		break;
-
-	case 4:
-		seq_printf(m, "ChkAux : non=%u ok=%u upd=%u obs=%u\n",
-			   atomic_read(&fscache_n_checkaux_none),
-			   atomic_read(&fscache_n_checkaux_okay),
-			   atomic_read(&fscache_n_checkaux_update),
-			   atomic_read(&fscache_n_checkaux_obsolete));
-		break;
-
-	case 5:
-		seq_printf(m, "Pages  : mrk=%u unc=%u\n",
-			   atomic_read(&fscache_n_marks),
-			   atomic_read(&fscache_n_uncaches));
-		break;
-
-	case 6:
-		seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u"
-			   " oom=%u\n",
-			   atomic_read(&fscache_n_acquires),
-			   atomic_read(&fscache_n_acquires_null),
-			   atomic_read(&fscache_n_acquires_no_cache),
-			   atomic_read(&fscache_n_acquires_ok),
-			   atomic_read(&fscache_n_acquires_nobufs),
-			   atomic_read(&fscache_n_acquires_oom));
-		break;
-
-	case 7:
-		seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n",
-			   atomic_read(&fscache_n_object_lookups),
-			   atomic_read(&fscache_n_object_lookups_negative),
-			   atomic_read(&fscache_n_object_lookups_positive),
-			   atomic_read(&fscache_n_object_created));
-		break;
-
-	case 8:
-		seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
-			   atomic_read(&fscache_n_updates),
-			   atomic_read(&fscache_n_updates_null),
-			   atomic_read(&fscache_n_updates_run));
-		break;
-
-	case 9:
-		seq_printf(m, "Relinqs: n=%u nul=%u wcr=%u\n",
-			   atomic_read(&fscache_n_relinquishes),
-			   atomic_read(&fscache_n_relinquishes_null),
-			   atomic_read(&fscache_n_relinquishes_waitcrt));
-		break;
-
-	case 10:
-		seq_printf(m, "AttrChg: n=%u ok=%u nbf=%u oom=%u run=%u\n",
-			   atomic_read(&fscache_n_attr_changed),
-			   atomic_read(&fscache_n_attr_changed_ok),
-			   atomic_read(&fscache_n_attr_changed_nobufs),
-			   atomic_read(&fscache_n_attr_changed_nomem),
-			   atomic_read(&fscache_n_attr_changed_calls));
-		break;
-
-	case 11:
-		seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u\n",
-			   atomic_read(&fscache_n_allocs),
-			   atomic_read(&fscache_n_allocs_ok),
-			   atomic_read(&fscache_n_allocs_wait),
-			   atomic_read(&fscache_n_allocs_nobufs));
-		break;
-	case 12:
-		seq_printf(m, "Allocs : ops=%u owt=%u\n",
-			   atomic_read(&fscache_n_alloc_ops),
-			   atomic_read(&fscache_n_alloc_op_waits));
-		break;
-
-	case 13:
-		seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u"
-			   " int=%u oom=%u\n",
-			   atomic_read(&fscache_n_retrievals),
-			   atomic_read(&fscache_n_retrievals_ok),
-			   atomic_read(&fscache_n_retrievals_wait),
-			   atomic_read(&fscache_n_retrievals_nodata),
-			   atomic_read(&fscache_n_retrievals_nobufs),
-			   atomic_read(&fscache_n_retrievals_intr),
-			   atomic_read(&fscache_n_retrievals_nomem));
-		break;
-	case 14:
-		seq_printf(m, "Retrvls: ops=%u owt=%u\n",
-			   atomic_read(&fscache_n_retrieval_ops),
-			   atomic_read(&fscache_n_retrieval_op_waits));
-		break;
-
-	case 15:
-		seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n",
-			   atomic_read(&fscache_n_stores),
-			   atomic_read(&fscache_n_stores_ok),
-			   atomic_read(&fscache_n_stores_again),
-			   atomic_read(&fscache_n_stores_nobufs),
-			   atomic_read(&fscache_n_stores_oom));
-		break;
-	case 16:
-		seq_printf(m, "Stores : ops=%u run=%u\n",
-			   atomic_read(&fscache_n_store_ops),
-			   atomic_read(&fscache_n_store_calls));
-		break;
-
-	case 17:
-		seq_printf(m, "Ops    : pend=%u run=%u enq=%u\n",
-			   atomic_read(&fscache_n_op_pend),
-			   atomic_read(&fscache_n_op_run),
-			   atomic_read(&fscache_n_op_enqueue));
-		break;
-
-	case 18:
-		seq_printf(m, "Ops    : dfr=%u rel=%u gc=%u\n",
-			   atomic_read(&fscache_n_op_deferred_release),
-			   atomic_read(&fscache_n_op_release),
-			   atomic_read(&fscache_n_op_gc));
-		break;
-
-	default:
-		break;
-	}
-	return 0;
-}
-
-#endif /* end CONFIG_FSCACHE_STATS */
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-/*
- * display the time-taken histogram
- */
-static int fscache_histogram_show(struct seq_file *m, void *v)
-{
-	unsigned long index;
-	unsigned n[5], t;
-
-	switch ((unsigned long) v) {
-	case 1:
-		seq_puts(m, "JIFS  SECS  OBJ INST  OP RUNS   OBJ RUNS "
-			 " RETRV DLY RETRIEVLS\n");
-		return 0;
-	case 2:
-		seq_puts(m, "===== ===== ========= ========= ========="
-			 " ========= =========\n");
-		return 0;
-	default:
-		index = (unsigned long) v - 3;
-		n[0] = atomic_read(&fscache_obj_instantiate_histogram[index]);
-		n[1] = atomic_read(&fscache_ops_histogram[index]);
-		n[2] = atomic_read(&fscache_objs_histogram[index]);
-		n[3] = atomic_read(&fscache_retrieval_delay_histogram[index]);
-		n[4] = atomic_read(&fscache_retrieval_histogram[index]);
-		if (!(n[0] | n[1] | n[2] | n[3] | n[4]))
-			return 0;
-
-		t = (index * 1000) / HZ;
-
-		seq_printf(m, "%4lu  0.%03u %9u %9u %9u %9u %9u\n",
-			   index, t, n[0], n[1], n[2], n[3], n[4]);
-		return 0;
-	}
-}
-#endif /* end CONFIG_FSCACHE_HISTOGRAM */
diff --git a/fs/fscache/fsc-stats.c b/fs/fscache/fsc-stats.c
index 8762d43..93ffc8f 100644
--- a/fs/fscache/fsc-stats.c
+++ b/fs/fscache/fsc-stats.c
@@ -18,7 +18,6 @@
 /*
  * operation counters
  */
-#ifdef CONFIG_FSCACHE_STATS
 atomic_t fscache_n_op_pend;
 atomic_t fscache_n_op_run;
 atomic_t fscache_n_op_enqueue;
@@ -93,12 +92,121 @@ atomic_t fscache_n_checkaux_none;
 atomic_t fscache_n_checkaux_okay;
 atomic_t fscache_n_checkaux_update;
 atomic_t fscache_n_checkaux_obsolete;
-#endif
-
-#ifdef CONFIG_FSCACHE_HISTOGRAM
-atomic_t fscache_obj_instantiate_histogram[HZ];
-atomic_t fscache_objs_histogram[HZ];
-atomic_t fscache_ops_histogram[HZ];
-atomic_t fscache_retrieval_delay_histogram[HZ];
-atomic_t fscache_retrieval_histogram[HZ];
-#endif
+
+/*
+ * display the general statistics
+ */
+static int fscache_stats_show(struct seq_file *m, void *v)
+{
+	seq_puts(m, "FS-Cache statistics\n");
+
+	seq_printf(m, "Cookies: idx=%u dat=%u spc=%u\n",
+		   atomic_read(&fscache_n_cookie_index),
+		   atomic_read(&fscache_n_cookie_data),
+		   atomic_read(&fscache_n_cookie_special));
+
+	seq_printf(m, "Objects: alc=%u nal=%u avl=%u ded=%u\n",
+		   atomic_read(&fscache_n_object_alloc),
+		   atomic_read(&fscache_n_object_no_alloc),
+		   atomic_read(&fscache_n_object_avail),
+		   atomic_read(&fscache_n_object_dead));
+	seq_printf(m, "ChkAux : non=%u ok=%u upd=%u obs=%u\n",
+		   atomic_read(&fscache_n_checkaux_none),
+		   atomic_read(&fscache_n_checkaux_okay),
+		   atomic_read(&fscache_n_checkaux_update),
+		   atomic_read(&fscache_n_checkaux_obsolete));
+
+	seq_printf(m, "Pages  : mrk=%u unc=%u\n",
+		   atomic_read(&fscache_n_marks),
+		   atomic_read(&fscache_n_uncaches));
+
+	seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u"
+		   " oom=%u\n",
+		   atomic_read(&fscache_n_acquires),
+		   atomic_read(&fscache_n_acquires_null),
+		   atomic_read(&fscache_n_acquires_no_cache),
+		   atomic_read(&fscache_n_acquires_ok),
+		   atomic_read(&fscache_n_acquires_nobufs),
+		   atomic_read(&fscache_n_acquires_oom));
+
+	seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n",
+		   atomic_read(&fscache_n_object_lookups),
+		   atomic_read(&fscache_n_object_lookups_negative),
+		   atomic_read(&fscache_n_object_lookups_positive),
+		   atomic_read(&fscache_n_object_created));
+
+	seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
+		   atomic_read(&fscache_n_updates),
+		   atomic_read(&fscache_n_updates_null),
+		   atomic_read(&fscache_n_updates_run));
+
+	seq_printf(m, "Relinqs: n=%u nul=%u wcr=%u\n",
+		   atomic_read(&fscache_n_relinquishes),
+		   atomic_read(&fscache_n_relinquishes_null),
+		   atomic_read(&fscache_n_relinquishes_waitcrt));
+
+	seq_printf(m, "AttrChg: n=%u ok=%u nbf=%u oom=%u run=%u\n",
+		   atomic_read(&fscache_n_attr_changed),
+		   atomic_read(&fscache_n_attr_changed_ok),
+		   atomic_read(&fscache_n_attr_changed_nobufs),
+		   atomic_read(&fscache_n_attr_changed_nomem),
+		   atomic_read(&fscache_n_attr_changed_calls));
+
+	seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u\n",
+		   atomic_read(&fscache_n_allocs),
+		   atomic_read(&fscache_n_allocs_ok),
+		   atomic_read(&fscache_n_allocs_wait),
+		   atomic_read(&fscache_n_allocs_nobufs));
+	seq_printf(m, "Allocs : ops=%u owt=%u\n",
+		   atomic_read(&fscache_n_alloc_ops),
+		   atomic_read(&fscache_n_alloc_op_waits));
+
+	seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u"
+		   " int=%u oom=%u\n",
+		   atomic_read(&fscache_n_retrievals),
+		   atomic_read(&fscache_n_retrievals_ok),
+		   atomic_read(&fscache_n_retrievals_wait),
+		   atomic_read(&fscache_n_retrievals_nodata),
+		   atomic_read(&fscache_n_retrievals_nobufs),
+		   atomic_read(&fscache_n_retrievals_intr),
+		   atomic_read(&fscache_n_retrievals_nomem));
+	seq_printf(m, "Retrvls: ops=%u owt=%u\n",
+		   atomic_read(&fscache_n_retrieval_ops),
+		   atomic_read(&fscache_n_retrieval_op_waits));
+
+	seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n",
+		   atomic_read(&fscache_n_stores),
+		   atomic_read(&fscache_n_stores_ok),
+		   atomic_read(&fscache_n_stores_again),
+		   atomic_read(&fscache_n_stores_nobufs),
+		   atomic_read(&fscache_n_stores_oom));
+	seq_printf(m, "Stores : ops=%u run=%u\n",
+		   atomic_read(&fscache_n_store_ops),
+		   atomic_read(&fscache_n_store_calls));
+
+	seq_printf(m, "Ops    : pend=%u run=%u enq=%u\n",
+		   atomic_read(&fscache_n_op_pend),
+		   atomic_read(&fscache_n_op_run),
+		   atomic_read(&fscache_n_op_enqueue));
+	seq_printf(m, "Ops    : dfr=%u rel=%u gc=%u\n",
+		   atomic_read(&fscache_n_op_deferred_release),
+		   atomic_read(&fscache_n_op_release),
+		   atomic_read(&fscache_n_op_gc));
+	return 0;
+}
+
+/*
+ * open "/proc/fs/fscache/stats" allowing provision of a statistical summary
+ */
+static int fscache_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fscache_stats_show, NULL);
+}
+
+const struct file_operations fscache_stats_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fscache_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index a31f4c1..0410bd9 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -29,10 +29,6 @@ struct fscache_cache_ops;
 struct fscache_object;
 struct fscache_operation;
 
-#ifdef CONFIG_FSCACHE_PROC
-extern struct proc_dir_entry *proc_fscache;
-#endif
-
 /*
  * cache tag definition
  */

  parent reply	other threads:[~2008-11-21 15:32 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-20 14:41 [PATCH 00/45] Permit filesystem local caching [ver #41] David Howells
2008-11-20 14:41 ` [PATCH 01/45] Create a dynamically sized pool of threads for doing very slow work items " David Howells
2008-11-21  8:09   ` Andrew Morton
2008-11-21 10:24     ` David Howells
2008-11-21 10:24       ` David Howells
2008-11-21 18:17       ` Andrew Morton
2008-11-21 18:17         ` Andrew Morton
2008-11-22  0:38         ` David Howells
2008-12-19  4:14   ` Serge E. Hallyn
2008-12-19 11:42     ` David Howells
2008-12-19 12:12       ` David Howells
2008-12-19 12:12         ` David Howells
2008-12-19 16:52         ` Serge E. Hallyn
2008-12-19 11:44     ` David Howells
2008-12-19 11:44       ` David Howells
2008-12-19  4:19   ` Serge E. Hallyn
2008-12-19  4:19     ` Serge E. Hallyn
2008-12-19  7:15   ` Andrew Morton
2008-12-19  7:15     ` Andrew Morton
2008-12-19 12:54     ` David Howells
2008-11-20 14:41 ` [PATCH 02/45] Make slow-work thread pool actually dynamic " David Howells
2008-12-19 17:58   ` Serge E. Hallyn
2008-11-20 14:41 ` [PATCH 03/45] Make the slow work pool configurable " David Howells
2008-12-19 18:33   ` Serge E. Hallyn
2008-12-19 18:33     ` Serge E. Hallyn
2008-11-20 14:42 ` [PATCH 04/45] Document the slow work thread pool " David Howells
2008-11-20 14:42 ` [PATCH 05/45] FS-Cache: Release page->private after failed readahead " David Howells
2008-11-21  8:12   ` Andrew Morton
2008-11-21 10:27     ` David Howells
2008-11-21 10:27       ` David Howells
2008-11-20 14:42 ` [PATCH 06/45] FS-Cache: Recruit a couple of page flags for cache management " David Howells
2008-11-21  8:17   ` Andrew Morton
2008-11-21  8:17     ` Andrew Morton
2008-11-21 10:31     ` David Howells
2008-11-21 10:31       ` David Howells
2008-11-20 14:42 ` [PATCH 07/45] FS-Cache: Provide an add_wait_queue_tail() function " David Howells
2008-11-21  8:17   ` Andrew Morton
2008-11-21  8:17     ` Andrew Morton
2008-11-21 13:32     ` David Howells
2008-11-21 13:32       ` David Howells
2008-11-20 14:42 ` [PATCH 08/45] FS-Cache: Add the FS-Cache netfs API and documentation " David Howells
2008-11-20 14:42 ` [PATCH 09/45] FS-Cache: Add the FS-Cache cache backend " David Howells
2008-11-20 14:42 ` [PATCH 10/45] FS-Cache: Add main configuration option, module entry points and debugging " David Howells
2008-11-20 14:42 ` [PATCH 11/45] FS-Cache: Add use of /proc and presentation of statistics " David Howells
2008-11-21  0:15   ` Alexey Dobriyan
2008-11-21  2:17     ` David Howells
2008-11-21  2:17       ` David Howells
2008-11-21  2:34       ` Alexey Dobriyan
2008-11-21 15:32     ` David Howells [this message]
2008-11-21 15:32       ` David Howells
2008-11-20 14:42 ` [PATCH 12/45] FS-Cache: Root index definition " David Howells
2008-11-20 14:42 ` [PATCH 13/45] FS-Cache: Add cache tag handling " David Howells
2008-11-20 14:42 ` [PATCH 14/45] FS-Cache: Add cache management " David Howells
2008-11-20 14:42 ` [PATCH 15/45] FS-Cache: Provide a slab for cookie allocation " David Howells
2008-11-20 14:43 ` [PATCH 16/45] FS-Cache: Add netfs registration " David Howells
2008-11-20 14:43 ` [PATCH 17/45] FS-Cache: Bit waiting helpers " David Howells
2008-11-20 14:43 ` [PATCH 18/45] FS-Cache: Object management state machine " David Howells
2008-11-20 14:43 ` [PATCH 19/45] FS-Cache: Implement the cookie management part of the netfs API " David Howells
2008-11-20 14:43 ` [PATCH 20/45] FS-Cache: Add and document asynchronous operation handling " David Howells
2008-11-20 14:43 ` [PATCH 21/45] FS-Cache: Implement data I/O part of netfs API " David Howells
2008-11-20 14:43 ` [PATCH 22/45] CacheFiles: Add missing copy_page export for ia64 " David Howells
2008-11-20 14:43 ` [PATCH 23/45] CacheFiles: Be consistent about the use of mapping vs file->f_mapping in Ext3 " David Howells
2008-11-22 17:38   ` Andreas Dilger
2008-11-26 14:40     ` David Howells
2008-11-20 14:43 ` [PATCH 24/45] CacheFiles: Add a hook to write a single page of data to an inode " David Howells
2008-11-21  8:23   ` Andrew Morton
2008-11-21  8:23     ` Andrew Morton
2008-11-21 12:43     ` David Howells
2008-11-21 12:43       ` David Howells
2008-11-21 13:00       ` Jamie Lokier
2008-11-21 17:15         ` Valdis.Kletnieks
2008-11-21 17:36       ` Randy Dunlap
2008-11-22  0:48         ` David Howells
2008-11-22  0:48           ` David Howells
2008-11-21 18:31       ` Andrew Morton
2008-11-21 18:31         ` Andrew Morton
2008-11-20 14:43 ` [PATCH 25/45] CacheFiles: Permit the page lock state to be monitored " David Howells
2008-11-20 14:43 ` [PATCH 26/45] CacheFiles: Export things for CacheFiles " David Howells
2008-11-20 14:43 ` [PATCH 27/45] CacheFiles: A cache that backs onto a mounted filesystem " David Howells
2008-11-20 14:44 ` [PATCH 28/45] FS-Cache: Make kAFS use FS-Cache " David Howells
2008-11-20 14:44 ` [PATCH 29/45] NFS: Add comment banners to some NFS functions " David Howells
2008-11-20 14:44 ` [PATCH 30/45] NFS: Add FS-Cache option bit and debug bit " David Howells
2008-11-20 14:44 ` [PATCH 31/45] NFS: Permit local filesystem caching to be enabled for NFS " David Howells
2008-11-20 14:44 ` [PATCH 32/45] NFS: Register NFS for caching and retrieve the top-level index " David Howells
2008-11-20 14:44 ` [PATCH 33/45] NFS: Define and create server-level objects " David Howells
2008-11-20 14:44 ` [PATCH 34/45] NFS: Define and create superblock-level " David Howells
2008-11-20 14:44 ` [PATCH 35/45] NFS: Define and create inode-level cache " David Howells
2008-11-20 14:44 ` [PATCH 36/45] NFS: Use local disk inode cache " David Howells
2008-11-20 14:44 ` [PATCH 37/45] NFS: Invalidate FsCache page flags when cache removed " David Howells
2008-11-20 14:44 ` [PATCH 38/45] NFS: Add some new I/O counters for FS-Cache doing things for NFS " David Howells
2008-11-20 14:45 ` [PATCH 39/45] NFS: FS-Cache page management " David Howells
2008-11-20 14:45 ` [PATCH 40/45] NFS: Add read context retention for FS-Cache to call back with " David Howells
2008-11-20 14:45 ` [PATCH 41/45] NFS: nfs_readpage_async() needs to be accessible as a fallback for local caching " David Howells
2008-11-20 14:45 ` [PATCH 42/45] NFS: Read pages from FS-Cache into an NFS inode " David Howells
2008-11-20 14:45 ` [PATCH 43/45] NFS: Store pages from an NFS inode into a local cache " David Howells
2008-11-20 14:45 ` [PATCH 44/45] NFS: Display local caching state " David Howells
2008-11-20 14:45 ` [PATCH 45/45] NFS: Add mount options to enable local caching on NFS " David Howells
2008-11-21  8:28 ` [PATCH 00/45] Permit filesystem local caching " Andrew Morton
2008-11-21  8:28   ` Andrew Morton
2008-11-22  1:11   ` David Howells
2008-11-22  1:11     ` David Howells
2008-11-25  0:09   ` David Howells
2008-11-25  0:09     ` David Howells
2008-11-25 13:39   ` FS-Cache Benchmarks David Howells
2008-11-25 13:39     ` David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=15505.1227281536@redhat.com \
    --to=dhowells@redhat.com \
    --cc=adobriyan@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nfsv4@linux-nfs.org \
    --cc=trond.myklebust@fys.uio.no \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.