diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-02-15 14:29:08 -0500 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-02-15 14:29:08 -0500 |
commit | 0f05501579dc0a4e66ccbbd8e0b29d052d9b5920 (patch) | |
tree | 79bf8b7b328e87e8c30cc64e64a1bea9a6f2dca5 /runtime | |
parent | 044427bcdfa2a1d58a912bf96546892bef82b717 (diff) | |
parent | 275f40a6d612f94e5272eeed772e9c9294cb8e1f (diff) | |
download | systemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.tar.gz systemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.tar.xz systemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.zip |
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 28 | ||||
-rw-r--r-- | runtime/alloc.c | 9 | ||||
-rw-r--r-- | runtime/counter.c | 4 | ||||
-rw-r--r-- | runtime/io.c | 5 | ||||
-rw-r--r-- | runtime/pmap-gen.c | 6 | ||||
-rw-r--r-- | runtime/print_new.c | 5 | ||||
-rw-r--r-- | runtime/stack-i386.c | 2 | ||||
-rw-r--r-- | runtime/stack-ia64.c | 4 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 11 | ||||
-rw-r--r-- | runtime/stat.c | 4 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 4 | ||||
-rw-r--r-- | runtime/transport/control.c | 8 | ||||
-rw-r--r-- | runtime/transport/procfs.c | 6 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 2 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.c | 79 | ||||
-rw-r--r-- | runtime/uprobes/uprobes.h | 3 |
16 files changed, 147 insertions, 33 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 7536cc88..b501c1ef 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,31 @@ +2008-02-06 Masami Hiramatsu <mhiramat@redhat.com> + + * stack-ia64.c (__stp_show_stack_sym): Skip printing symbol if (ip == + REG_IP(regs)). + +2008-01-29 Martin Hunt <hunt@redhat.com> + + * io.c (_stp_vlog): Use get_cpu() instead + of smp_processor_id() because this function can get + called with interrupts enabled. + +2008-01-29 Martin Hunt <hunt@redhat.com> + + * alloc.c (struct _stp_malloc_type): Remove + redundant field. + +2008-01-28 Martin Hunt <hunt@redhat.com> + + * alloc.c: Use DEFINE_SPINLOCK. + * counter.c: Ditto. + * pmap-gen.c: Ditto. + * print_new.c: Ditto. + * stat.c: Ditto. + +2008-01-27 Frank Ch. Eigler <fche@elastic.org> + + * stack-i386.c (__stp_stack_print): Correct #elif->#else typo. + 2008-01-14 Martin Hunt <hunt@redhat.com> * print.c (_stp_print_kernel_info): New function. diff --git a/runtime/alloc.c b/runtime/alloc.c index f022755a..cfdb97bd 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -32,7 +32,7 @@ static int _stp_allocated_net_memory = 0; #ifdef DEBUG_MEM -static spinlock_t _stp_mem_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(_stp_mem_lock); static int _stp_allocated_memory = 0; #define MEM_MAGIC 0xc11cf77f @@ -41,15 +41,14 @@ static int _stp_allocated_memory = 0; enum _stp_memtype { MEM_KMALLOC, MEM_VMALLOC, MEM_PERCPU }; typedef struct { - enum _stp_memtype type; char *alloc; char *free; } _stp_malloc_type; static const _stp_malloc_type const _stp_malloc_types[] = { - {MEM_KMALLOC, "kmalloc", "kfree"}, - {MEM_VMALLOC, "vmalloc", "vfree"}, - {MEM_PERCPU, "alloc_percpu", "free_percpu"} + {"kmalloc", "kfree"}, + {"vmalloc", "vfree"}, + {"alloc_percpu", "free_percpu"} }; struct _stp_mem_entry { diff --git a/runtime/counter.c b/runtime/counter.c index 42555dfa..d0376547 100644 --- a/runtime/counter.c +++ b/runtime/counter.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Counter aggregation Functions - * Copyright (C) 2005 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -60,7 +60,7 @@ Counter _stp_counter_init (void) int i; for_each_cpu(i) { Counter c = per_cpu_ptr (cnt, i); - c->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(c->lock); } } #endif diff --git a/runtime/io.c b/runtime/io.c index e36381bd..c49d86e6 100644 --- a/runtime/io.c +++ b/runtime/io.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * I/O for printing warnings, errors and debug messages - * Copyright (C) 2005, 2006, 2007 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -25,7 +25,7 @@ enum code { INFO=0, WARN, ERROR, DBUG }; static void _stp_vlog (enum code type, const char *func, int line, const char *fmt, va_list args) { int num; - char *buf = per_cpu_ptr(Stp_lbuf, smp_processor_id()); + char *buf = per_cpu_ptr(Stp_lbuf, get_cpu()); int start = 0; if (type == DBUG) { @@ -53,6 +53,7 @@ static void _stp_vlog (enum code type, const char *func, int line, const char *f _stp_print_flush(); } } + put_cpu(); } /** Logs Data. diff --git a/runtime/pmap-gen.c b/runtime/pmap-gen.c index ca8d45c5..0efffdb6 100644 --- a/runtime/pmap-gen.c +++ b/runtime/pmap-gen.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * pmap API generator - * Copyright (C) 2005-2007 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -412,7 +412,7 @@ PMAP KEYSYM(_stp_pmap_new) (unsigned max_entries) m->copy = KEYSYM(pmap_copy_keys); m->cmp = KEYSYM(pmap_key_cmp); #if NEED_MAP_LOCKS - m->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(m->lock); #endif } m = &pmap->agg; @@ -466,7 +466,7 @@ PMAP KEYSYM(_stp_pmap_new) (unsigned max_entries, int htype, ...) m->copy = KEYSYM(pmap_copy_keys); m->cmp = KEYSYM(pmap_key_cmp); #if NEED_MAP_LOCKS - m->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(m->lock); #endif } m = &pmap->agg; diff --git a/runtime/print_new.c b/runtime/print_new.c index 95a83a8d..75bbd82b 100644 --- a/runtime/print_new.c +++ b/runtime/print_new.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Print Flush Function - * Copyright (C) 2007 Red Hat Inc. + * Copyright (C) 2007-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -15,7 +15,8 @@ * * @note Preemption must be disabled to use this. */ -spinlock_t _stp_print_lock = SPIN_LOCK_UNLOCKED; + +DEFINE_SPINLOCK(_stp_print_lock); void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb) { diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index d73f4c84..b46ff06b 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -23,7 +23,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) { #ifdef STAPCONF_X86_UNIREGS unsigned long ebp = regs->bp; - #elif + #else unsigned long ebp = regs->ebp; #endif diff --git a/runtime/stack-ia64.c b/runtime/stack-ia64.c index cab25a0b..ca9d25a6 100644 --- a/runtime/stack-ia64.c +++ b/runtime/stack-ia64.c @@ -23,8 +23,8 @@ static void __stp_show_stack_sym(struct unw_frame_info *info, void *arg) if (skip){ if (ip == REG_IP(regs)) skip = 0; - else continue; - } + continue; + } _stp_print_char(' '); _stp_symbol_print(ip); _stp_print_char('\n'); diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index d1bba3f8..3a678405 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -336,7 +336,11 @@ int check_permissions(void) /* If neither group was found, just return an error. */ if (stapdev_gid == (gid_t)-1 && stapusr_gid == (gid_t)-1) { - err("ERROR: unable to find either group \"stapdev\" or group \"stapusr\"\n"); + err("ERROR: You are trying to run stap as a normal user.\n" + "You should either be root, or be part of either " + "group \"stapdev\" or group \"stapusr\".\n" + "Your system doesn't seem to have either group.\n" + "For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage\n"); return -1; } @@ -374,7 +378,10 @@ int check_permissions(void) /* If path_check is 0, then the user isn't a member of either * group. Error out. */ if (path_check == 0) { - err("ERROR: you must be a member of either group \"stapdev\" or group \"stapusr\"\n"); + err("ERROR: You are trying to run stap as a normal user.\n" + "You must be a member of either group \"stapdev\" or group \"stapusr\".\n" + "Please contact your system administrator to get yourself membership to either of those groups.\n" + "For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage.\n"); return 0; } diff --git a/runtime/stat.c b/runtime/stat.c index 298a6653..f8b5f018 100644 --- a/runtime/stat.c +++ b/runtime/stat.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Statistics Aggregation - * Copyright (C) 2005, 2007 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * Copyright (C) 2006 Intel Corporation * * This file is part of systemtap, and is free software. You can @@ -111,7 +111,7 @@ Stat _stp_stat_init (int type, ...) int i; for_each_cpu(i) { stat *sdp = per_cpu_ptr (sd, i); - sdp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(sdp->lock); } } #endif diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index e7bbabd8..764e3579 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,7 @@ +2008-01-28 Martin Hunt <hunt@redhat.com> + + * control.c, procfs.c, symbols.c: Use DEFINE_SPINLOCK + 2008-01-15 Martin Hunt <hunt@redhat.com> PR4037 and fixes to better synchronize staprun and stapio. diff --git a/runtime/transport/control.c b/runtime/transport/control.c index 3179f507..0bf99fc8 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- * * debugfs control channel - * Copyright (C) 2007 Red Hat Inc. + * Copyright (C) 2007-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -15,9 +15,9 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS; static struct list_head _stp_ctl_ready_q; static struct list_head _stp_sym_ready_q; static struct list_head _stp_pool_q; -spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED; -spinlock_t _stp_ctl_ready_lock = SPIN_LOCK_UNLOCKED; -spinlock_t _stp_sym_ready_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(_stp_pool_lock); +DEFINE_SPINLOCK(_stp_ctl_ready_lock); +DEFINE_SPINLOCK(_stp_sym_ready_lock); static ssize_t _stp_sym_write_cmd (struct file *file, const char __user *buf, size_t count, loff_t *ppos) diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index 85e97d15..33f6db33 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -15,9 +15,9 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS; static struct list_head _stp_ctl_ready_q; static struct list_head _stp_sym_ready_q; static struct list_head _stp_pool_q; -spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED; -spinlock_t _stp_ctl_ready_lock = SPIN_LOCK_UNLOCKED; -spinlock_t _stp_sym_ready_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(_stp_pool_lock); +DEFINE_SPINLOCK(_stp_ctl_ready_lock); +DEFINE_SPINLOCK(_stp_sym_ready_lock); #ifdef STP_BULKMODE extern int _stp_relay_flushing; diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index dde0f967..e740dde8 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -16,7 +16,7 @@ #define _SYMBOLS_C_ #include "../sym.h" -spinlock_t _stp_module_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(_stp_module_lock); #define STP_TRYLOCK_MODULES ({ \ int numtrylock = 0; \ while (!spin_trylock_irqsave (&_stp_module_lock, flags) && (++numtrylock < MAXTRYLOCK)) \ diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index f0b72c46..f7d90add 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -94,6 +94,15 @@ struct deferred_registration { enum uprobe_type type; }; +/* + * Calling a signal handler cancels single-stepping, so uprobes delays + * calling the handler, as necessary, until after single-stepping is completed. + */ +struct delayed_signal { + struct list_head list; + siginfo_t info; +}; + static struct uprobe_task *uprobe_find_utask(struct task_struct *tsk) { struct hlist_head *head; @@ -436,6 +445,7 @@ static int quiesce_all_threads(struct uprobe_process *uproc, static void uprobe_free_task(struct uprobe_task *utask) { struct deferred_registration *dr, *d; + struct delayed_signal *ds, *ds2; struct uretprobe_instance *ri; struct hlist_node *r1, *r2; @@ -445,6 +455,12 @@ static void uprobe_free_task(struct uprobe_task *utask) list_del(&dr->list); kfree(dr); } + + list_for_each_entry_safe(ds, ds2, &utask->delayed_signals, list) { + list_del(&ds->list); + kfree(ds); + } + hlist_for_each_entry_safe(ri, r1, r2, &utask->uretprobe_instances, hlist) { hlist_del(&ri->hlist); @@ -557,6 +573,7 @@ static struct uprobe_task *uprobe_add_task(struct task_struct *t, utask->doomed = 0; INIT_HLIST_HEAD(&utask->uretprobe_instances); INIT_LIST_HEAD(&utask->deferred_registrations); + INIT_LIST_HEAD(&utask->delayed_signals); INIT_LIST_HEAD(&utask->list); list_add_tail(&utask->list, &uproc->thread_list); uprobe_hash_utask(utask); @@ -1577,6 +1594,33 @@ static inline void uprobe_post_ssin(struct uprobe_task *utask, /* uprobe_pre_ssout() and uprobe_post_ssout() are architecture-specific. */ /* + * Delay delivery of the indicated signal until after single-step. + * Otherwise single-stepping will be cancelled as part of calling + * the signal handler. + */ +static u32 uprobe_delay_signal(struct uprobe_task *utask, siginfo_t *info) +{ + struct delayed_signal *ds = kmalloc(sizeof(*ds), GFP_USER); + if (ds) { + ds->info = *info; + INIT_LIST_HEAD(&ds->list); + list_add_tail(&ds->list, &utask->delayed_signals); + } + return UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN | + UTRACE_ACTION_SINGLESTEP | UTRACE_ACTION_NEWSTATE; +} + +static void uprobe_inject_delayed_signals(struct list_head *delayed_signals) +{ + struct delayed_signal *ds, *tmp; + list_for_each_entry_safe(ds, tmp, delayed_signals, list) { + send_sig_info(ds->info.si_signo, &ds->info, current); + list_del(&ds->list); + kfree(ds); + } +} + +/* * Signal callback: * * We get called here with: @@ -1616,10 +1660,24 @@ static u32 uprobe_report_signal(struct utrace_attached_engine *engine, unsigned long probept; int hit_uretprobe_trampoline = 0; int registrations_deferred = 0; + int uproc_freed = 0; + struct list_head delayed_signals; utask = (struct uprobe_task *)rcu_dereference(engine->data); BUG_ON(!utask); + /* + * info will be null if we're called with action=UTRACE_SIGNAL_HANDLER, + * which means that single-stepping has been disabled so a signal + * handler can be called in the probed process. That should never + * happen because we intercept and delay handled signals (action = + * UTRACE_ACTION_RESUME) until after we're done single-stepping. + */ + BUG_ON(!info); + if (action == UTRACE_ACTION_RESUME && utask->active_probe && + info->si_signo != SSTEP_SIGNAL) + return uprobe_delay_signal(utask, info); + if (info->si_signo != BREAKPOINT_SIGNAL && info->si_signo != SSTEP_SIGNAL) goto no_interest; @@ -1722,13 +1780,21 @@ bkpt_done: uprobe_get_process(uproc); } + /* + * Delayed signals are a little different. We want + * them delivered even if all the probes get unregistered + * and uproc and utask go away. So disconnect the list + * from utask and make it a local list. + */ + INIT_LIST_HEAD(&delayed_signals); + list_splice_init(&utask->delayed_signals, &delayed_signals); + ret = UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN | UTRACE_ACTION_NEWSTATE; utask->state = UPTASK_RUNNING; if (utask->quiescing) { up_read(&uproc->rwsem); - if (utask_fake_quiesce(utask) == 1) - ret |= UTRACE_ACTION_DETACH; + uproc_freed |= utask_fake_quiesce(utask); } else up_read(&uproc->rwsem); @@ -1738,12 +1804,17 @@ bkpt_done: * we just recycled was the last reason for * keeping uproc around. */ - uprobe_put_process(uproc); + uproc_freed |= uprobe_put_process(uproc); if (registrations_deferred) { uprobe_run_def_regs(&utask->deferred_registrations); - uprobe_put_process(uproc); + uproc_freed |= uprobe_put_process(uproc); } + + uprobe_inject_delayed_signals(&delayed_signals); + + if (uproc_freed) + ret |= UTRACE_ACTION_DETACH; break; default: goto no_interest; diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h index 418518f8..0c471474 100644 --- a/runtime/uprobes/uprobes.h +++ b/runtime/uprobes/uprobes.h @@ -385,6 +385,9 @@ struct uprobe_task { /* [un]registrations initiated by handlers must be asynchronous. */ struct list_head deferred_registrations; + + /* Delay handler-destined signals 'til after single-step done. */ + struct list_head delayed_signals; }; #ifdef CONFIG_UPROBES_SSOL |