summaryrefslogtreecommitdiffstats
path: root/runtime/transport/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/transport/transport.c')
-rw-r--r--runtime/transport/transport.c251
1 files changed, 173 insertions, 78 deletions
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 318c62f1..ec73f05f 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -14,27 +14,46 @@
#ifndef _TRANSPORT_TRANSPORT_C_
#define _TRANSPORT_TRANSPORT_C_
-#include <linux/delay.h>
-#include <linux/namei.h>
#include "transport.h"
-#include "../mempool.c"
-#include "symbols.c"
+#include <linux/debugfs.h>
+#include <linux/namei.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
-static struct utt_trace *_stp_utt = NULL;
-static unsigned int utt_seq = 1;
-static int _stp_probes_started = 0;
-static pid_t _stp_target = 0;
static int _stp_exit_flag = 0;
+
+static uid_t _stp_uid = 0;
+static gid_t _stp_gid = 0;
+static int _stp_pid = 0;
+
+static int _stp_ctl_attached = 0;
+
+static pid_t _stp_target = 0;
+static int _stp_probes_started = 0;
+
+// For now, disable transport version 3
+#if STP_TRANSPORT_VERSION == 3
+#undef STP_TRANSPORT_VERSION
+#define STP_TRANSPORT_VERSION 2
+#endif
+
#include "control.h"
-#ifdef STP_OLD_TRANSPORT
+#if STP_TRANSPORT_VERSION == 1
#include "relayfs.c"
-#include "procfs.c"
-#else
-#include "utt.c"
+#elif STP_TRANSPORT_VERSION == 2
+#include "relay_v2.c"
#include "debugfs.c"
+#elif STP_TRANSPORT_VERSION == 3
+#include "ring_buffer.c"
+#include "debugfs.c"
+#else
+#error "Unknown STP_TRANSPORT_VERSION"
#endif
#include "control.c"
+static unsigned _stp_nsubbufs = 8;
+static unsigned _stp_subbuf_size = 65536*4;
+
/* module parameters */
static int _stp_bufsize;
module_param(_stp_bufsize, int, 0);
@@ -47,7 +66,6 @@ MODULE_PARM_DESC(_stp_unprivileged_user, "user is unprivileged");
/* forward declarations */
static void probe_exit(void);
static int probe_start(void);
-static void _stp_exit(void);
/* check for new workqueue API */
#ifdef DECLARE_DELAYED_WORK
@@ -91,14 +109,15 @@ static void _stp_handle_start(struct _stp_msg_start *st)
/* when someone does /sbin/rmmod on a loaded systemtap module. */
static void _stp_cleanup_and_exit(int send_exit)
{
- static int called = 0;
- if (!called) {
+ static int _stp_exit_called = 0;
+
+ if (!_stp_exit_called) {
int failures;
dbug_trans(1, "cleanup_and_exit (%d)\n", send_exit);
_stp_exit_flag = 1;
/* we only want to do this stuff once */
- called = 1;
+ _stp_exit_called = 1;
if (_stp_probes_started) {
dbug_trans(1, "calling probe_exit\n");
@@ -111,9 +130,8 @@ static void _stp_cleanup_and_exit(int send_exit)
if (failures)
_stp_warn("There were %d transport failures.\n", failures);
- dbug_trans(1, "************** calling startstop 0 *************\n");
- if (_stp_utt)
- utt_trace_startstop(_stp_utt, 0, &utt_seq);
+ dbug_trans(1, "*** calling _stp_transport_data_fs_stop ***\n");
+ _stp_transport_data_fs_stop();
dbug_trans(1, "ctl_send STP_EXIT\n");
if (send_exit)
@@ -140,11 +158,11 @@ static void _stp_request_exit(void)
static void _stp_detach(void)
{
dbug_trans(1, "detach\n");
- _stp_attached = 0;
+ _stp_ctl_attached = 0;
_stp_pid = 0;
if (!_stp_exit_flag)
- utt_set_overwrite(1);
+ _stp_transport_data_fs_overwrite(1);
cancel_delayed_work(&_stp_work);
wake_up_interruptible(&_stp_ctl_wq);
@@ -156,9 +174,9 @@ static void _stp_detach(void)
static void _stp_attach(void)
{
dbug_trans(1, "attach\n");
- _stp_attached = 1;
+ _stp_ctl_attached = 1;
_stp_pid = current->pid;
- utt_set_overwrite(0);
+ _stp_transport_data_fs_overwrite(0);
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
}
@@ -185,7 +203,7 @@ static void _stp_work_queue(void *data)
/* if exit flag is set AND we have finished with probe_start() */
if (unlikely(_stp_exit_flag && _stp_probes_started))
_stp_request_exit();
- if (likely(_stp_attached))
+ if (likely(_stp_ctl_attached))
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
}
@@ -195,34 +213,18 @@ static void _stp_work_queue(void *data)
* This is called automatically when the module is unloaded.
*
*/
-static void _stp_transport_close()
+static void _stp_transport_close(void)
{
- dbug_trans(1, "%d: ************** transport_close *************\n", current->pid);
+ dbug_trans(1, "%d: ************** transport_close *************\n",
+ current->pid);
_stp_cleanup_and_exit(0);
destroy_workqueue(_stp_wq);
_stp_unregister_ctl_channel();
- if (_stp_utt)
- utt_trace_remove(_stp_utt);
+ _stp_transport_fs_close();
_stp_print_cleanup(); /* free print buffers */
_stp_mem_debug_done();
- dbug_trans(1, "---- CLOSED ----\n");
-}
-
-static struct utt_trace *_stp_utt_open(void)
-{
- struct utt_trace_setup utts;
- strlcpy(utts.root, "systemtap", sizeof(utts.root));
- strlcpy(utts.name, THIS_MODULE->name, sizeof(utts.name));
- utts.buf_size = _stp_subbuf_size;
- utts.buf_nr = _stp_nsubbufs;
-
-#ifdef STP_BULKMODE
- utts.is_global = 0;
-#else
- utts.is_global = 1;
-#endif
- return utt_trace_setup(&utts);
+ dbug_trans(1, "---- CLOSED ----\n");
}
/**
@@ -232,7 +234,6 @@ static struct utt_trace *_stp_utt_open(void)
static int _stp_transport_init(void)
{
dbug_trans(1, "transport_init\n");
- _stp_init_pid = current->pid;
#ifdef STAPCONF_TASK_UID
_stp_uid = current->uid;
_stp_gid = current->gid;
@@ -258,12 +259,8 @@ static int _stp_transport_init(void)
dbug_trans(1, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size);
}
-#if !defined (STP_OLD_TRANSPORT) || defined (STP_BULKMODE)
- /* open utt (relayfs) channel to send data to userspace */
- _stp_utt = _stp_utt_open();
- if (!_stp_utt)
+ if (_stp_transport_fs_init(THIS_MODULE->name) != 0)
goto err0;
-#endif
/* create control channel */
if (_stp_register_ctl_channel() < 0)
@@ -274,18 +271,17 @@ static int _stp_transport_init(void)
goto err2;
/* start transport */
- utt_trace_startstop(_stp_utt, 1, &utt_seq);
+ _stp_transport_data_fs_start();
/* create workqueue of kernel threads */
_stp_wq = create_workqueue("systemtap");
if (!_stp_wq)
goto err3;
- _stp_transport_state = 1;
-
/* Signal stapio to send us STP_START back (XXX: ?!?!?!). */
_stp_ctl_send(STP_TRANSPORT, NULL, 0);
+ dbug_trans(1, "returning 0...\n");
return 0;
err3:
@@ -293,8 +289,7 @@ err3:
err2:
_stp_unregister_ctl_channel();
err1:
- if (_stp_utt)
- utt_trace_remove(_stp_utt);
+ _stp_transport_fs_close();
err0:
return -1;
}
@@ -322,7 +317,7 @@ static struct dentry *_stp_lockfile = NULL;
static int _stp_lock_transport_dir(void)
{
int numtries = 0;
-#ifdef STP_OLD_TRANSPORT
+#if STP_TRANSPORT_VERSION == 1
while ((_stp_lockfile = relayfs_create_dir("systemtap_lock", NULL)) == NULL) {
#else
while ((_stp_lockfile = debugfs_create_dir("systemtap_lock", NULL)) == NULL) {
@@ -337,7 +332,7 @@ static int _stp_lock_transport_dir(void)
static void _stp_unlock_transport_dir(void)
{
if (_stp_lockfile) {
-#ifdef STP_OLD_TRANSPORT
+#if STP_TRANSPORT_VERSION == 1
relayfs_remove_dir(_stp_lockfile);
#else
debugfs_remove(_stp_lockfile);
@@ -346,51 +341,151 @@ static void _stp_unlock_transport_dir(void)
}
}
-/* _stp_get_root_dir(name) - creates root directory 'name' or */
-/* returns a pointer to it if it already exists. Used in */
-/* utt.c and relayfs.c. Will not be necessary if utt is included */
-/* in the kernel. */
+static struct dentry *__stp_root_dir = NULL;
-static struct dentry *_stp_get_root_dir(const char *name)
+/* _stp_get_root_dir() - creates root directory or returns
+ * a pointer to it if it already exists. */
+
+static struct dentry *_stp_get_root_dir(void)
{
struct file_system_type *fs;
- struct dentry *root;
struct super_block *sb;
+ const char *name = "systemtap";
-#ifdef STP_OLD_TRANSPORT
+ if (__stp_root_dir != NULL) {
+ return __stp_root_dir;
+ }
+
+#if STP_TRANSPORT_VERSION == 1
fs = get_fs_type("relayfs");
+ if (!fs) {
+ errk("Couldn't find relayfs filesystem.\n");
+ return NULL;
+ }
#else
fs = get_fs_type("debugfs");
-#endif
if (!fs) {
- errk("Couldn't find debugfs or relayfs filesystem.\n");
+ errk("Couldn't find debugfs filesystem.\n");
return NULL;
}
+#endif
if (!_stp_lock_transport_dir()) {
errk("Couldn't lock transport directory.\n");
return NULL;
}
-#ifdef STP_OLD_TRANSPORT
- root = relayfs_create_dir(name, NULL);
+#if STP_TRANSPORT_VERSION == 1
+ __stp_root_dir = relayfs_create_dir(name, NULL);
#else
- root = debugfs_create_dir(name, NULL);
+ __stp_root_dir = debugfs_create_dir(name, NULL);
#endif
- if (!root) {
- /* couldn't create it because it is already there, so find it. */
- sb = list_entry(fs->fs_supers.next, struct super_block, s_instances);
+ if (!__stp_root_dir) {
+ /* Couldn't create it because it is already there, so
+ * find it. */
+ sb = list_entry(fs->fs_supers.next, struct super_block,
+ s_instances);
_stp_lock_inode(sb->s_root->d_inode);
- root = lookup_one_len(name, sb->s_root, strlen(name));
+ __stp_root_dir = lookup_one_len(name, sb->s_root,
+ strlen(name));
_stp_unlock_inode(sb->s_root->d_inode);
- if (!IS_ERR(root))
- dput(root);
+ if (!IS_ERR(__stp_root_dir))
+ dput(__stp_root_dir);
else {
- root = NULL;
+ __stp_root_dir = NULL;
errk("Could not create or find transport directory.\n");
}
}
+ else if (IS_ERR(__stp_root_dir)) {
+ __stp_root_dir = NULL;
+ errk("Could not create root directory \"%s\", error %ld\n", name,
+ -PTR_ERR(__stp_root_dir));
+ }
+
_stp_unlock_transport_dir();
- return root;
+ return __stp_root_dir;
+}
+
+static void _stp_remove_root_dir(void)
+{
+ if (__stp_root_dir) {
+ if (!_stp_lock_transport_dir()) {
+ errk("Unable to lock transport directory.\n");
+ return;
+ }
+ if (simple_empty(__stp_root_dir)) {
+#if STP_TRANSPORT_VERSION == 1
+ relayfs_remove_dir(__stp_root_dir);
+#else
+ debugfs_remove(__stp_root_dir);
+#endif
+ }
+ _stp_unlock_transport_dir();
+ __stp_root_dir = NULL;
+ }
+}
+
+static struct dentry *__stp_module_dir = NULL;
+
+static struct dentry *_stp_get_module_dir(void)
+{
+ return __stp_module_dir;
+}
+
+static int _stp_transport_fs_init(const char *module_name)
+{
+ struct dentry *root_dir;
+
+ dbug_trans(1, "entry\n");
+ if (module_name == NULL)
+ return -1;
+
+ root_dir = _stp_get_root_dir();
+ if (root_dir == NULL)
+ return -1;
+
+#if STP_TRANSPORT_VERSION == 1
+ __stp_module_dir = relayfs_create_dir(module_name, root_dir);
+#else
+ __stp_module_dir = debugfs_create_dir(module_name, root_dir);
+#endif
+ if (!__stp_module_dir) {
+ errk("Could not create module directory \"%s\"\n",
+ module_name);
+ _stp_remove_root_dir();
+ return -1;
+ }
+ else if (IS_ERR(__stp_module_dir)) {
+ errk("Could not create module directory \"%s\", error %ld\n",
+ module_name, -PTR_ERR(__stp_module_dir));
+ _stp_remove_root_dir();
+ return -1;
+ }
+
+ if (_stp_transport_data_fs_init() != 0) {
+ _stp_remove_root_dir();
+ return -1;
+ }
+ dbug_trans(1, "returning 0\n");
+ return 0;
+}
+
+static void _stp_transport_fs_close(void)
+{
+ dbug_trans(1, "stp_transport_fs_close\n");
+
+ _stp_transport_data_fs_close();
+
+ if (__stp_module_dir) {
+#if STP_TRANSPORT_VERSION == 1
+ relayfs_remove_dir(__stp_module_dir);
+#else
+ debugfs_remove(__stp_module_dir);
+#endif
+ __stp_module_dir = NULL;
+ }
+
+ _stp_remove_root_dir();
}
+
#endif /* _TRANSPORT_C_ */