diff options
-rw-r--r-- | runtime/transport/ChangeLog | 23 | ||||
-rw-r--r-- | runtime/transport/procfs.c | 3 | ||||
-rw-r--r-- | runtime/transport/transport.c | 52 | ||||
-rw-r--r-- | runtime/transport/transport.h | 1 | ||||
-rw-r--r-- | runtime/transport/transport.txt | 85 |
5 files changed, 137 insertions, 27 deletions
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index 6b0a7726..c1eca3fd 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,26 @@ +2006-02-25 Martin Hunt <hunt@redhat.com> + + * procfs.c (_stp_proc_write_cmd): Check return code for + _stp_transport_open(). + + * transport.c (_stp_transport_write): This function + can now sleep because it is + (_stp_handle_start): Don't use a mutex when a simple atomic + will do. + (_stp_work_queue): Check atomic to see if probe_start() + has finished before attempting exit. + (_stp_transport_close): PR2391. Cancel work queue. + (_stp_transport_init): If _stp_register_procfs() fails, + return an error code. + + * transport.txt: New file. Documents transport initialization and + shutdown sequence. + +2006-02-24 Martin Hunt <hunt@redhat.com> + + * transport.c (_stp_transport_init): Fail if + _stp_register_procfs() fails. + 2006-02-17 Martin Hunt <hunt@redhat.com> * procfs.c (_stp_proc_read_cmd): Change spin_lock() diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index d083fb64..b878a0f5 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -103,7 +103,8 @@ static ssize_t _stp_proc_write_cmd (struct file *file, const char __user *buf, return 0; if (copy_from_user (&ti, &buf[4], sizeof(struct transport_info))) return -EFAULT; - _stp_transport_open (&ti); + if (_stp_transport_open (&ti) < 0) + return -1; break; } default: diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index da903f6d..a38d1f56 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -1,15 +1,18 @@ -#ifndef _TRANSPORT_TRANSPORT_C_ /* -*- linux-c -*- */ -#define _TRANSPORT_TRANSPORT_C_ - -/* +/* -*- linux-c -*- * transport.c - stp transport functions * * Copyright (C) IBM Corporation, 2005 - * Copyright (C) Red Hat Inc, 2005 + * Copyright (C) Red Hat Inc, 2005, 2006 * - * This file is released under the GPL. + * 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 + * Public License (GPL); either version 2, or (at your option) any + * later version. */ +#ifndef _TRANSPORT_TRANSPORT_C_ +#define _TRANSPORT_TRANSPORT_C_ + #include <linux/delay.h> #include "transport.h" @@ -19,8 +22,7 @@ static struct rchan *_stp_chan; static struct dentry *_stp_dir; #endif -static DECLARE_MUTEX(_stp_start_mutex); - +static atomic_t _stp_start_finished = ATOMIC_INIT (0); static int _stp_dpid; static int _stp_pid; @@ -45,7 +47,7 @@ int _stp_transport_open(struct transport_info *info); /* * _stp_streaming - boolean, are we using 'streaming' output? */ -static inline int _stp_streaming(void) +static int _stp_streaming(void) { if (_stp_transport_mode == STP_TRANSPORT_PROC) return 1; @@ -99,12 +101,14 @@ void _stp_handle_start (struct transport_start *st) { kbug ("stp_handle_start pid=%d\n", st->pid); - down (&_stp_start_mutex); + /* note: st->pid is actually the return code for the reply packet */ st->pid = probe_start(); - up (&_stp_start_mutex); + atomic_set(&_stp_start_finished,1); - if (st->pid < 0) + /* if probe_start() failed, suppress calling probe_exit() */ + if (st->pid < 0) _stp_exit_called = 1; + _stp_transport_send(STP_START, st, sizeof(*st)); } @@ -118,11 +122,11 @@ static void _stp_handle_subbufs_consumed(int pid, struct consumed_info *info) } #endif -static void _stp_cleanup_and_exit (int closing) +static void _stp_cleanup_and_exit (int dont_rmmod) { int failures; - kbug("cleanup_and_exit (%d)\n", closing); + kbug("cleanup_and_exit (%d)\n", dont_rmmod); if (!_stp_exit_called) { _stp_exit_called = 1; @@ -137,8 +141,7 @@ static void _stp_cleanup_and_exit (int closing) relay_flush(_stp_chan); } #endif - kbug("SENDING STP_EXIT\n"); - _stp_transport_send(STP_EXIT, &closing, sizeof(int)); + _stp_transport_send(STP_EXIT, &dont_rmmod, sizeof(int)); } } @@ -158,15 +161,13 @@ static void _stp_work_queue (void *data) if (do_io) wake_up_interruptible(&_stp_proc_wq); - if (_stp_exit_flag) { + /* if exit flag is set AND we have finished with probe_start() */ + if (unlikely(_stp_exit_flag && atomic_read(&_stp_start_finished))) { cancel_delayed_work(&stp_exit); - down (&_stp_start_mutex); _stp_cleanup_and_exit(0); - up (&_stp_start_mutex); wake_up_interruptible(&_stp_proc_wq); } else schedule_delayed_work(&stp_exit, STP_WORK_TIMER); - } /** @@ -178,14 +179,13 @@ static void _stp_work_queue (void *data) void _stp_transport_close() { kbug("************** transport_close *************\n"); + cancel_delayed_work(&stp_exit); _stp_cleanup_and_exit(1); - + wake_up_interruptible(&_stp_proc_wq); #ifdef STP_RELAYFS if (_stp_transport_mode == STP_TRANSPORT_RELAYFS) _stp_relayfs_close(_stp_chan, _stp_dir); #endif - - ssleep(1); _stp_unregister_procfs(); kbug("---- CLOSED ----\n"); } @@ -193,7 +193,7 @@ void _stp_transport_close() /** * _stp_transport_open - open proc and relayfs channels * with proper parameters - * Returns negative on failure, 0 otherwise. + * Returns negative on failure, >0 otherwise. * * This function registers the probe with the control channel, * and if the probe output will not be 'streaming', creates a @@ -249,7 +249,9 @@ int _stp_transport_init(void) { kbug("transport_init from %ld %ld\n", (long)_stp_pid, (long)current->pid); - _stp_register_procfs(); + if (_stp_register_procfs() < 0) + return -1; + schedule_delayed_work(&stp_exit, STP_WORK_TIMER); return 0; } diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h index e62260ab..1cbe196a 100644 --- a/runtime/transport/transport.h +++ b/runtime/transport/transport.h @@ -24,7 +24,6 @@ static int _stp_transport_mode = STP_TRANSPORT_RELAYFS; static int _stp_transport_mode = STP_TRANSPORT_PROC; #endif -extern void _stp_transport_cleanup(void); extern void _stp_transport_close(void); #endif /* _TRANSPORT_TRANSPORT_H_ */ diff --git a/runtime/transport/transport.txt b/runtime/transport/transport.txt new file mode 100644 index 00000000..5118cc0c --- /dev/null +++ b/runtime/transport/transport.txt @@ -0,0 +1,85 @@ +INITIALIZATION + +init_module() is defined in runtime.h. It returns _stp_transport_init(). + +int _stp_transport_init(void) +{ + /* allocates buffers, creates /proc/systemtap/stuff */ + if (_stp_register_procfs() < 0) + return -1; + + /* starts up the work queue */ + schedule_delayed_work(&stp_exit, STP_WORK_TIMER); + + /* always succeeds */ + return 0; +} + +*** Module is now loaded *** + +In stpd, librelay.c, init_stp() forks any commands specified with +the "-c" parameter. Then it sends STP_TRANSPORT_INFO message with +the buffer size (if it was specified on the stpd command line) and +the pid from the fork (or 0 otherwise). + +In procfs.c, _stp_proc_write_cmd() receives the message. It calls +_stp_transport_open(). + +_stp_transport_open() initializes relayfs if necessary. It returns a +STP_TRANSPORT_INFO message with the transport_mode +(relayfs or procfs-only), and buffer information. + +stpd receives the STP_TRANSPORT_INFO message in stp_main_loop(), +It initializes relayfs (if necessary) and replies with an +STP_START message. + +***Communications are now fully established.*** + +_stp_proc_write_cmd() receives the STP_START. It calls _stp_handle_start(). + +_stp_handle_start() calls probe_start(), which the translator generates. +It allocates memory and registers probes. When that returns, +an atomic variable is set indicating probe_start finished. An STP_START +message is returned to stpd with the return value from probe_start() + +stpd receives the STP_START message in stp_main_loop(). If the return value +is < 0 (indicating probe_start failed to register probes, etc) stpd +cleans up and exits. + +*** Probes running. Everything Up. *** + + +SHUTDOWN AND UNLOADING + +There are 3 ways to initiate shutdown. + +1. stpd can initiate it. This happens when stpd receives a ^C or +a child specified with "-c" exits. + +2. Something can call _stp_exit(). + +3. rmmod. This can happen when stpd dies for an unexpected reason +and the module is still loaded. So the user does an rmmod. Also, when +STP_START fails, stpd simply rmmods the module. + + +For #1, stpd sends an STP_EXIT message. +_stp_proc_write_cmd() receives the STP_EXIT. It sets _stp_exit_flag +and returns. + +The next time _stp_work_queue() runs, it will notice that +_stp_exit_flag is set. It checks to see if probe_start() finished +because we don't want to start exiting until then. It will cancel itself, +and call _stp_cleanup_and_exit(0). That will call probe_exit() which +unregisters the probes. Then it sends an STP_EXIT(0) message to +stpd. stpd gets the message and calls cleanup_and_exit(0) + +For #2, _stp_exit() sets _stp_exit_flag. + +For #3, cleanup_module() calls _stp_transport_close(). +_stp_transport_close() cancels the work_queue, then calls +_stp_cleanup_and_exit(1). The "1" is passed as an argument to +the STP_EXIT message. Stpd calls cleanup_and_exit(1), which cleans +up everything on its side, but does not do an "rmmod". Finally, +_stp_unregister_procfs() to remove the procfs stuff. + |