Messages in this thread | | | Date | Tue, 7 Jul 2015 14:54:33 +0200 | From | Anton Arapov <> | Subject | Re: [PATCH v2 05/11] uprobes: Change handle_trampoline() to find the next chain beforehand |
| |
On Tue, Jul 07, 2015 at 03:22:50AM +0200, Oleg Nesterov wrote: > No functional changes, preparation. > > Add the new helper, find_next_ret_chain(), which finds the first !chained > entry and returns its ->next. Yes, it is suboptimal. We probably want to > turn ->chained into ->start_of_this_chain pointer and avoid another loop. > But this needs the boring changes in dup_utask(), so lets do this later. > > Change the main loop in handle_trampoline() to unwind the stack until ri > is equal to the pointer returned by this new helper. > > Signed-off-by: Oleg Nesterov <oleg@redhat.com> > Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Acked-by: Anton Arapov <arapov@gmail.com>
> --- > kernel/events/uprobes.c | 27 ++++++++++++++++----------- > 1 files changed, 16 insertions(+), 11 deletions(-) > > diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c > index 4c941fe..98e4d97 100644 > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -1766,11 +1766,22 @@ handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs) > up_read(&uprobe->register_rwsem); > } > > +static struct return_instance *find_next_ret_chain(struct return_instance *ri) > +{ > + bool chained; > + > + do { > + chained = ri->chained; > + ri = ri->next; /* can't be NULL if chained */ > + } while (chained); > + > + return ri; > +} > + > static void handle_trampoline(struct pt_regs *regs) > { > struct uprobe_task *utask; > - struct return_instance *ri; > - bool chained; > + struct return_instance *ri, *next; > > utask = current->utask; > if (!utask) > @@ -1780,24 +1791,18 @@ static void handle_trampoline(struct pt_regs *regs) > if (!ri) > goto sigill; > > + next = find_next_ret_chain(ri); > /* > * TODO: we should throw out return_instance's invalidated by > * longjmp(), currently we assume that the probed function always > * returns. > */ > instruction_pointer_set(regs, ri->orig_ret_vaddr); > - > - for (;;) { > + do { > handle_uretprobe_chain(ri, regs); > - > - chained = ri->chained; > ri = free_ret_instance(ri); > utask->depth--; > - > - if (!chained) > - break; > - BUG_ON(!ri); > - } > + } while (ri != next); > > utask->return_instances = ri; > return; > -- > 1.5.5.1 >
| |