aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2008-04-28 05:12:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:21 -0400
commita10aa579878fc6f9cd17455067380bbdf1d53c91 (patch)
treec42fbb1e9422e5334c2207cafed4a2b5b1ad16c4
parentb45445684198a946b587732265692e6495993abf (diff)
vmalloc: show vmalloced areas via /proc/vmallocinfo
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>
-rw-r--r--fs/proc/proc_misc.c17
-rw-r--r--include/linux/vmalloc.h2
-rw-r--r--mm/vmalloc.c76
3 files changed, 94 insertions, 1 deletions
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 2d563979cb02..441a32f0e5f2 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -456,6 +456,20 @@ static const struct file_operations proc_slabstats_operations = {
456#endif 456#endif
457#endif 457#endif
458 458
459#ifdef CONFIG_MMU
460static int vmalloc_open(struct inode *inode, struct file *file)
461{
462 return seq_open(file, &vmalloc_op);
463}
464
465static const struct file_operations proc_vmalloc_operations = {
466 .open = vmalloc_open,
467 .read = seq_read,
468 .llseek = seq_lseek,
469 .release = seq_release,
470};
471#endif
472
459static int show_stat(struct seq_file *p, void *v) 473static int show_stat(struct seq_file *p, void *v)
460{ 474{
461 int i; 475 int i;
@@ -869,6 +883,9 @@ void __init proc_misc_init(void)
869 create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations); 883 create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
870#endif 884#endif
871#endif 885#endif
886#ifdef CONFIG_MMU
887 proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
888#endif
872 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); 889 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
873 create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops); 890 create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
874 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); 891 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index ce8e7da05807..7f3adfda337a 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -87,4 +87,6 @@ extern void free_vm_area(struct vm_struct *area);
87extern rwlock_t vmlist_lock; 87extern rwlock_t vmlist_lock;
88extern struct vm_struct *vmlist; 88extern struct vm_struct *vmlist;
89 89
90extern const struct seq_operations vmalloc_op;
91
90#endif /* _LINUX_VMALLOC_H */ 92#endif /* _LINUX_VMALLOC_H */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ecf91f8034bf..afa550f66537 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -14,7 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17 17#include <linux/seq_file.h>
18#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
19 19
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
@@ -873,3 +873,77 @@ void free_vm_area(struct vm_struct *area)
873 kfree(area); 873 kfree(area);
874} 874}
875EXPORT_SYMBOL_GPL(free_vm_area); 875EXPORT_SYMBOL_GPL(free_vm_area);
876
877
878#ifdef CONFIG_PROC_FS
879static void *s_start(struct seq_file *m, loff_t *pos)
880{
881 loff_t n = *pos;
882 struct vm_struct *v;
883
884 read_lock(&vmlist_lock);
885 v = vmlist;
886 while (n > 0 && v) {
887 n--;
888 v = v->next;
889 }
890 if (!n)
891 return v;
892
893 return NULL;
894
895}
896
897static void *s_next(struct seq_file *m, void *p, loff_t *pos)
898{
899 struct vm_struct *v = p;
900
901 ++*pos;
902 return v->next;
903}
904
905static void s_stop(struct seq_file *m, void *p)
906{
907 read_unlock(&vmlist_lock);
908}
909
910static int s_show(struct seq_file *m, void *p)
911{
912 struct vm_struct *v = p;
913
914 seq_printf(m, "0x%p-0x%p %7ld",
915 v->addr, v->addr + v->size, v->size);
916
917 if (v->nr_pages)
918 seq_printf(m, " pages=%d", v->nr_pages);
919
920 if (v->phys_addr)
921 seq_printf(m, " phys=%lx", v->phys_addr);
922
923 if (v->flags & VM_IOREMAP)
924 seq_printf(m, " ioremap");
925
926 if (v->flags & VM_ALLOC)
927 seq_printf(m, " vmalloc");
928
929 if (v->flags & VM_MAP)
930 seq_printf(m, " vmap");
931
932 if (v->flags & VM_USERMAP)
933 seq_printf(m, " user");
934
935 if (v->flags & VM_VPAGES)
936 seq_printf(m, " vpages");
937
938 seq_putc(m, '\n');
939 return 0;
940}
941
942const struct seq_operations vmalloc_op = {
943 .start = s_start,
944 .next = s_next,
945 .stop = s_stop,
946 .show = s_show,
947};
948#endif
949