Index: mm/mmap.c =================================================================== RCS file: /home/mb/develop/linux/rsync/linux-2.5/mm/mmap.c,v retrieving revision 1.149 diff -u -p -r1.149 mmap.c --- mm/mmap.c 28 Oct 2004 15:17:10 -0000 1.149 +++ mm/mmap.c 20 Nov 2004 22:14:27 -0000 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,12 @@ */ #undef DEBUG_MM_RB +/* enable/disable find_vma() statistics. + * 1 => enabled + * 0 => disabled + */ +#define MMAP_FINDVMA_STATS 1 + /* description of effects of mapping type and prot in current implementation. * this is due to the limited x86 page protection hardware. The expected * behavior is in parens: @@ -1246,6 +1253,123 @@ get_unmapped_area(struct file *file, uns EXPORT_SYMBOL(get_unmapped_area); +#if MMAP_FINDVMA_STATS != 0 +static spinlock_t findvma_stat_lock = SPIN_LOCK_UNLOCKED; +static unsigned long findvma_stat_cachehit; +static unsigned long findvma_stat_cachemiss; +static unsigned long findvma_stat_fail; +static struct proc_dir_entry *findvma_stat_proc; + +static int findvma_stat_read(char *buf, char **start, off_t offset, int size, int *eof, void *data) +{ + int written; + unsigned long total = findvma_stat_cachehit + findvma_stat_cachemiss + findvma_stat_fail; + unsigned long hit_percent = findvma_stat_cachehit * 100 / total; + unsigned long miss_percent = findvma_stat_cachemiss * 100 / total; + unsigned long fail_percent = findvma_stat_fail * 100 / total; + + spin_lock(&findvma_stat_lock); + written = snprintf(buf, size, "findvma_stat_cachehit == %lu\n" + "findvma_stat_cachemiss == %lu\n" + "findvma_stat_fail == %lu\n" + "cachehit percentage == %lu%%\n" + "cachemiss percentage == %lu%%\n" + "fail percentage == %lu%%\n", + findvma_stat_cachehit, + findvma_stat_cachemiss, + findvma_stat_fail, + hit_percent, + miss_percent, + fail_percent); + spin_unlock(&findvma_stat_lock); + *eof = 1; + return written; +} + +static int findvma_stat_write(struct file *f, const char __user *buf, unsigned long cnt, void *data) +{ + int ret = -EINVAL; + char *kbuf; + + if (cnt < 1) + goto out; + + kbuf = kmalloc(cnt, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto out; + } + if (copy_from_user(kbuf, buf, cnt)) { + ret = -EFAULT; + goto out_free; + } + if (*kbuf == 'c') { + /* clear find_vma() statistics. */ + spin_lock(&findvma_stat_lock); + findvma_stat_cachehit = 0; + findvma_stat_cachemiss = 0; + findvma_stat_fail = 0; + spin_unlock(&findvma_stat_lock); + ret = cnt; + } +out_free: + kfree(kbuf); +out: + return ret; +} + +static void findvma_stat_init(void) +{ + static int already_tried = 0; + if (already_tried) + return; + printk("initializing find_vma() statistics... "); + findvma_stat_proc = create_proc_entry("findvma_stat", S_IRUGO | S_IWUSR, 0); + if (!findvma_stat_proc) { + printk("FAILED.\n"); + already_tried = 1; + return; + } + findvma_stat_proc->read_proc = findvma_stat_read; + findvma_stat_proc->write_proc = findvma_stat_write; + findvma_stat_proc->data = 0; + printk("Ok.\n"); +} + +static inline void findvma_stat_inc_cachehit(void) +{ + spin_lock(&findvma_stat_lock); + if (!findvma_stat_proc) + findvma_stat_init(); + findvma_stat_cachehit++; + spin_unlock(&findvma_stat_lock); +} + +static inline void findvma_stat_inc_cachemiss(void) +{ + spin_lock(&findvma_stat_lock); + if (!findvma_stat_proc) + findvma_stat_init(); + findvma_stat_cachemiss++; + spin_unlock(&findvma_stat_lock); +} + + +static inline void findvma_stat_inc_fail(void) +{ + spin_lock(&findvma_stat_lock); + if (unlikely(!findvma_stat_proc)) + findvma_stat_init(); + findvma_stat_fail++; + spin_unlock(&findvma_stat_lock); +} + +#else /* MMAP_FINDVMA_STATS */ +# define findvma_stat_inc_cachehit() do { } while (0) +# define findvma_stat_inc_cachemiss() do { } while (0) +# define findvma_stat_inc_fail() do { } while (0) +#endif /* MMAP_FINDVMA_STATS */ + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) { @@ -1275,10 +1399,15 @@ struct vm_area_struct * find_vma(struct } else rb_node = rb_node->rb_right; } - if (vma) + if (vma) { mm->mmap_cache = vma; - } + findvma_stat_inc_cachemiss(); + } + } else + findvma_stat_inc_cachehit(); } + if (!vma) + findvma_stat_inc_fail(); return vma; }