]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: fixes for tracepoint cleanup
authorKris Van Hees <kris.van.hees@oracle.com>
Wed, 22 May 2013 23:25:48 +0000 (19:25 -0400)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 29 Jun 2015 21:41:44 +0000 (22:41 +0100)
Various fixes to handle tracepoint cleanup.  It is important to note that it is
most common that USDT providers will be cleaned up (asynchronously) when the
process/task they relate to is already gone.  We therefore cannot use a (pid,
addr) pair to identify the tracepoint for removal.  The new implementation
stores the (inode, offset) pair calculated right before registering the uprobe,
so that we can use that same pair again when unregistering.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
include/linux/dtrace_os.h
kernel/dtrace/dtrace_os.c

index b7a6bb4f85588f3310ba697f8810e24a2caed951..7f5430e30af0643fb967195250f0923baf868614 100644 (file)
@@ -7,6 +7,7 @@ typedef uint32_t dtrace_id_t;
 
 #ifndef HEADERS_CHECK
 
+#include <linux/uprobes.h>
 #include <asm/asm-offsets.h>
 
 #define DTRACE_IDNONE 0
@@ -79,14 +80,18 @@ extern void unregister_pid_provider(pid_t);
 extern void dtrace_task_init(struct task_struct *tsk);
 extern void dtrace_task_cleanup(struct task_struct *tsk);
 
-typedef struct uprobe_consumer fasttrap_machtp_t;
+typedef struct fasttrap_machtp {
+       struct inode            *fmtp_ino;
+       loff_t                  fmtp_off;
+       struct uprobe_consumer  fmtp_cns;
+} fasttrap_machtp_t;
 
 extern void (*dtrace_helpers_cleanup)(struct task_struct *);
 extern void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
 extern void (*dtrace_tracepoint_hit)(fasttrap_machtp_t *, struct pt_regs *);
 
 extern int dtrace_tracepoint_enable(pid_t, uintptr_t, fasttrap_machtp_t *);
-extern int dtrace_tracepoint_disable(pid_t, uintptr_t, fasttrap_machtp_t *);
+extern int dtrace_tracepoint_disable(pid_t, fasttrap_machtp_t *);
 
 #endif
 
index a7adcfd5e0a09a83d62ab5b487f511df4d57bdca..823960c37cbbb9cf0c8a6ef7315155140c2f404d 100644 (file)
@@ -978,12 +978,15 @@ void dtrace_task_cleanup(struct task_struct *tsk)
 
 static int handler(struct uprobe_consumer *self, struct pt_regs *regs)
 {
+       fasttrap_machtp_t       *mtp = container_of(self, fasttrap_machtp_t,
+                                                   fmtp_cns);
+
        pr_info("USDT-HANDLER: Called for PC %lx\n", GET_IP(regs));
        read_lock(&this_cpu_core->cpu_ft_lock);
        if (dtrace_tracepoint_hit == NULL)
                pr_warn("Fasttrap probes, but no handler\n");
        else
-               (*dtrace_tracepoint_hit)(self, regs);
+               (*dtrace_tracepoint_hit)(mtp, regs);
        read_unlock(&this_cpu_core->cpu_ft_lock);
 
        return 0;
@@ -998,6 +1001,9 @@ int dtrace_tracepoint_enable(pid_t pid, uintptr_t addr,
        loff_t                  off;
        int                     rc = 0;
 
+       mtp->fmtp_ino = NULL;
+       mtp->fmtp_off = 0;
+
        p = find_task_by_vpid(pid);
        if (!p) {
                pr_warn("PID %d not found\n", pid);
@@ -1016,59 +1022,53 @@ pr_info("DEBUG: PID %d: vma 0x%p, mapping 0x%p, inode 0x%p, offset 0x%llx\n", pi
 
        if (((uintptr_t)ino & 0xffff880000000000ULL) == 0xffff880000000000ULL) {
 pr_info("DEBUG: Registering uprobe...\n");
-               mtp->handler = handler;
-               rc = uprobe_register(ino, off, mtp);
+               mtp->fmtp_cns.handler = handler;
+
+               rc = uprobe_register(ino, off, &mtp->fmtp_cns);
 
                /*
                 * If successful, increment the count of the number of
                 * tracepoints active in the victim process.
                 */
-               if (rc == 0)
+               if (rc == 0) {
+                       mtp->fmtp_ino = ino;
+                       mtp->fmtp_off = off;
+
                        p->dtrace_tp_count++;
+               }
        }
 
        return rc;
 }
 EXPORT_SYMBOL(dtrace_tracepoint_enable);
 
-int dtrace_tracepoint_disable(pid_t pid, uintptr_t addr,
-                             fasttrap_machtp_t *mtp)
+int dtrace_tracepoint_disable(pid_t pid, fasttrap_machtp_t *mtp)
 {
        struct task_struct      *p;
-       struct inode            *ino;
-       struct vm_area_struct   *vma;
-       loff_t                  off;
 
-       if (!mtp || !mtp->handler) {
-               pr_warn("DTRACE: No handler for tracepoint\n");
+       if (!mtp || !mtp->fmtp_ino) {
+               pr_warn("DTRACE: Tracepoint was never enabled\n");
                return -ENOENT;
        }
 
-       p = find_task_by_vpid(pid);
-       if (!p) {
-               pr_warn("PID %d not found\n", pid);
-               return -ESRCH;
+       if (!mtp->fmtp_cns.handler) {
+               pr_warn("DTRACE: No handler for tracepoint\n");
+               return -ENOENT;
        }
 
-       vma = p->mm->mmap;
-       if (vma->vm_file == NULL) {
-               pr_warn("DTRACE: vma->vm_file is NULL\n");
-               return -ESRCH;
-       }
+pr_info("DEBUG: Unregistering uprobe...\n");
+       uprobe_unregister(mtp->fmtp_ino, mtp->fmtp_off, &mtp->fmtp_cns);
 
-       ino = vma->vm_file->f_mapping->host;
-       off = ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (addr - vma->vm_start);
-pr_info("DEBUG: PID %d: vma 0x%p, mapping 0x%p, inode 0x%p, offset 0x%llx\n", pid, vma, vma->vm_file->f_mapping, ino, off);
+       mtp->fmtp_ino = NULL;
+       mtp->fmtp_off = 0;
 
-       if (((uintptr_t)ino & 0xffff880000000000ULL) == 0xffff880000000000ULL) {
-pr_info("DEBUG: Registering uprobe...\n");
-               uprobe_unregister(ino, off, mtp);
-               /*
-                * Decrement the count of the number of tracepoints active in
-                * the victim process.
-                */
+       /*
+        * Decrement the count of the number of tracepoints active in
+        * the victim process (if it still exists).
+        */
+       p = find_task_by_vpid(pid);
+       if (p)
                p->dtrace_tp_count--;
-       }
 
        return 0;
 }