perf_counter: Generate mmap events for install_special_mapping()
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Fri, 5 Jun 2009 12:04:55 +0000 (14:04 +0200)
committerIngo Molnar <mingo@elte.hu>
Fri, 5 Jun 2009 12:46:41 +0000 (14:46 +0200)
In order to track the vdso also generate mmap events for
install_special_mapping().

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
include/linux/perf_counter.h
kernel/perf_counter.c
mm/mmap.c

index 6ca403acd4196566a5d9744b211708ec9cc99314..40dc0e273d9c4559aa975c665fc4f856808de3f0 100644 (file)
@@ -617,8 +617,13 @@ static inline int is_software_counter(struct perf_counter *counter)
 
 extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64);
 
-extern void perf_counter_mmap(unsigned long addr, unsigned long len,
-                             unsigned long pgoff, struct file *file);
+extern void __perf_counter_mmap(struct vm_area_struct *vma);
+
+static inline void perf_counter_mmap(struct vm_area_struct *vma)
+{
+       if (vma->vm_flags & VM_EXEC)
+               __perf_counter_mmap(vma);
+}
 
 extern void perf_counter_comm(struct task_struct *tsk);
 extern void perf_counter_fork(struct task_struct *tsk);
@@ -668,10 +673,7 @@ static inline void
 perf_swcounter_event(u32 event, u64 nr, int nmi,
                     struct pt_regs *regs, u64 addr)                    { }
 
-static inline void
-perf_counter_mmap(unsigned long addr, unsigned long len,
-                 unsigned long pgoff, struct file *file)               { }
-
+static inline void perf_counter_mmap(struct vm_area_struct *vma)       { }
 static inline void perf_counter_comm(struct task_struct *tsk)          { }
 static inline void perf_counter_fork(struct task_struct *tsk)          { }
 static inline void perf_counter_init(void)                             { }
index a5d3e2aedd2f107ad5bf5a74153e4679ca97ee42..37a5a241ca7eca0c1dc2ce07589271e839594f05 100644 (file)
@@ -2255,7 +2255,7 @@ out:
 }
 
 static void perf_output_copy(struct perf_output_handle *handle,
-                            void *buf, unsigned int len)
+                            const void *buf, unsigned int len)
 {
        unsigned int pages_mask;
        unsigned int offset;
@@ -2681,9 +2681,10 @@ void perf_counter_comm(struct task_struct *task)
  */
 
 struct perf_mmap_event {
-       struct file     *file;
-       char            *file_name;
-       int             file_size;
+       struct vm_area_struct   *vma;
+
+       const char              *file_name;
+       int                     file_size;
 
        struct {
                struct perf_event_header        header;
@@ -2744,11 +2745,12 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
 {
        struct perf_cpu_context *cpuctx;
        struct perf_counter_context *ctx;
-       struct file *file = mmap_event->file;
+       struct vm_area_struct *vma = mmap_event->vma;
+       struct file *file = vma->vm_file;
        unsigned int size;
        char tmp[16];
        char *buf = NULL;
-       char *name;
+       const char *name;
 
        if (file) {
                buf = kzalloc(PATH_MAX, GFP_KERNEL);
@@ -2762,6 +2764,15 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
                        goto got_name;
                }
        } else {
+               name = arch_vma_name(mmap_event->vma);
+               if (name)
+                       goto got_name;
+
+               if (!vma->vm_mm) {
+                       name = strncpy(tmp, "[vdso]", sizeof(tmp));
+                       goto got_name;
+               }
+
                name = strncpy(tmp, "//anon", sizeof(tmp));
                goto got_name;
        }
@@ -2791,8 +2802,7 @@ got_name:
        kfree(buf);
 }
 
-void perf_counter_mmap(unsigned long addr, unsigned long len,
-                      unsigned long pgoff, struct file *file)
+void __perf_counter_mmap(struct vm_area_struct *vma)
 {
        struct perf_mmap_event mmap_event;
 
@@ -2800,12 +2810,12 @@ void perf_counter_mmap(unsigned long addr, unsigned long len,
                return;
 
        mmap_event = (struct perf_mmap_event){
-               .file   = file,
+               .vma    = vma,
                .event  = {
                        .header = { .type = PERF_EVENT_MMAP, },
-                       .start  = addr,
-                       .len    = len,
-                       .pgoff  = pgoff,
+                       .start  = vma->vm_start,
+                       .len    = vma->vm_end - vma->vm_start,
+                       .pgoff  = vma->vm_pgoff,
                },
        };
 
index 6451ce2854b9f671bff0f3befe6a537807d3c5c6..8101de490c73941ab8815733a3899c614cdb8cb7 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1220,8 +1220,7 @@ munmap_back:
        if (correct_wcount)
                atomic_inc(&inode->i_writecount);
 out:
-       if (vm_flags & VM_EXEC)
-               perf_counter_mmap(addr, len, pgoff, file);
+       perf_counter_mmap(vma);
 
        mm->total_vm += len >> PAGE_SHIFT;
        vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
@@ -2309,6 +2308,8 @@ int install_special_mapping(struct mm_struct *mm,
 
        mm->total_vm += len >> PAGE_SHIFT;
 
+       perf_counter_mmap(vma);
+
        return 0;
 }