d_path: Make get_dcookie() use a struct path argument
[safe/jmp/linux-2.6] / drivers / oprofile / buffer_sync.c
index 745a141..b07ba2a 100644 (file)
@@ -26,7 +26,9 @@
 #include <linux/profile.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+
 #include "oprofile_stats.h"
 #include "event_buffer.h"
 #include "cpu_buffer.h"
@@ -43,13 +45,16 @@ static void process_task_mortuary(void);
  * list for processing. Only after two full buffer syncs
  * does the task eventually get freed, because by then
  * we are sure we will not reference it again.
+ * Can be invoked from softirq via RCU callback due to
+ * call_rcu() of the task struct, hence the _irqsave.
  */
 static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
 {
+       unsigned long flags;
        struct task_struct * task = data;
-       spin_lock(&task_mortuary);
+       spin_lock_irqsave(&task_mortuary, flags);
        list_add(&task->tasks, &dying_tasks);
-       spin_unlock(&task_mortuary);
+       spin_unlock_irqrestore(&task_mortuary, flags);
        return NOTIFY_OK;
 }
 
@@ -105,10 +110,10 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
                return 0;
 
        /* FIXME: should we process all CPU buffers ? */
-       down(&buffer_sem);
+       mutex_lock(&buffer_mutex);
        add_event_entry(ESCAPE_CODE);
        add_event_entry(MODULE_LOADED_CODE);
-       up(&buffer_sem);
+       mutex_unlock(&buffer_mutex);
 #endif
        return 0;
 }
@@ -182,23 +187,22 @@ void sync_stop(void)
        end_sync();
 }
 
+
 /* Optimisation. We can manage without taking the dcookie sem
  * because we cannot reach this code without at least one
  * dcookie user still being registered (namely, the reader
  * of the event buffer). */
-static inline unsigned long fast_get_dcookie(struct dentry * dentry,
-       struct vfsmount * vfsmnt)
+static inline unsigned long fast_get_dcookie(struct path *path)
 {
        unsigned long cookie;
-       if (dentry->d_cookie)
-               return (unsigned long)dentry;
-       get_dcookie(dentry, vfsmnt, &cookie);
+
+       if (path->dentry->d_cookie)
+               return (unsigned long)path->dentry;
+       get_dcookie(path, &cookie);
        return cookie;
 }
 
+
 /* Look up the dcookie for the task's first VM_EXECUTABLE mapping,
  * which corresponds loosely to "application name". This is
  * not strictly necessary but allows oprofile to associate
@@ -206,7 +210,7 @@ static inline unsigned long fast_get_dcookie(struct dentry * dentry,
  */
 static unsigned long get_exec_dcookie(struct mm_struct * mm)
 {
-       unsigned long cookie = 0;
+       unsigned long cookie = NO_COOKIE;
        struct vm_area_struct * vma;
  
        if (!mm)
@@ -217,8 +221,7 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm)
                        continue;
                if (!(vma->vm_flags & VM_EXECUTABLE))
                        continue;
-               cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                       vma->vm_file->f_vfsmnt);
+               cookie = fast_get_dcookie(&vma->vm_file->f_path);
                break;
        }
 
@@ -234,35 +237,41 @@ out:
  */
 static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
 {
-       unsigned long cookie = 0;
+       unsigned long cookie = NO_COOKIE;
        struct vm_area_struct * vma;
 
        for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
  
-               if (!vma->vm_file)
-                       continue;
-
                if (addr < vma->vm_start || addr >= vma->vm_end)
                        continue;
 
-               cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                       vma->vm_file->f_vfsmnt);
-               *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 
+               if (vma->vm_file) {
+                       cookie = fast_get_dcookie(&vma->vm_file->f_path);
+                       *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
+                               vma->vm_start;
+               } else {
+                       /* must be an anonymous map */
+                       *offset = addr;
+               }
+
                break;
        }
 
+       if (!vma)
+               cookie = INVALID_COOKIE;
+
        return cookie;
 }
 
 
-static unsigned long last_cookie = ~0UL;
+static unsigned long last_cookie = INVALID_COOKIE;
  
 static void add_cpu_switch(int i)
 {
        add_event_entry(ESCAPE_CODE);
        add_event_entry(CPU_SWITCH_CODE);
        add_event_entry(i);
-       last_cookie = ~0UL;
+       last_cookie = INVALID_COOKIE;
 }
 
 static void add_kernel_ctx_switch(unsigned int in_kernel)
@@ -317,7 +326,7 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
  
        cookie = lookup_dcookie(mm, s->eip, &offset);
  
-       if (!cookie) {
+       if (cookie == INVALID_COOKIE) {
                atomic_inc(&oprofile_stats.sample_lost_no_mapping);
                return 0;
        }
@@ -424,25 +433,22 @@ static void increment_tail(struct oprofile_cpu_buffer * b)
  */
 static void process_task_mortuary(void)
 {
-       struct list_head * pos;
-       struct list_head * pos2;
+       unsigned long flags;
+       LIST_HEAD(local_dead_tasks);
        struct task_struct * task;
+       struct task_struct * ttask;
 
-       spin_lock(&task_mortuary);
+       spin_lock_irqsave(&task_mortuary, flags);
 
-       list_for_each_safe(pos, pos2, &dead_tasks) {
-               task = list_entry(pos, struct task_struct, tasks);
-               list_del(&task->tasks);
-               free_task(task);
-       }
+       list_splice_init(&dead_tasks, &local_dead_tasks);
+       list_splice_init(&dying_tasks, &dead_tasks);
+
+       spin_unlock_irqrestore(&task_mortuary, flags);
 
-       list_for_each_safe(pos, pos2, &dying_tasks) {
-               task = list_entry(pos, struct task_struct, tasks);
+       list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) {
                list_del(&task->tasks);
-               list_add_tail(&task->tasks, &dead_tasks);
+               free_task(task);
        }
-
-       spin_unlock(&task_mortuary);
 }
 
 
@@ -494,7 +500,7 @@ void sync_buffer(int cpu)
        sync_buffer_state state = sb_buffer_start;
        unsigned long available;
 
-       down(&buffer_sem);
+       mutex_lock(&buffer_mutex);
  
        add_cpu_switch(cpu);
 
@@ -543,5 +549,5 @@ void sync_buffer(int cpu)
 
        mark_done(cpu);
 
-       up(&buffer_sem);
+       mutex_unlock(&buffer_mutex);
 }