[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