From: "Randy.Dunlap" <rddunlap@osdl.org>

Anton needs this for ppc64.  Things overflow with a huge number of CPUs.



 fs/proc/proc_misc.c |   68 +++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 54 insertions(+), 14 deletions(-)

diff -puN fs/proc/proc_misc.c~convert-proc-stat-to-seq_file fs/proc/proc_misc.c
--- 25/fs/proc/proc_misc.c~convert-proc-stat-to-seq_file	2003-08-31 22:27:58.000000000 -0700
+++ 25-akpm/fs/proc/proc_misc.c	2003-08-31 22:27:58.000000000 -0700
@@ -356,10 +356,9 @@ static struct file_operations proc_slabi
 	.release	= seq_release,
 };
 
-static int kstat_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+int show_stat(struct seq_file *p, void *v)
 {
-	int i, len;
+	int i;
 	extern unsigned long total_forks;
 	u64 jif;
 	unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
@@ -379,10 +378,10 @@ static int kstat_read_proc(char *page, c
 	jif = ((u64)now.tv_sec * HZ) + (now.tv_usec/(1000000/HZ)) - jif;
 	do_div(jif, HZ);
 
-	for (i = 0 ; i < NR_CPUS; i++) {
+	for (i = 0; i < NR_CPUS; i++) {
 		int j;
 
-		if(!cpu_online(i)) continue;
+		if (!cpu_online(i)) continue;
 		user += kstat_cpu(i).cpustat.user;
 		nice += kstat_cpu(i).cpustat.nice;
 		system += kstat_cpu(i).cpustat.system;
@@ -394,7 +393,7 @@ static int kstat_read_proc(char *page, c
 			sum += kstat_cpu(i).irqs[j];
 	}
 
-	len = sprintf(page, "cpu  %u %u %u %u %u %u %u\n",
+	seq_printf(p, "cpu  %u %u %u %u %u %u %u\n",
 		jiffies_to_clock_t(user),
 		jiffies_to_clock_t(nice),
 		jiffies_to_clock_t(system),
@@ -402,9 +401,9 @@ static int kstat_read_proc(char *page, c
 		jiffies_to_clock_t(iowait),
 		jiffies_to_clock_t(irq),
 		jiffies_to_clock_t(softirq));
-	for (i = 0 ; i < NR_CPUS; i++){
+	for (i = 0; i < NR_CPUS; i++){
 		if (!cpu_online(i)) continue;
-		len += sprintf(page + len, "cpu%d %u %u %u %u %u %u %u\n",
+		seq_printf(p, "cpu%d %u %u %u %u %u %u %u\n",
 			i,
 			jiffies_to_clock_t(kstat_cpu(i).cpustat.user),
 			jiffies_to_clock_t(kstat_cpu(i).cpustat.nice),
@@ -414,14 +413,25 @@ static int kstat_read_proc(char *page, c
 			jiffies_to_clock_t(kstat_cpu(i).cpustat.irq),
 			jiffies_to_clock_t(kstat_cpu(i).cpustat.softirq));
 	}
-	len += sprintf(page + len, "intr %u", sum);
+	seq_printf(p, "intr %u", sum);
 
 #if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
-	for (i = 0 ; i < NR_IRQS ; i++)
-		len += sprintf(page + len, " %u", kstat_irqs(i));
+{
+	static int last_irq = 0;
+
+	for (i = last_irq; i < NR_IRQS; i++) {
+		if (irq_desc[i].action) {
+			if (i > last_irq)
+				last_irq = i;
+		}
+	}
+
+	for (i = 0; i <= last_irq; i++)
+		seq_printf(p, " %u", kstat_irqs(i));
+}
 #endif
 
-	len += sprintf(page + len,
+	seq_printf(p,
 		"\nctxt %lu\n"
 		"btime %lu\n"
 		"processes %lu\n"
@@ -433,8 +443,38 @@ static int kstat_read_proc(char *page, c
 		nr_running(),
 		nr_iowait());
 
-	return proc_calc_metrics(page, start, off, count, eof, len);
+	return 0;
+}
+
+static int stat_open(struct inode *inode, struct file *file)
+{
+	unsigned size = 4096 * (1 + num_online_cpus() / 32);
+	char *buf;
+	struct seq_file *m;
+	int res;
+
+	/* don't ask for more than the kmalloc() max size, currently 128 KB */
+	if (size > 128 * 1024)
+		size = 128 * 1024;
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	res = single_open(file, show_stat, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
 }
+static struct file_operations proc_stat_operations = {
+	.open		= stat_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 static int devices_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
@@ -626,7 +666,6 @@ void __init proc_misc_init(void)
 #ifdef CONFIG_STRAM_PROC
 		{"stram",	stram_read_proc},
 #endif
-		{"stat",	kstat_read_proc},
 		{"devices",	devices_read_proc},
 		{"filesystems",	filesystems_read_proc},
 		{"cmdline",	cmdline_read_proc},
@@ -648,6 +687,7 @@ void __init proc_misc_init(void)
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 	create_seq_entry("partitions", 0, &proc_partitions_operations);
+	create_seq_entry("stat", 0, &proc_stat_operations);
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
 	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 	create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);

_