diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 23 | ||||
-rw-r--r-- | runtime/staprun/ChangeLog | 25 | ||||
-rw-r--r-- | runtime/staprun/common.c | 6 | ||||
-rw-r--r-- | runtime/staprun/mainloop.c | 122 | ||||
-rw-r--r-- | runtime/staprun/stapio.c | 2 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 2 | ||||
-rw-r--r-- | runtime/task_finder.c | 139 | ||||
-rw-r--r-- | runtime/time.c | 7 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 6 | ||||
-rw-r--r-- | runtime/transport/transport.c | 6 | ||||
-rw-r--r-- | runtime/vsprintf.c | 6 |
11 files changed, 223 insertions, 121 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 3eabede9..8410b918 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,26 @@ +2008-05-05 Frank Ch. Eigler <fche@elastic.org> + + PR 6481. + * time.c (__stp_time_timer_callback): Reenable irq's before + mod_timer. + +2008-05-05 David Smith <dsmith@redhat.com> + + * task_finder.c (stap_utrace_detach_ops): Make sure we ignore + /sbin/init. + (__stp_utrace_attach): Added function to handle details of + attaching a utrace engine. + (__stp_utrace_task_finder_report_clone): Calls + __stp_utrace_attach. + (__stp_utrace_task_finder_report_exec): Ditto. + (stap_start_task_finder): Ditto. + +2008-04-30 Masami Hiramatsu <mhiramat@redhat.com> + + PR 5648 + From Shaohua Li <shaohua.li@intel.com> + * vsprintf.c (_stp_vsnprintf): Fix unaligned access warning on ia64. + 2008-04-29 David Smith <dsmith@redhat.com> * task_finder.c: Made more robust by ensuring that all utrace diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog index 9e0ccb73..969c299d 100644 --- a/runtime/staprun/ChangeLog +++ b/runtime/staprun/ChangeLog @@ -1,3 +1,28 @@ +2008-05-05 Martin Hunt <hunt@redhat.com> + + * mainloop.c (child_proc): Handle sig_chld + in the proper thread. + (signal_thread): Don't call send_request() + because it isn't thread-safe. + +2008-05-05 Martin Hunt <hunt@redhat.com> + + * mainloop.c (signal_thread): New thread to handle signals + better. + (setup_main_signals): Create signal thread. + +2008-04-30 Masami Hiramatsu <mhiramat@redhat.com> + + PR 6008 + * common.c (parse_args): Increase the limitation of the buffer size + to 4095MB. + * common.c (usage): Ditto. + +2008-04-30 Masami Hiramatsu <mhiramat@redhat.com> + + * stapio.c (main): Fix a typo in a debug message. + * staprun.c (main): Ditto. + 2008-04-24 Frank Ch. Eigler <fche@elastic.org> PR 6451. diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index b716d27f..93da51d8 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -58,8 +58,8 @@ void parse_args(int argc, char **argv) break; case 'b': buffer_size = (unsigned)atoi(optarg); - if (buffer_size < 1 || buffer_size > 64) { - err("Invalid buffer size '%d' (should be 1-64).\n", buffer_size); + if (buffer_size < 1 || buffer_size > 4095) { + err("Invalid buffer size '%d' (should be 1-4095).\n", buffer_size); usage(argv[0]); } break; @@ -130,7 +130,7 @@ void usage(char *prog) err("-o FILE Send output to FILE.\n"); err("-b buffer size The systemtap module specifies a buffer size.\n"); err(" Setting one here will override that value. The\n"); - err(" value should be an integer between 1 and 64\n"); + err(" value should be an integer between 1 and 4095 \n"); err(" which be assumed to be the buffer size in MB.\n"); err(" That value will be per-cpu in bulk mode.\n"); err("-L Load module and start probes, then detach.\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 37a4f58a..61963743 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -16,8 +16,8 @@ /* globals */ int ncpus; static int use_old_transport = 0; -enum _stp_sig_type { sig_none, sig_done, sig_detach }; -static enum _stp_sig_type got_signal = sig_none; +//enum _stp_sig_type { sig_none, sig_done, sig_detach }; +//static enum _stp_sig_type got_signal = sig_none; /** * send_request - send request to kernel over control channel @@ -29,48 +29,83 @@ static enum _stp_sig_type got_signal = sig_none; */ int send_request(int type, void *data, int len) { - char buf[1024]; - - /* Before doing memcpy, make sure 'buf' is big enough. */ - if ((len + 4) > (int)sizeof(buf)) { - _err("exceeded maximum send_request size.\n"); - return -1; - } - memcpy(buf, &type, 4); - memcpy(&buf[4], data, len); - return write(control_channel, buf, len+4); + char buf[1024]; + + /* Before doing memcpy, make sure 'buf' is big enough. */ + if ((len + 4) > (int)sizeof(buf)) { + _err("exceeded maximum send_request size.\n"); + return -1; + } + memcpy(buf, &type, 4); + memcpy(&buf[4], data, len); + return write(control_channel, buf, len + 4); } +static void *signal_thread(void *arg) +{ + sigset_t *s = (sigset_t *) arg; + int signum, rc, btype = STP_EXIT; + + while (1) { + if (sigwait(s, &signum) < 0) { + _perr("sigwait"); + continue; + } + dbug(2, "sigproc %d (%s)\n", signum, strsignal(signum)); + if (signum == SIGQUIT) + cleanup_and_exit(1); + else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM) { + // send STP_EXIT + rc = write(control_channel, &btype, sizeof(btype)); + break; + } + } + return NULL; +} -static void sigproc(int signum) +static void chld_proc(int signum) { - dbug(2, "sigproc %d (%s)\n", signum, strsignal(signum)); - - if (signum == SIGCHLD) { - pid_t pid = waitpid(-1, NULL, WNOHANG); - if (pid != target_pid) - return; - send_request(STP_EXIT, NULL, 0); - } else if (signum == SIGQUIT) - got_signal = sig_detach; - else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM) - got_signal = sig_done; + int32_t rc, btype = STP_EXIT; + dbug(2, "chld_proc %d (%s)\n", signum, strsignal(signum)); + pid_t pid = waitpid(-1, NULL, WNOHANG); + if (pid != target_pid) + return; + // send STP_EXIT + rc = write(control_channel, &btype, sizeof(btype)); } -static void setup_main_signals(int cleanup) +static void setup_main_signals(void) { - struct sigaction a; - memset(&a, 0, sizeof(a)); - sigfillset(&a.sa_mask); - if (cleanup == 0) { - a.sa_handler = sigproc; - sigaction(SIGCHLD, &a, NULL); - } else - a.sa_handler = SIG_IGN; - sigaction(SIGINT, &a, NULL); - sigaction(SIGTERM, &a, NULL); - sigaction(SIGHUP, &a, NULL); - sigaction(SIGQUIT, &a, NULL); + pthread_t tid; + struct sigaction sa; + sigset_t *s = malloc(sizeof(*s)); + if (!s) { + _perr("malloc failed"); + exit(1); + } + sigfillset(s); + pthread_sigmask(SIG_SETMASK, s, NULL); + memset(&sa, 0, sizeof(sa)); + sigfillset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + + sa.sa_handler = chld_proc; + sigaction(SIGCHLD, &sa, NULL); + + sigemptyset(s); + sigaddset(s, SIGINT); + sigaddset(s, SIGTERM); + sigaddset(s, SIGHUP); + sigaddset(s, SIGQUIT); + pthread_sigmask(SIG_SETMASK, s, NULL); + if (pthread_create(&tid, NULL, signal_thread, s) < 0) { + _perr("failed to create thread"); + exit(1); + } } /* @@ -229,7 +264,7 @@ void cleanup_and_exit(int detach) return; exiting = 1; - setup_main_signals(1); + setup_main_signals(); dbug(1, "detach=%d\n", detach); @@ -272,20 +307,17 @@ int stp_main_loop(void) char recvbuf[8196]; setvbuf(ofp, (char *)NULL, _IOLBF, 0); - setup_main_signals(0); + setup_main_signals(); dbug(2, "in main loop\n"); send_request(STP_READY, NULL, 0); - while (1) { /* handle messages from control channel */ + /* handle messages from control channel */ + while (1) { nb = read(control_channel, recvbuf, sizeof(recvbuf)); dbug(2, "nb=%d\n", (int)nb); if (nb <= 0) { - if (got_signal == sig_done) - send_request(STP_EXIT, NULL, 0); - else if (got_signal == sig_detach) - cleanup_and_exit(1); - else if (errno != EINTR) + if (errno != EINTR) _perr("Unexpected EOF in read (nb=%ld)", (long)nb); continue; } diff --git a/runtime/staprun/stapio.c b/runtime/staprun/stapio.c index b591244f..3c8c4f7f 100644 --- a/runtime/staprun/stapio.c +++ b/runtime/staprun/stapio.c @@ -30,7 +30,7 @@ int main(int argc, char **argv) parse_args(argc, argv); if (buffer_size) - dbug(1, "Using a buffer of %u bytes.\n", buffer_size); + dbug(1, "Using a buffer of %u MB.\n", buffer_size); if (optind < argc) { parse_modpath(argv[optind++]); diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index ee9bdc7b..0291d01f 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -230,7 +230,7 @@ int main(int argc, char **argv) parse_args(argc, argv); if (buffer_size) - dbug(2, "Using a buffer of %u bytes.\n", buffer_size); + dbug(2, "Using a buffer of %u MB.\n", buffer_size); if (optind < argc) { parse_modpath(argv[optind++]); diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 915925a3..6d79c98a 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -93,6 +93,10 @@ stap_utrace_detach_ops(struct utrace_engine_ops *ops) rcu_read_lock(); for_each_process(tsk) { struct mm_struct *mm; + + if (tsk->pid <= 1) + continue; + mm = get_task_mm(tsk); if (mm) { mmput(mm); @@ -188,6 +192,45 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) #define __STP_UTRACE_ATTACHED_TASK_EVENTS (UTRACE_EVENT(DEATH)) +static int +__stp_utrace_attach(struct task_struct *tsk, + const struct utrace_engine_ops *ops, void *data, + unsigned long event_flags) +{ + struct utrace_attached_engine *engine; + struct mm_struct *mm; + int rc = 0; + + // Ignore init + if (tsk->pid <= 1) + return EPERM; + + // Ignore threads with no mm (which are kernel threads). + mm = get_task_mm(tsk); + if (! mm) + return EPERM; + mmput(mm); + + engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE, ops, data); + if (IS_ERR(engine)) { + int error = -PTR_ERR(engine); + if (error != ENOENT) { + _stp_error("utrace_attach returned error %d on pid %d", + error, (int)tsk->pid); + rc = error; + } + } + else if (unlikely(engine == NULL)) { + _stp_error("utrace_attach returned NULL on pid %d", + (int)tsk->pid); + rc = EFAULT; + } + else { + utrace_set_flags(tsk, engine, event_flags); + } + return rc; +} + static u32 __stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, struct task_struct *parent, @@ -200,21 +243,9 @@ __stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) return UTRACE_ACTION_RESUME; - // On clone, attach to the child. Ignore threads with no mm - // (which are kernel threads). - mm = get_task_mm(child); - if (mm) { - mmput(mm); - child_engine = utrace_attach(child, UTRACE_ATTACH_CREATE, - engine->ops, 0); - if (IS_ERR(child_engine)) - _stp_error("attach to clone child %d failed: %ld", - (int)child->pid, PTR_ERR(child_engine)); - else { - utrace_set_flags(child, child_engine, - __STP_UTRACE_TASK_FINDER_EVENTS); - } - } + // On clone, attach to the child. + (void) __stp_utrace_attach(child, engine->ops, 0, + __STP_UTRACE_TASK_FINDER_EVENTS); return UTRACE_ACTION_RESUME; } @@ -253,6 +284,8 @@ __stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, struct list_head *cb_node; list_for_each(cb_node, &tgt->callback_list_head) { struct stap_task_finder_target *cb_tgt; + int rc; + cb_tgt = list_entry(cb_node, struct stap_task_finder_target, callback_list); @@ -269,19 +302,11 @@ __stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, } // Set up thread death notification. - engine = utrace_attach(tsk, - UTRACE_ATTACH_CREATE, - &cb_tgt->ops, cb_tgt); - if (IS_ERR(engine)) { - _stp_error("attach to exec'ed %d failed: %ld", - (int)tsk->pid, - PTR_ERR(engine)); - } - else { - utrace_set_flags(tsk, engine, + rc = __stp_utrace_attach(tsk, &cb_tgt->ops, cb_tgt, __STP_UTRACE_ATTACHED_TASK_EVENTS); - cb_tgt->engine_attached = 1; - } + if (rc != 0 && rc != EPERM) + break; + cb_tgt->engine_attached = 1; } } return UTRACE_ACTION_RESUME; @@ -346,46 +371,35 @@ stap_start_task_finder(void) } atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING); - printk(KERN_ERR "SYSTEMTAP: in RUNNING state\n"); rcu_read_lock(); for_each_process(tsk) { - struct utrace_attached_engine *engine; struct mm_struct *mm; char *mmpath; size_t mmpathlen; struct list_head *tgt_node; + /* Attach to the thread */ + rc = __stp_utrace_attach(tsk, &__stp_utrace_task_finder_ops, 0, + __STP_UTRACE_TASK_FINDER_EVENTS); + if (rc == EPERM) { + /* Ignore EPERM errors, which mean this wasn't + * a thread we can attach to. */ + rc = 0; + continue; + } + else if (rc != 0) { + /* If we get a real error, quit. */ + break; + } + + /* Grab the path associated with this task. */ mm = get_task_mm(tsk); if (! mm) { /* If the thread doesn't have a mm_struct, it is * a kernel thread which we need to skip. */ continue; } - - /* Attach to the thread */ - engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE, - &__stp_utrace_task_finder_ops, 0); - if (IS_ERR(engine)) { - int error = -PTR_ERR(engine); - if (error != ENOENT) { - mmput(mm); - _stp_error("utrace_attach returned error %d on pid %d", - error, (int)tsk->pid); - rc = error; - break; - } - } - else if (unlikely(engine == NULL)) { - mmput(mm); - _stp_error("utrace_attach returned NULL on pid %d", - (int)tsk->pid); - rc = EFAULT; - break; - } - utrace_set_flags(tsk, engine, __STP_UTRACE_TASK_FINDER_EVENTS); - - /* Check the thread's exe's path/pid against our list. */ mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX); mmput(mm); /* We're done with mm */ if (IS_ERR(mmpath)) { @@ -395,6 +409,7 @@ stap_start_task_finder(void) break; } + /* Check the thread's exe's path/pid against our list. */ mmpathlen = strlen(mmpath); list_for_each(tgt_node, &__stp_task_finder_list) { struct stap_task_finder_target *tgt; @@ -430,23 +445,17 @@ stap_start_task_finder(void) } // Set up thread death notification. - engine = utrace_attach(tsk, - UTRACE_ATTACH_CREATE, - &cb_tgt->ops, cb_tgt); - if (IS_ERR(engine)) { - _stp_error("attach to %d failed: %ld", - (int)tsk->pid, - PTR_ERR(engine)); - } - else { - utrace_set_flags(tsk, engine, + rc = __stp_utrace_attach(tsk, &cb_tgt->ops, + cb_tgt, __STP_UTRACE_ATTACHED_TASK_EVENTS); - cb_tgt->engine_attached = 1; - } + if (rc != 0 && rc != EPERM) + break; + cb_tgt->engine_attached = 1; } } } rcu_read_unlock(); + _stp_kfree(mmpath_buf); return rc; } diff --git a/runtime/time.c b/runtime/time.c index 52a2edbb..8a0b6fad 100644 --- a/runtime/time.c +++ b/runtime/time.c @@ -131,10 +131,13 @@ __stp_time_timer_callback(unsigned long val) time->base_cycles = cycles; write_sequnlock(&time->lock); + local_irq_restore(flags); + /* PR6481: reenable IRQs before resetting the timer. + XXX: The worst that can probably happen is that we get + two consecutive timer resets. */ + if (likely(stp_timer_reregister)) mod_timer(&time->timer, jiffies + 1); - - local_irq_restore(flags); } /* This is called as an IPI, with interrupts disabled. */ diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index b0f2aee8..9d0ba162 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,9 @@ +2008-04-30 Masami Hiramatsu <mhiramat@redhat.com> + + PR 5645 + * transport.c (_stp_transport_init): Fix subbuffer size calculation + overflow. + 2008-04-21 hunt <hunt@redhat.com> * control.c (_stp_ctl_write): Return len + sizeof(int) so diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index 1f9a1667..a4e4e652 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -225,7 +225,11 @@ int _stp_transport_init(void) if (_stp_bufsize) { unsigned size = _stp_bufsize * 1024 * 1024; - _stp_subbuf_size = ((size >> 2) + 1) * 65536; + _stp_subbuf_size = 65536; + while (size / _stp_subbuf_size > 64 && + _stp_subbuf_size < 1024 * 1024) { + _stp_subbuf_size <<= 1; + } _stp_nsubbufs = size / _stp_subbuf_size; dbug_trans(1, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size); } diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c index 0bf625a5..dcaa1bc3 100644 --- a/runtime/vsprintf.c +++ b/runtime/vsprintf.c @@ -256,18 +256,18 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) break; case 2: if((str + 1) <= end) - *(int16_t *)str = (int16_t)num; + memcpy(str, &num, 2); str+=2; break; case 4: if((str + 3) <= end) - *(int32_t *)str = num; + memcpy(str, &num, 4); str+=4; break; default: // "%.8b" by default case 8: if((str + 7) <= end) - *(int64_t *)str = num; + memcpy(str, &num, 8); str+=8; break; } |