uretprobes: Introduce uprobe_consumer->ret_handler()
authorAnton Arapov <anton@redhat.com>
Wed, 3 Apr 2013 16:00:31 +0000 (18:00 +0200)
committerOleg Nesterov <oleg@redhat.com>
Sat, 13 Apr 2013 13:31:53 +0000 (15:31 +0200)
Enclose return probes implementation, introduce ->ret_handler() and update
existing code to rely on ->handler() *and* ->ret_handler() for uprobe and
uretprobe respectively.

Signed-off-by: Anton Arapov <anton@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
include/linux/uprobes.h
kernel/events/uprobes.c

index 19612881399aebb6089e76ad7be2f4c42f716373..5c8d3290df41bf0944b1651f5ac24d085881437a 100644 (file)
@@ -46,6 +46,9 @@ enum uprobe_filter_ctx {
 
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
+       int (*ret_handler)(struct uprobe_consumer *self,
+                               unsigned long func,
+                               struct pt_regs *regs);
        bool (*filter)(struct uprobe_consumer *self,
                                enum uprobe_filter_ctx ctx,
                                struct mm_struct *mm);
index 7312503caf2e5b03c41cc426e994442445df8c51..eb384e90ac92b27f1eb2fde6fabfc2aca9b5f508 100644 (file)
@@ -838,6 +838,14 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        struct uprobe *uprobe;
        int ret;
 
+       /* Uprobe must have at least one set consumer */
+       if (!uc->handler && !uc->ret_handler)
+               return -EINVAL;
+
+       /* TODO: Implement return probes */
+       if (uc->ret_handler)
+               return -ENOSYS;
+
        /* Racy, just to catch the obvious mistakes */
        if (offset > i_size_read(inode))
                return -EINVAL;
@@ -1497,10 +1505,13 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 
        down_read(&uprobe->register_rwsem);
        for (uc = uprobe->consumers; uc; uc = uc->next) {
-               int rc = uc->handler(uc, regs);
+               int rc = 0;
 
-               WARN(rc & ~UPROBE_HANDLER_MASK,
-                       "bad rc=0x%x from %pf()\n", rc, uc->handler);
+               if (uc->handler) {
+                       rc = uc->handler(uc, regs);
+                       WARN(rc & ~UPROBE_HANDLER_MASK,
+                               "bad rc=0x%x from %pf()\n", rc, uc->handler);
+               }
                remove &= rc;
        }