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);