[PATCH 2/2] Allow deferred register/unregister of uprobes.

Srikar Dronamraju srikar at linux.vnet.ibm.com
Wed Aug 26 12:17:16 UTC 2009


commit 20744cb97a3e4aec63ba7b92ce4115170fd468d6
Author: Srikar Dronamraju <srikar at 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 <srikar at 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);




More information about the utrace-devel mailing list