]> git.hungrycats.org Git - linux/commitdiff
[PATCH] /proc/slabinfo cleanup (seq_...)
authorAlexander Viro <viro@math.psu.edu>
Sat, 9 Feb 2002 14:18:05 +0000 (06:18 -0800)
committerDavid S. Miller <davem@redhat.com>
Sat, 9 Feb 2002 14:18:05 +0000 (06:18 -0800)
Straightforward rewrite to seq_file.

fs/proc/proc_misc.c
include/linux/slab.h
mm/slab.c

index e542e57a28c6ab4c44ac8519e7e03fd9bd3521c3..dbcbec45128642e4b22343b6bb39645b96b70830 100644 (file)
@@ -223,6 +223,20 @@ static struct file_operations proc_ksyms_operations = {
 };
 #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)
 {
@@ -551,6 +565,7 @@ void __init proc_misc_init(void)
                entry->proc_fops = &proc_kmsg_operations;
        create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
        create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+       create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 #ifdef CONFIG_MODULES
        create_seq_entry("ksyms", 0, &proc_ksyms_operations);
 #endif
@@ -575,8 +590,4 @@ void __init proc_misc_init(void)
                        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;
 }
index ceff3509f29eb276451bba17e9709d9c3dcd3d58..50cefbbc92a8f243cb31e74e26260da26be7f44f 100644 (file)
@@ -62,11 +62,6 @@ extern void *kmalloc(size_t, int);
 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);
-struct file;
-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;
index 9835c232b06664820379c660a6f008cafb4cc39d..26c7eb5aac015d5e086bc2e7a36b4734a339fb89 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -75,6 +75,7 @@
 #include       <linux/interrupt.h>
 #include       <linux/init.h>
 #include       <linux/compiler.h>
+#include       <linux/seq_file.h>
 #include       <asm/uaccess.h>
 
 /*
@@ -1869,31 +1870,56 @@ out:
 }
 
 #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 += sprintf(page+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
@@ -1901,116 +1927,89 @@ static int proc_getdata (char*page, char**start, off_t off, int count)
                                " (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;
-               const char *name; 
-               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;
 
-               name = cachep->name; 
-               {
-               char tmp; 
-               if (__get_user(tmp, name)) 
-                       name = "broken"; 
-               }       
+       name = cachep->name; 
+       {
+       char tmp; 
+       if (__get_user(tmp, name)) 
+               name = "broken"; 
+       }       
 
-               len += sprintf(page+len, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
-                       name, active_objs, num_objs, cachep->objsize,
-                       active_slabs, num_slabs, (1<<cachep->gfporder));
+       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 += sprintf(page+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
-               {
-                       unsigned int batchcount = cachep->batchcount;
-                       unsigned int limit;
-
-                       if (cc_data(cachep))
-                               limit = cc_data(cachep)->limit;
-                        else
-                               limit = 0;
-                       len += sprintf(page+len, " : %4u %4u",
-                                       limit, batchcount);
-               }
+       {
+               unsigned int batchcount = cachep->batchcount;
+               unsigned int limit;
+
+               if (cc_data(cachep))
+                       limit = cc_data(cachep)->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 += sprintf(page+len, " : %6lu %6lu %6lu %6lu",
-                                       allochit, allocmiss, freehit, freemiss);
-               }
+       {
+               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
-               len += sprintf(page+len,"\n");
-               spin_unlock_irq(&cachep->spinlock);
-               FIXUP(got_data_up);
-               p = cachep->next.next;
-       } while (p != &cache_cache.next);
-got_data_up:
-       up(&cache_chain_sem);
-
-got_data:
-       *start = page+off;
-       return len;
+       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
@@ -2020,28 +2019,24 @@ got_data:
  * 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;