vmalloc: show vmalloced areas via /proc/vmallocinfo
authorChristoph Lameter <clameter@sgi.com>
Mon, 28 Apr 2008 09:12:40 +0000 (02:12 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Apr 2008 15:58:21 +0000 (08:58 -0700)
Implement a new proc file that allows the display of the currently allocated
vmalloc memory.

It allows to see the users of vmalloc.  That is important if vmalloc space is
scarce (i386 for example).

And it's going to be important for the compound page fallback to vmalloc.
Many of the current users can be switched to use compound pages with fallback.
 This means that the number of users of vmalloc is reduced and page tables no
longer necessary to access the memory.  /proc/vmallocinfo allows to review how
that reduction occurs.

If memory becomes fragmented and larger order allocations are no longer
possible then /proc/vmallocinfo allows to see which compound page allocations
fell back to virtual compound pages.  That is important for new users of
virtual compound pages.  Such as order 1 stack allocation etc that may
fallback to virtual compound pages in the future.

/proc/vmallocinfo permissions are made readable-only-by-root to avoid possible
information leakage.

[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: CONFIG_MMU=n build fix]
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Hugh Dickins <hugh@veritas.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/proc/proc_misc.c
include/linux/vmalloc.h
mm/vmalloc.c

index 2d563979cb025412dce7847bd79979c34a8456eb..441a32f0e5f2f4460c243ad17ea29249bbd38728 100644 (file)
@@ -456,6 +456,20 @@ static const struct file_operations proc_slabstats_operations = {
 #endif
 #endif
 
+#ifdef CONFIG_MMU
+static int vmalloc_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &vmalloc_op);
+}
+
+static const struct file_operations proc_vmalloc_operations = {
+       .open           = vmalloc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+#endif
+
 static int show_stat(struct seq_file *p, void *v)
 {
        int i;
@@ -868,6 +882,9 @@ void __init proc_misc_init(void)
 #ifdef CONFIG_DEBUG_SLAB_LEAK
        create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
 #endif
+#endif
+#ifdef CONFIG_MMU
+       proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
 #endif
        create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
        create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
index ce8e7da05807b7e69f0967b6c78620a4c202d6b7..7f3adfda337a102c15c08051b213ae687b908a90 100644 (file)
@@ -87,4 +87,6 @@ extern void free_vm_area(struct vm_struct *area);
 extern rwlock_t vmlist_lock;
 extern struct vm_struct *vmlist;
 
+extern const struct seq_operations vmalloc_op;
+
 #endif /* _LINUX_VMALLOC_H */
index ecf91f8034bf0e8cb2c3effb63609fd3c8405cdb..afa550f66537a9d496aaa677d9d761c723106ebc 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-
+#include <linux/seq_file.h>
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
@@ -873,3 +873,77 @@ void free_vm_area(struct vm_struct *area)
        kfree(area);
 }
 EXPORT_SYMBOL_GPL(free_vm_area);
+
+
+#ifdef CONFIG_PROC_FS
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+       loff_t n = *pos;
+       struct vm_struct *v;
+
+       read_lock(&vmlist_lock);
+       v = vmlist;
+       while (n > 0 && v) {
+               n--;
+               v = v->next;
+       }
+       if (!n)
+               return v;
+
+       return NULL;
+
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+       struct vm_struct *v = p;
+
+       ++*pos;
+       return v->next;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+       read_unlock(&vmlist_lock);
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+       struct vm_struct *v = p;
+
+       seq_printf(m, "0x%p-0x%p %7ld",
+               v->addr, v->addr + v->size, v->size);
+
+       if (v->nr_pages)
+               seq_printf(m, " pages=%d", v->nr_pages);
+
+       if (v->phys_addr)
+               seq_printf(m, " phys=%lx", v->phys_addr);
+
+       if (v->flags & VM_IOREMAP)
+               seq_printf(m, " ioremap");
+
+       if (v->flags & VM_ALLOC)
+               seq_printf(m, " vmalloc");
+
+       if (v->flags & VM_MAP)
+               seq_printf(m, " vmap");
+
+       if (v->flags & VM_USERMAP)
+               seq_printf(m, " user");
+
+       if (v->flags & VM_VPAGES)
+               seq_printf(m, " vpages");
+
+       seq_putc(m, '\n');
+       return 0;
+}
+
+const struct seq_operations vmalloc_op = {
+       .start = s_start,
+       .next = s_next,
+       .stop = s_stop,
+       .show = s_show,
+};
+#endif
+