From Dipankar

This patch makes some basic statistics for RCU available in /proc/rcu.
It is a trimmed down version of the earler rcu_stats patch in -mm kernels.
I removed all the RCU implementation dependent stats (mostly needed for
debugging) and retained only the part that was very generic in
nature - # of RCU requests and # of actual RCU updates for each
CPU. This will allow us to monitor the health of the RCU
subsystem and such things have been extremely useful for me to
investigate problems.

[dipankar@llm04 dipankar]$ cat /proc/rcu
CPU : 0
RCU requests : 0
RCU updates : 0

CPU : 1
RCU requests : 0
RCU updates : 0

CPU : 2
RCU requests : 0
RCU updates : 0

CPU : 3
RCU requests : 0
RCU updates : 0




 25-akpm/Documentation/filesystems/proc.txt |    4 ++
 25-akpm/fs/proc/proc_misc.c                |   13 +++++++
 25-akpm/include/linux/rcupdate.h           |    4 ++
 25-akpm/kernel/rcupdate.c                  |   48 +++++++++++++++++++++++++++--
 4 files changed, 67 insertions(+), 2 deletions(-)

diff -puN fs/proc/proc_misc.c~rcu-stats fs/proc/proc_misc.c
--- 25/fs/proc/proc_misc.c~rcu-stats	Tue Mar 18 15:07:32 2003
+++ 25-akpm/fs/proc/proc_misc.c	Tue Mar 18 15:07:32 2003
@@ -246,6 +246,18 @@ static struct file_operations proc_cpuin
 	.release	= seq_release,
 };
 
+extern struct seq_operations rcu_op;
+static int rcu_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &rcu_op);
+}
+static struct file_operations proc_rcu_operations = {
+	.open		= rcu_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 extern struct seq_operations vmstat_op;
 static int vmstat_open(struct inode *inode, struct file *file)
 {
@@ -592,6 +604,7 @@ void __init proc_misc_init(void)
 	if (entry)
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+	create_seq_entry("rcu", 0, &proc_rcu_operations);
 	create_seq_entry("partitions", 0, &proc_partitions_operations);
 #if !defined(CONFIG_ARCH_S390)
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
diff -puN include/linux/rcupdate.h~rcu-stats include/linux/rcupdate.h
--- 25/include/linux/rcupdate.h~rcu-stats	Tue Mar 18 15:07:32 2003
+++ 25-akpm/include/linux/rcupdate.h	Tue Mar 18 15:07:32 2003
@@ -95,6 +95,8 @@ struct rcu_data {
         long  	       	batch;           /* Batch # for current RCU batch */
         struct list_head  nxtlist;
         struct list_head  curlist;
+ 	long		nr_rcureqs;
+ 	long		nr_rcupdates;
 };
 
 DECLARE_PER_CPU(struct rcu_data, rcu_data);
@@ -105,6 +107,8 @@ extern struct rcu_ctrlblk rcu_ctrlblk;
 #define RCU_batch(cpu) 		(per_cpu(rcu_data, (cpu)).batch)
 #define RCU_nxtlist(cpu) 	(per_cpu(rcu_data, (cpu)).nxtlist)
 #define RCU_curlist(cpu) 	(per_cpu(rcu_data, (cpu)).curlist)
+#define RCU_nr_rcureqs(cpu) 	(per_cpu(rcu_data, (cpu)).nr_rcureqs)
+#define RCU_nr_rcupdates(cpu) 	(per_cpu(rcu_data, (cpu)).nr_rcupdates)
 
 #define RCU_QSCTR_INVALID	0
 
diff -puN kernel/rcupdate.c~rcu-stats kernel/rcupdate.c
--- 25/kernel/rcupdate.c~rcu-stats	Tue Mar 18 15:07:32 2003
+++ 25-akpm/kernel/rcupdate.c	Tue Mar 18 15:07:32 2003
@@ -41,6 +41,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/percpu.h>
+#include <linux/seq_file.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
 
@@ -75,6 +76,7 @@ void call_rcu(struct rcu_head *head, voi
 	local_irq_save(flags);
 	cpu = smp_processor_id();
 	list_add_tail(&head->list, &RCU_nxtlist(cpu));
+	RCU_nr_rcureqs(cpu)++;
 	local_irq_restore(flags);
 }
 
@@ -82,7 +84,7 @@ void call_rcu(struct rcu_head *head, voi
  * Invoke the completed RCU callbacks. They are expected to be in
  * a per-cpu list.
  */
-static void rcu_do_batch(struct list_head *list)
+static void rcu_do_batch(int cpu, struct list_head *list)
 {
 	struct list_head *entry;
 	struct rcu_head *head;
@@ -92,6 +94,7 @@ static void rcu_do_batch(struct list_hea
 		list_del(entry);
 		head = list_entry(entry, struct rcu_head, list);
 		head->func(head->arg);
+		RCU_nr_rcupdates(cpu)++;
 	}
 }
 
@@ -187,7 +190,7 @@ static void rcu_process_callbacks(unsign
 	}
 	rcu_check_quiescent_state();
 	if (!list_empty(&list))
-		rcu_do_batch(&list);
+		rcu_do_batch(cpu, &list);
 }
 
 void rcu_check_callbacks(int cpu, int user)
@@ -266,3 +269,44 @@ void synchronize_kernel(void)
 
 EXPORT_SYMBOL(call_rcu);
 EXPORT_SYMBOL(synchronize_kernel);
+
+#ifdef	CONFIG_PROC_FS
+
+static void *rcu_start(struct seq_file *m, loff_t *pos)
+{
+	static int cpu;
+	cpu = *pos;
+	return *pos < NR_CPUS ? &cpu : NULL;
+}
+		
+static void *rcu_next(struct seq_file *m, void *v, loff_t *pos) 
+{
+	++*pos;
+	return rcu_start(m, pos);
+}
+
+static void rcu_stop(struct seq_file *m, void *v)
+{
+}
+
+static int show_rcu(struct seq_file *m, void *v)
+{
+	int cpu = *(int *)v;
+
+	if (!cpu_online(cpu))
+		return 0;
+	seq_printf(m, "CPU : %d\n", cpu);
+	seq_printf(m, "RCU requests : %ld\n", RCU_nr_rcureqs(cpu));
+	seq_printf(m, "RCU updates : %ld\n\n", RCU_nr_rcupdates(cpu));
+	return 0;
+}
+
+struct seq_operations rcu_op = {
+	.start	= rcu_start,
+	.next	= rcu_next,
+	.stop	= rcu_stop,
+	.show	= show_rcu,
+};
+
+#endif
+
diff -puN Documentation/filesystems/proc.txt~rcu-stats Documentation/filesystems/proc.txt
--- 25/Documentation/filesystems/proc.txt~rcu-stats	Tue Mar 18 15:07:32 2003
+++ 25-akpm/Documentation/filesystems/proc.txt	Tue Mar 18 15:07:32 2003
@@ -222,6 +222,7 @@ Table 1-3: Kernel info in /proc 
  partitions  Table of partitions known to the system           
  pci	     Depreciated info of PCI bus (new way -> /proc/bus/pci/, 
              decoupled by lspci					(2.4)
+ rcu	     Read-Copy Update information			(2.5)
  rtc         Real time clock                                   
  scsi        SCSI info (see text)                              
  slabinfo    Slab pool info                                    
@@ -346,6 +347,9 @@ available.  In this case, there are 0 ch
 ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE 
 available in ZONE_NORMAL, etc... 
 
+The rcu file gives information about Read-Copy Update synchronization
+primitive. It indicates the number for RCU requests and actual
+updates for every CPU.
 
 1.3 IDE devices in /proc/ide
 ----------------------------

_