]> sourceware.org Git - systemtap.git/commitdiff
2006-02-25 Martin Hunt <hunt@redhat.com>
authorhunt <hunt>
Sat, 25 Feb 2006 10:18:39 +0000 (10:18 +0000)
committerhunt <hunt>
Sat, 25 Feb 2006 10:18:39 +0000 (10:18 +0000)
* 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.

runtime/transport/ChangeLog
runtime/transport/procfs.c
runtime/transport/transport.c
runtime/transport/transport.h
runtime/transport/transport.txt [new file with mode: 0644]

index 6b0a772657c20c2d45bf9c99c506c46347060e03..c1eca3fd2d2a874cdf9f9959ee8204e361ffe1f8 100644 (file)
@@ -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()
index d083fb64c794fdf576c6857bde97bfb90fd67a95..b878a0f50f769a7a7e11c3bc3a616ea1d7589386 100644 (file)
@@ -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:
index da903f6d0bc0f1229bce2528f510966bf135f0c4..a38d1f56a831984969413e78cf34f9dae2cd6e24 100644 (file)
@@ -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;
 }
index e62260ab528ce2944d0193600e9e429265e8634c..1cbe196aa48f279c8d1743ccb72001b7076ead6d 100644 (file)
@@ -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 (file)
index 0000000..5118cc0
--- /dev/null
@@ -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.
+
This page took 0.039815 seconds and 5 git commands to generate.