public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Benjamin LaHaise <bcrl@redhat.com>
To: Tom Vier <tmv@comcast.net>
Cc: linux-kernel@vger.kernel.org
Subject: Re: /proc/slab garbage
Date: Sat, 1 Jun 2002 15:02:53 -0400	[thread overview]
Message-ID: <20020601150253.A5566@redhat.com> (raw)
In-Reply-To: <Pine.LNX.4.21.0205281905260.7798-100000@freak.distro.conectiva> <20020601184737.GA618@zero>

On Sat, Jun 01, 2002 at 02:47:37PM -0400, Tom Vier wrote:
> when i cat /proc/slabinfo, after the normal info, it's spits out garbage;
> seemingly random memory contents. it's printing past the end of the buffer.
> i can email an example upon request.
> 
> Linux zero 2.4.19-pre9 #1 Tue May 28 20:54:41 EDT 2002 alpha unknown

The patch below should fix it properly: it's a backport of Al Viro's 
seqfile patch for slabinfo.  The first part also reverts the vnsprintf 
changes made previously as seq file relies on C99 style behaviour 
of snprintf.  It's against a 2.4.19ish tree, but I've not checked 
that it applies against 2.4.19-pre9.

		-ben
-- 
"You will be reincarnated as a toad; and you will be much happier."

diff -urN linux/lib/vsprintf.c linux.diff/lib/vsprintf.c
--- linux/lib/vsprintf.c	Mon May 27 17:51:27 2002
+++ linux.diff/lib/vsprintf.c	Mon May 27 17:54:21 2002
@@ -172,41 +172,50 @@
 	if (!(type&(ZEROPAD+LEFT))) {
 		while(size-->0) {
 			if (buf <= end)
-				*buf++ = ' ';
+				*buf = ' ';
+			++buf;
 		}
 	}
 	if (sign) {
 		if (buf <= end)
-			*buf++ = sign;
+			*buf = sign;
+		++buf;
 	}
 	if (type & SPECIAL) {
 		if (base==8) {
 			if (buf <= end)
-				*buf++ = '0';
+				*buf = '0';
+			++buf;
 		} else if (base==16) {
 			if (buf <= end)
-				*buf++ = '0';
+				*buf = '0';
+			++buf;
 			if (buf <= end)
-				*buf++ = digits[33];
+				*buf = digits[33];
+			++buf;
 		}
 	}
 	if (!(type & LEFT)) {
 		while (size-- > 0) {
 			if (buf <= end)
-				*buf++ = c;
+				*buf = c;
+			++buf;
 		}
 	}
 	while (i < precision--) {
 		if (buf <= end)
-			*buf++ = '0';
+			*buf = '0';
+		++buf;
 	}
 	while (i-- > 0) {
 		if (buf <= end)
-			*buf++ = tmp[i];
+			*buf = tmp[i];
+		++buf;
 	}
 	while (size-- > 0) {
 		if (buf <= end)
-			*buf++ = ' ';
+			*buf = ' ';
+		++buf;
 	}
 	return buf;
 }
@@ -238,10 +247,6 @@
 				/* 'z' support added 23/7/1999 S.H.    */
 				/* 'z' changed to 'Z' --davidm 1/25/99 */
 
-	/* Enforce absolute minimum size: one character + the trailing 0 */
-	if (size < 2)
-		return 0;
-
 	str = buf;
 	end = buf + size - 1;
 
@@ -253,7 +258,8 @@
 	for (; *fmt ; ++fmt) {
 		if (*fmt != '%') {
 			if (str <= end)
-				*str++ = *fmt;
+				*str = *fmt;
+			++str;
 			continue;
 		}
 
@@ -317,15 +323,18 @@
 				if (!(flags & LEFT)) {
 					while (--field_width > 0) {
 						if (str <= end)
-							*str++ = ' ';
+							*str = ' ';
+						++str;
 					}
 				}
 				c = (unsigned char) va_arg(args, int);
 				if (str <= end)
-					*str++ = c;
+					*str = c;
+				++str;
 				while (--field_width > 0) {
 					if (str <= end)
-						*str++ = ' ';
+						*str = ' ';
+					++str;
 				}
 				continue;
 
@@ -339,16 +348,19 @@
 				if (!(flags & LEFT)) {
 					while (len < field_width--) {
 						if (str <= end)
-							*str++ = ' ';
+							*str = ' ';
+						++str;
 					}
 				}
 				for (i = 0; i < len; ++i) {
 					if (str <= end)
-						*str++ = *s++;
+						*str = *s;
+					++str; ++s;
 				}
 				while (len < field_width--) {
 					if (str <= end)
-						*str++ = ' ';
+						*str = ' ';
+					++str;
 				}
 				continue;
 
@@ -380,7 +392,8 @@
 
 			case '%':
 				if (str <= end)
-					*str++ = '%';
+					*str = '%';
+				++str;
 				continue;
 
 				/* integer number formats - set up the flags and "break" */
@@ -402,10 +415,12 @@
 
 			default:
 				if (str <= end)
-					*str++ = '%';
+					*str = '%';
+				++str;
 				if (*fmt) {
 					if (str <= end)
-						*str++ = *fmt;
+						*str = *fmt;
+					++str;
 				} else {
 					--fmt;
 				}
diff -urN linux.orig/fs/proc/proc_misc.c linux.work/fs/proc/proc_misc.c
--- linux.orig/fs/proc/proc_misc.c	Mon May 27 17:14:07 2002
+++ linux.work/fs/proc/proc_misc.c	Mon May 27 17:14:39 2002
@@ -289,6 +289,20 @@
 };
 #endif
 
+extern struct seq_operations slabinfo_op;
+extern ssize_t slabinfo_write(struct file *, const char *, size_t, loff_t *);
+static int slabinfo_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &slabinfo_op);
+}
+static struct file_operations proc_slabinfo_operations = {
+	open:		slabinfo_open,
+	read:		seq_read,
+	write:		slabinfo_write,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
+
 static int kstat_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
@@ -589,6 +603,7 @@
 	if (entry)
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 #ifdef CONFIG_MODULES
 	create_seq_entry("ksyms", 0, &proc_ksyms_operations);
 #endif
@@ -613,8 +628,4 @@
 			entry->proc_fops = &ppc_htab_operations;
 	}
 #endif
-	entry = create_proc_read_entry("slabinfo", S_IWUSR | S_IRUGO, NULL,
-				       slabinfo_read_proc, NULL);
-	if (entry)
-		entry->write_proc = slabinfo_write_proc;
 }
diff -urN linux.orig/include/linux/slab.h linux.work/include/linux/slab.h
--- linux.orig/include/linux/slab.h	Mon May 27 17:14:07 2002
+++ linux.work/include/linux/slab.h	Mon May 27 17:14:39 2002
@@ -62,10 +62,6 @@
 extern void kfree(const void *);
 
 extern int FASTCALL(kmem_cache_reap(int));
-extern int slabinfo_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data);
-extern int slabinfo_write_proc(struct file *file, const char *buffer,
-			   unsigned long count, void *data);
 
 /* System wide caches */
 extern kmem_cache_t	*vm_area_cachep;
diff -urN linux.orig/mm/slab.c linux.work/mm/slab.c
--- linux.orig/mm/slab.c	Mon May 27 17:14:07 2002
+++ linux.work/mm/slab.c	Mon May 27 17:14:39 2002
@@ -72,6 +72,8 @@
 #include	<linux/slab.h>
 #include	<linux/interrupt.h>
 #include	<linux/init.h>
+#include	<linux/compiler.h>
+#include	<linux/seq_file.h>
 #include	<asm/uaccess.h>
 
 /*
@@ -1849,31 +1851,56 @@
 }
 
 #ifdef CONFIG_PROC_FS
-/* /proc/slabinfo
- *	cache-name num-active-objs total-objs
- *	obj-size num-active-slabs total-slabs
- *	num-pages-per-slab
- */
-#define FIXUP(t)				\
-	do {					\
-		if (len <= off) {		\
-			off -= len;		\
-			len = 0;		\
-		} else {			\
-			if (len-off >= count)	\
-				goto t;		\
-		}				\
-	} while (0)
 
-static int proc_getdata (char*page, char**start, off_t off, int count)
+static void *s_start(struct seq_file *m, loff_t *pos)
 {
+	loff_t n = *pos;
 	struct list_head *p;
-	int len = 0;
 
-	/* Output format version, so at least we can change it without _too_
-	 * many complaints.
-	 */
-	len += snprintf(page+len, PAGE_SIZE-len, "slabinfo - version: 1.1"
+	down(&cache_chain_sem);
+	if (!n)
+		return (void *)1;
+	p = &cache_cache.next;
+	while (--n) {
+		p = p->next;
+		if (p == &cache_cache.next)
+			return NULL;
+	}
+	return list_entry(p, kmem_cache_t, next);
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	kmem_cache_t *cachep = p;
+	++*pos;
+	if (p == (void *)1)
+		return &cache_cache;
+	cachep = list_entry(cachep->next.next, kmem_cache_t, next);
+	return cachep == &cache_cache ? NULL : cachep;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+	up(&cache_chain_sem);
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+	kmem_cache_t *cachep = p;
+	struct list_head *q;
+	slab_t		*slabp;
+	unsigned long	active_objs;
+	unsigned long	num_objs;
+	unsigned long	active_slabs = 0;
+	unsigned long	num_slabs;
+	const char *name; 
+
+	if (p == (void*)1) {
+		/*
+		 * Output format version, so at least we can change it
+		 * without _too_ many complaints.
+		 */
+		seq_puts(m, "slabinfo - version: 1.1"
 #if STATS
 				" (statistics)"
 #endif
@@ -1881,117 +1908,91 @@
 				" (SMP)"
 #endif
 				"\n");
-	FIXUP(got_data);
-
-	down(&cache_chain_sem);
-	p = &cache_cache.next;
-	do {
-		kmem_cache_t	*cachep;
-		struct list_head *q;
-		slab_t		*slabp;
-		unsigned long	active_objs;
-		unsigned long	num_objs;
-		unsigned long	active_slabs = 0;
-		unsigned long	num_slabs;
-		cachep = list_entry(p, kmem_cache_t, next);
+		return 0;
+	}
 
-		spin_lock_irq(&cachep->spinlock);
-		active_objs = 0;
-		num_slabs = 0;
-		list_for_each(q,&cachep->slabs_full) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse != cachep->num)
-				BUG();
-			active_objs += cachep->num;
-			active_slabs++;
-		}
-		list_for_each(q,&cachep->slabs_partial) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse == cachep->num || !slabp->inuse)
-				BUG();
-			active_objs += slabp->inuse;
-			active_slabs++;
-		}
-		list_for_each(q,&cachep->slabs_free) {
-			slabp = list_entry(q, slab_t, list);
-			if (slabp->inuse)
-				BUG();
-			num_slabs++;
-		}
-		num_slabs+=active_slabs;
-		num_objs = num_slabs*cachep->num;
+	spin_lock_irq(&cachep->spinlock);
+	active_objs = 0;
+	num_slabs = 0;
+	list_for_each(q,&cachep->slabs_full) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse != cachep->num)
+			BUG();
+		active_objs += cachep->num;
+		active_slabs++;
+	}
+	list_for_each(q,&cachep->slabs_partial) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse == cachep->num || !slabp->inuse)
+			BUG();
+		active_objs += slabp->inuse;
+		active_slabs++;
+	}
+	list_for_each(q,&cachep->slabs_free) {
+		slabp = list_entry(q, slab_t, list);
+		if (slabp->inuse)
+			BUG();
+		num_slabs++;
+	}
+	num_slabs+=active_slabs;
+	num_objs = num_slabs*cachep->num;
 
-		len += snprintf(page+len, PAGE_SIZE-len,
-			"%-17s %6lu %6lu %6u %4lu %4lu %4u",
-			cachep->name, active_objs, num_objs, cachep->objsize,
-			active_slabs, num_slabs, (1<<cachep->gfporder));
+	name = cachep->name; 
+	{
+	char tmp; 
+	if (__get_user(tmp, name)) 
+		name = "broken"; 
+	}       
+
+	seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
+		name, active_objs, num_objs, cachep->objsize,
+		active_slabs, num_slabs, (1<<cachep->gfporder));
 
 #if STATS
-		{
-			unsigned long errors = cachep->errors;
-			unsigned long high = cachep->high_mark;
-			unsigned long grown = cachep->grown;
-			unsigned long reaped = cachep->reaped;
-			unsigned long allocs = cachep->num_allocations;
-
-			len += snprintf(page+len, PAGE_SIZE-len,
-					" : %6lu %7lu %5lu %4lu %4lu",
-					high, allocs, grown, reaped, errors);
-		}
+	{
+		unsigned long errors = cachep->errors;
+		unsigned long high = cachep->high_mark;
+		unsigned long grown = cachep->grown;
+		unsigned long reaped = cachep->reaped;
+		unsigned long allocs = cachep->num_allocations;
+
+		seq_printf(m, " : %6lu %7lu %5lu %4lu %4lu",
+				high, allocs, grown, reaped, errors);
+	}
 #endif
 #ifdef CONFIG_SMP
-		{
-			cpucache_t *cc = cc_data(cachep);
-			unsigned int batchcount = cachep->batchcount;
-			unsigned int limit;
-
-			if (cc)
-				limit = cc->limit;
-			else
-				limit = 0;
-			len += snprintf(page+len, PAGE_SIZE-len, " : %4u %4u",
-					limit, batchcount);
-		}
+	{
+		cpucache_t *cc = cc_data(cachep);
+		unsigned int batchcount = cachep->batchcount;
+		unsigned int limit;
+
+		if (cc)
+			limit = cc->limit;
+		else
+			limit = 0;
+		seq_printf(m, " : %4u %4u",
+				limit, batchcount);
+	}
 #endif
 #if STATS && defined(CONFIG_SMP)
-		{
-			unsigned long allochit = atomic_read(&cachep->allochit);
-			unsigned long allocmiss = atomic_read(&cachep->allocmiss);
-			unsigned long freehit = atomic_read(&cachep->freehit);
-			unsigned long freemiss = atomic_read(&cachep->freemiss);
-			len += snprintf(page+len, PAGE_SIZE-len,
-					" : %6lu %6lu %6lu %6lu",
-					allochit, allocmiss, freehit, freemiss);
-		}
-#endif
-		len += snprintf(page+len, PAGE_SIZE-len, "\n");
-		spin_unlock_irq(&cachep->spinlock);
-		FIXUP(got_data_up);
-		p = cachep->next.next;
-		if (len > PAGE_SIZE - 512)
-			break;
-	} while (p != &cache_cache.next);
-got_data_up:
-	up(&cache_chain_sem);
-
-got_data:
-	if (off < len) {
-		*start = page+off;
-		return len;
+	{
+		unsigned long allochit = atomic_read(&cachep->allochit);
+		unsigned long allocmiss = atomic_read(&cachep->allocmiss);
+		unsigned long freehit = atomic_read(&cachep->freehit);
+		unsigned long freemiss = atomic_read(&cachep->freemiss);
+		seq_printf(m, " : %6lu %6lu %6lu %6lu",
+				allochit, allocmiss, freehit, freemiss);
 	}
+#endif
+	spin_unlock_irq(&cachep->spinlock);
+	seq_putc(m, '\n');
 	return 0;
 }
 
 /**
- * slabinfo_read_proc - generates /proc/slabinfo
- * @page: scratch area, one page long
- * @start: pointer to the pointer to the output buffer
- * @off: offset within /proc/slabinfo the caller is interested in
- * @count: requested len in bytes
- * @eof: eof marker
- * @data: unused
+ * slabinfo_op - iterator that generates /proc/slabinfo
  *
- * The contents of the buffer are
+ * Output layout:
  * cache-name
  * num-active-objs
  * total-objs
@@ -2001,28 +2002,24 @@
  * num-pages-per-slab
  * + further values on SMP and with statistics enabled
  */
-int slabinfo_read_proc (char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = proc_getdata(page, start, off, count);
-	len -= (*start-page);
-	if (len <= count)
-		*eof = 1;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
-}
+
+struct seq_operations slabinfo_op = {
+	start:	s_start,
+	next:	s_next,
+	stop:	s_stop,
+	show:	s_show
+};
 
 #define MAX_SLABINFO_WRITE 128
 /**
- * slabinfo_write_proc - SMP tuning for the slab allocator
+ * slabinfo_write - SMP tuning for the slab allocator
  * @file: unused
  * @buffer: user buffer
  * @count: data len
  * @data: unused
  */
-int slabinfo_write_proc (struct file *file, const char *buffer,
-				unsigned long count, void *data)
+ssize_t slabinfo_write(struct file *file, const char *buffer,
+				size_t count, loff_t *ppos)
 {
 #ifdef CONFIG_SMP
 	char kbuf[MAX_SLABINFO_WRITE+1], *tmp;

      reply	other threads:[~2002-06-01 19:02 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-05-28 22:06 Linux 2.4.19-pre9 Marcelo Tosatti
2002-05-29  5:37 ` Lars Marowsky-Bree
2002-05-29  6:06   ` Greg KH
2002-05-29 12:50     ` Linux 2.4.19-pre9, still USB freeze Stephan von Krawczynski
2002-05-29 13:55       ` Peter Wächtler
2002-05-29 13:58         ` Stephan von Krawczynski
2002-05-29 14:08           ` Peter Wächtler
2002-05-29 17:14       ` Greg KH
2002-06-04 18:24       ` Bill Davidsen
2002-05-30  0:34   ` Linux 2.4.19-pre9 Marcelo Tosatti
2002-05-30  1:23     ` David S. Miller
2002-05-30  1:02       ` Marcelo Tosatti
2002-06-04 18:35       ` Bill Davidsen
2002-05-29 12:02 ` lk-changelog.pl (new version 0.21) vs. Linux 2.4.19-pre9 ChangeLog Matthias Andree
2002-05-29 12:10 ` Linux 2.4.19-pre9 ChangeLog Summary Matthias Andree
2002-05-29 23:25 ` Linux 2.4.19-pre9 J.A. Magallon
2002-05-30  9:35   ` Meelis Roos
2002-06-01 18:47 ` /proc/slab garbage Tom Vier
2002-06-01 19:02   ` Benjamin LaHaise [this message]

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=20020601150253.A5566@redhat.com \
    --to=bcrl@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tmv@comcast.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox