commit 20744cb97a3e4aec63ba7b92ce4115170fd468d6
Author: Srikar Dronamraju <sri...@linux.vnet.ibm.com>
Date:   Wed Aug 19 12:26:15 2009 +0530

Use deferred registration facility for register_uprobe
    
Signed-off-by: Srikar Dronamraju <sri...@linux.vnet.ibm.com>
---
 kernel/utrace-gdb.c |   75 +++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 55 insertions(+), 20 deletions(-)

diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c
index 29e9c05..ac653fe 100644
--- a/kernel/utrace-gdb.c
+++ b/kernel/utrace-gdb.c
@@ -259,6 +259,37 @@ static bool can_gdb_handle_sigtrap(struct pt_regs *regs,
 void gdb_uprobe_handler(struct uprobe *up, struct pt_regs *regs)
 {
 }
+
+void gdb_register_complete(struct uprobe *up, int regflag, int ret)
+{
+       if (regflag) { /* register_uprobe */
+               struct gdb_uprobe *gup;
+               struct gdb_connection *gp = NULL, *p = NULL;
+
+               mutex_lock(&gdb_connections_mutex);
+               list_for_each_entry(p, &gdb_connections, link) {
+                       if (p->target == task_tgid_nr(current)) {
+                               gp = p;
+                               break;
+                       }
+               }
+               mutex_unlock(&gdb_connections_mutex);
+
+               if (!gp)
+                       return;
+
+               gup = container_of(up, struct gdb_uprobe, up);
+               if (ret) {
+                       /* register_uprobe failed */
+                       kfree(gup);
+                       return;
+               }
+               /* Dont bother to use a callback for unregister */
+               up->registration_callback = NULL;
+               INIT_LIST_HEAD(&gup->link);
+               list_add_tail(&gup->link, &gp->uprobes);
+       }
+}
 #endif /* CONFIG_HAVE_UPROBES */
 
 
@@ -1058,26 +1089,30 @@ static void handle_gdb_command_packet (struct 
gdb_connection *p, struct task_str
                                 }
                         }
                         
-                        if (gup == NULL) {
-                                gup = kzalloc(sizeof (struct gdb_uprobe), 
GFP_KERNEL);
-                                if (!gup) {
-                                        push_output_packet(p, "E04");
-                                } else {
-                                        gup->up.pid = task->tgid;
-                                        gup->up.vaddr = arg2;
-                                        gup->up.handler = gdb_uprobe_handler;
-                                        rc = register_uprobe (& gup->up);
-                                        if (rc != 0) {
-                                                kfree (gup);
-                                                push_output_packet (p, "E06");
-                                        } else {
-                                                INIT_LIST_HEAD(& gup->link);
-                                                list_add_tail(&gup->link, & 
p->uprobes);
-                                                push_output_packet(p, "OK");
-                                        }
-                                }
-                        }
-                }
+                       if (gup)        /* breakpoint already exists */
+                               break;
+
+                       gup = kzalloc(sizeof(struct gdb_uprobe), GFP_KERNEL);
+                       if (!gup) {
+                               push_output_packet(p, "E04");
+                               break;
+                       }
+                       gup->up.pid = task->tgid;
+                       gup->up.vaddr = arg2;
+                       gup->up.handler = gdb_uprobe_handler;
+                       gup->up.registration_callback = gdb_register_complete;
+                       rc = register_uprobe(&gup->up);
+                       if (rc && rc != -EINPROGRESS) {
+                               kfree(gup);
+                               push_output_packet(p, "E06");
+                       } else {
+                               push_output_packet(p, "OK");
+                               if (!rc) { /* register_uprobe succeed */
+                                       INIT_LIST_HEAD(&gup->link);
+                                       list_add_tail(&gup->link, &p->uprobes);
+                               }
+                       }
+               }
                 break;
         case 'z': /* TYPE,ADDR,LENGTH */
                 rc = sscanf(& p->input_buf[2], "%lu,%lx,%lx", &arg1, &arg2, 
&arg3);

Reply via email to