summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/debug.h1
-rw-r--r--runtime/print.c1
-rw-r--r--runtime/print.h16
-rw-r--r--runtime/print_new.c48
-rw-r--r--runtime/runtime.h3
-rw-r--r--runtime/sym.c1
-rw-r--r--runtime/transport/control.c8
-rw-r--r--runtime/transport/control.h1
-rw-r--r--runtime/transport/debugfs.c8
-rw-r--r--runtime/transport/relayfs.c2
-rw-r--r--runtime/transport/ring_buffer.c404
-rw-r--r--runtime/transport/transport.c193
-rw-r--r--runtime/transport/transport.h51
-rw-r--r--runtime/transport/utt.c4
-rw-r--r--runtime/transport/utt.h9
-rw-r--r--testsuite/systemtap.printf/end1.exp6
-rw-r--r--testsuite/systemtap.printf/end1b.exp2
-rw-r--r--testsuite/systemtap.printf/mixed_out.exp4
-rw-r--r--testsuite/systemtap.printf/mixed_outb.exp2
-rw-r--r--testsuite/systemtap.printf/out1.exp2
-rw-r--r--testsuite/systemtap.printf/out1b.exp2
-rw-r--r--testsuite/systemtap.printf/out2.exp2
-rw-r--r--testsuite/systemtap.printf/out2b.exp2
-rw-r--r--testsuite/systemtap.printf/out3.exp2
-rw-r--r--testsuite/systemtap.printf/out3b.exp2
25 files changed, 695 insertions, 81 deletions
diff --git a/runtime/debug.h b/runtime/debug.h
index e8b2e701..ce0c3943 100644
--- a/runtime/debug.h
+++ b/runtime/debug.h
@@ -14,7 +14,6 @@
* _dbug() writes to systemtap stderr.
* errk() writes to the system log.
*/
-static int _stp_transport_state = 0;
#define _dbug(args...) _stp_dbug(__FUNCTION__, __LINE__, args)
diff --git a/runtime/print.c b/runtime/print.c
index 2c84d3c9..fa517cb5 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -14,6 +14,7 @@
#include "string.h"
#include "vsprintf.c"
+#include "print.h"
#include "transport/transport.c"
/** @file print.c
diff --git a/runtime/print.h b/runtime/print.h
new file mode 100644
index 00000000..d5c588a3
--- /dev/null
+++ b/runtime/print.h
@@ -0,0 +1,16 @@
+/* -*- linux-c -*-
+ * Copyright (C) 2009 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
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _STP_PRINT_H_
+#define _STP_PRINT_H_
+
+static int _stp_print_init(void);
+static void _stp_print_cleanup(void);
+
+#endif /* _STP_PRINT_H_ */
diff --git a/runtime/print_new.c b/runtime/print_new.c
index fa7b4727..4857b301 100644
--- a/runtime/print_new.c
+++ b/runtime/print_new.c
@@ -23,13 +23,15 @@ void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb)
uint32_t len = pb->len;
/* check to see if there is anything in the buffer */
+ dbug_trans(1, "len = %ud\n", len);
if (likely (len == 0))
return;
pb->len = 0;
- if (unlikely(!_stp_utt || _stp_utt->trace_state != Utt_trace_running))
- return;
+//DRS FIXME: this digs down too deep in internals
+// if (unlikely(!_stp_utt || _stp_utt->trace_state != Utt_trace_running))
+// return;
#ifdef STP_BULKMODE
{
@@ -53,14 +55,46 @@ void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb)
}
#else
{
- void *buf;
+ struct _stp_entry *entry;
unsigned long flags;
+
+ dbug_trans(1, "calling _stp_data_write...\n");
spin_lock_irqsave(&_stp_print_lock, flags);
- buf = utt_reserve(_stp_utt, len);
- if (likely(buf))
- memcpy(buf, pb->buf, len);
+#if 0
+ entry = _stp_data_write_reserve(len);
+ if (likely(entry)) {
+ memcpy(entry->buf, pb->buf, len);
+ _stp_data_write_commit(entry);
+ }
else
- atomic_inc (&_stp_transport_failures);
+#endif
+ {
+ uint32_t cnt;
+ char *bufp = pb->buf;
+
+#define MAX_RESERVE_SIZE (4080 /*BUF_PAGE_SIZE*/ - sizeof(struct _stp_entry) - 10)
+ while (len > 0) {
+ if (len > MAX_RESERVE_SIZE) {
+ len -= MAX_RESERVE_SIZE;
+ cnt = MAX_RESERVE_SIZE;
+ }
+ else {
+ cnt = len;
+ len = 0;
+ }
+
+ entry = _stp_data_write_reserve(cnt);
+ if (likely(entry)) {
+ memcpy(entry->buf, bufp, cnt);
+ _stp_data_write_commit(entry);
+ bufp += cnt;
+ }
+ else {
+ atomic_inc (&_stp_transport_failures);
+ break;
+ }
+ }
+ }
spin_unlock_irqrestore(&_stp_print_lock, flags);
}
#endif /* STP_BULKMODE */
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fc5d454f..28283db6 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -45,6 +45,9 @@
static void _stp_dbug (const char *func, int line, const char *fmt, ...);
static void _stp_error (const char *fmt, ...);
+static void _stp_warn (const char *fmt, ...);
+
+static void _stp_exit(void);
#include "debug.h"
diff --git a/runtime/sym.c b/runtime/sym.c
index 1d88a862..31700326 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -12,6 +12,7 @@
#ifndef _STP_SYM_C_
#define _STP_SYM_C_
+#include "sym.h"
#include "string.c"
/** @file sym.c
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index edde244d..7626305a 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -9,6 +9,10 @@
* later version.
*/
+#include "control.h"
+#include "../mempool.c"
+#include "symbols.c"
+
static _stp_mempool_t *_stp_pool_q;
static struct list_head _stp_ctl_ready_q;
static DEFINE_SPINLOCK(_stp_ctl_ready_lock);
@@ -192,7 +196,7 @@ static ssize_t _stp_ctl_read_cmd(struct file *file, char __user *buf,
static int _stp_ctl_open_cmd(struct inode *inode, struct file *file)
{
- if (_stp_attached)
+ if (_stp_ctl_attached)
return -1;
_stp_attach();
return 0;
@@ -200,7 +204,7 @@ static int _stp_ctl_open_cmd(struct inode *inode, struct file *file)
static int _stp_ctl_close_cmd(struct inode *inode, struct file *file)
{
- if (_stp_attached)
+ if (_stp_ctl_attached)
_stp_detach();
return 0;
}
diff --git a/runtime/transport/control.h b/runtime/transport/control.h
index 5e7204ee..48289276 100644
--- a/runtime/transport/control.h
+++ b/runtime/transport/control.h
@@ -15,7 +15,6 @@
#include <linux/spinlock.h>
#include <linux/list.h>
-static _stp_mempool_t *_stp_pool_q;
static struct list_head _stp_ctl_ready_q;
static spinlock_t _stp_ctl_ready_lock;
static wait_queue_head_t _stp_ctl_wq;
diff --git a/runtime/transport/debugfs.c b/runtime/transport/debugfs.c
index 85ee604d..7a08982a 100644
--- a/runtime/transport/debugfs.c
+++ b/runtime/transport/debugfs.c
@@ -10,6 +10,7 @@
*/
#include <linux/debugfs.h>
+#include "transport.h"
#define STP_DEFAULT_BUFFERS 50
@@ -22,13 +23,14 @@ static struct dentry *_stp_cmd_file = NULL;
static int _stp_register_ctl_channel_fs(void)
{
- if (_stp_utt == NULL) {
- errk("_expected _stp_utt to be set.\n");
+ struct dentry *module_dir = _stp_get_module_dir();
+ if (module_dir == NULL) {
+ errk("no module directory found.\n");
return -1;
}
/* create [debugfs]/systemtap/module_name/.cmd */
- _stp_cmd_file = debugfs_create_file(".cmd", 0600, _stp_utt->dir,
+ _stp_cmd_file = debugfs_create_file(".cmd", 0600, module_dir,
NULL, &_stp_ctl_fops_cmd);
if (_stp_cmd_file == NULL) {
errk("Error creating systemtap debugfs entries.\n");
diff --git a/runtime/transport/relayfs.c b/runtime/transport/relayfs.c
index 6eefda8d..42be4283 100644
--- a/runtime/transport/relayfs.c
+++ b/runtime/transport/relayfs.c
@@ -86,7 +86,7 @@ static struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
if (!utt)
return NULL;
- utt->utt_tree_root = _stp_get_root_dir(utts->root);
+ utt->utt_tree_root = _stp_get_root_dir();
if (!utt->utt_tree_root)
goto err;
diff --git a/runtime/transport/ring_buffer.c b/runtime/transport/ring_buffer.c
new file mode 100644
index 00000000..51e9efa2
--- /dev/null
+++ b/runtime/transport/ring_buffer.c
@@ -0,0 +1,404 @@
+#include <linux/types.h>
+#include <linux/ring_buffer.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+
+static struct ring_buffer *__stp_ring_buffer = NULL;
+//DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
+
+/* _stp_poll_wait is a waitqueue for tasks blocked on
+ * _stp_data_poll_trace() */
+static DECLARE_WAIT_QUEUE_HEAD(_stp_poll_wait);
+
+#if 1
+/*
+ * Trace iterator - used by printout routines who present trace
+ * results to users and which routines might sleep, etc:
+ */
+struct _stp_ring_buffer_iterator {
+#if 0
+ struct trace_array *tr;
+ struct tracer *trace;
+ void *private;
+ struct ring_buffer_iter *buffer_iter[NR_CPUS];
+
+ /* The below is zeroed out in pipe_read */
+ struct trace_seq seq;
+ struct trace_entry *ent;
+#endif
+ int cpu;
+ u64 ts;
+
+#if 0
+ unsigned long iter_flags;
+ loff_t pos;
+ long idx;
+
+ cpumask_var_t started;
+#endif
+};
+static struct _stp_ring_buffer_iterator _stp_iter;
+#endif
+
+static void __stp_free_ring_buffer(void)
+{
+ if (__stp_ring_buffer)
+ ring_buffer_free(__stp_ring_buffer);
+ __stp_ring_buffer = NULL;
+}
+
+static int __stp_alloc_ring_buffer(void)
+{
+ int i;
+ unsigned long buffer_size = _stp_bufsize;
+
+ if (buffer_size == 0) {
+ dbug_trans(1, "using default buffer size...\n");
+ buffer_size = _stp_nsubbufs * _stp_subbuf_size;
+ }
+ /* The number passed to ring_buffer_alloc() is per cpu. Our
+ * 'buffer_size' is a total number of bytes to allocate. So,
+ * we need to divide buffer_size by the number of cpus. */
+ buffer_size /= num_online_cpus();
+ dbug_trans(1, "%lu\n", buffer_size);
+ __stp_ring_buffer = ring_buffer_alloc(buffer_size, 0);
+ if (!__stp_ring_buffer)
+ goto fail;
+
+ dbug_trans(1, "size = %lu\n", ring_buffer_size(__stp_ring_buffer));
+ return 0;
+
+fail:
+ __stp_free_ring_buffer();
+ return -ENOMEM;
+}
+
+static atomic_t _stp_trace_attached = ATOMIC_INIT(0);
+
+static int _stp_data_open_trace(struct inode *inode, struct file *file)
+{
+ /* We only allow for one reader */
+ dbug_trans(1, "trace attach\n");
+ if (atomic_inc_return(&_stp_trace_attached) != 1) {
+ atomic_dec(&_stp_trace_attached);
+ dbug_trans(1, "returning EBUSY\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int _stp_data_release_trace(struct inode *inode, struct file *file)
+{
+ dbug_trans(1, "trace detach\n");
+ atomic_dec(&_stp_trace_attached);
+ return 0;
+}
+
+struct trace_seq {
+ unsigned char buffer[PAGE_SIZE];
+ unsigned int len;
+ unsigned int readpos;
+};
+
+ssize_t
+_stp_trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
+{
+ int len;
+ int ret;
+
+ dbug_trans(1, "s: %p\n", s);
+ if (s == NULL)
+ return -EFAULT;
+
+ dbug_trans(1, "len: %d, readpos: %d, buffer: %p\n", s->len,
+ s->readpos, s->buffer);
+ if (s->len <= s->readpos)
+ return -EBUSY;
+
+ len = s->len - s->readpos;
+ if (cnt > len)
+ cnt = len;
+ ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
+ if (ret)
+ return -EFAULT;
+
+ s->readpos += len;
+ return cnt;
+}
+
+size_t
+_stp_entry_to_user(struct _stp_entry *entry, char __user *ubuf, size_t cnt)
+{
+ int ret;
+
+ dbug_trans(1, "entry(%p), ubuf(%p), cnt(%lu)\n", entry, ubuf, cnt);
+ if (entry == NULL || ubuf == NULL)
+ return -EFAULT;
+
+ /* We don't do partial entries - just fail. */
+ if (entry->len > cnt)
+ return -EBUSY;
+
+ if (cnt > entry->len)
+ cnt = entry->len;
+ ret = copy_to_user(ubuf, entry->buf, cnt);
+ if (ret)
+ return -EFAULT;
+
+ return cnt;
+}
+
+static void
+trace_seq_reset(struct trace_seq *s)
+{
+ s->len = 0;
+ s->readpos = 0;
+}
+
+static ssize_t tracing_wait_pipe(struct file *filp)
+{
+ while (ring_buffer_empty(__stp_ring_buffer)) {
+
+ if ((filp->f_flags & O_NONBLOCK)) {
+ dbug_trans(1, "returning -EAGAIN\n");
+ return -EAGAIN;
+ }
+
+ /*
+ * This is a make-shift waitqueue. The reason we don't use
+ * an actual wait queue is because:
+ * 1) we only ever have one waiter
+ * 2) the tracing, traces all functions, we don't want
+ * the overhead of calling wake_up and friends
+ * (and tracing them too)
+ * Anyway, this is really very primitive wakeup.
+ */
+ set_current_state(TASK_INTERRUPTIBLE);
+ //iter->tr->waiter = current;
+
+ /* sleep for 100 msecs, and try again. */
+ schedule_timeout(HZ/10);
+
+ //iter->tr->waiter = NULL;
+
+ if (signal_pending(current)) {
+ dbug_trans(1, "returning -EINTR\n");
+ return -EINTR;
+ }
+ }
+
+ dbug_trans(1, "returning 1\n");
+ return 1;
+}
+
+static struct _stp_entry *
+peek_next_entry(int cpu, u64 *ts)
+{
+ struct ring_buffer_event *event;
+
+ event = ring_buffer_peek(__stp_ring_buffer, cpu, ts);
+
+ return event ? ring_buffer_event_data(event) : NULL;
+}
+
+static struct _stp_entry *
+__find_next_entry(int *ent_cpu, u64 *ent_ts)
+{
+ struct _stp_entry *ent, *next = NULL;
+ u64 next_ts = 0, ts;
+ int next_cpu = -1;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+
+ if (ring_buffer_empty_cpu(__stp_ring_buffer, cpu))
+ continue;
+
+ ent = peek_next_entry(cpu, &ts);
+
+ /*
+ * Pick the entry with the smallest timestamp:
+ */
+ if (ent && (!next || ts < next_ts)) {
+ next = ent;
+ next_cpu = cpu;
+ next_ts = ts;
+ }
+ }
+
+ if (ent_cpu)
+ *ent_cpu = next_cpu;
+
+ if (ent_ts)
+ *ent_ts = next_ts;
+
+ return next;
+}
+
+/* Find the next real entry, and increment the iterator to the next entry */
+static struct _stp_entry *_stp_find_next_entry(void)
+{
+ return __find_next_entry(&_stp_iter.cpu, &_stp_iter.ts);
+}
+
+
+/*
+ * Consumer reader.
+ */
+static ssize_t
+_stp_data_read_trace(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ ssize_t sret;
+ struct _stp_entry *entry;
+
+ dbug_trans(1, "%lu\n", (unsigned long)cnt);
+
+ sret = tracing_wait_pipe(filp);
+ dbug_trans(1, "tracing_wait_pipe returned %ld\n", sret);
+ if (sret <= 0)
+ goto out;
+
+ /* stop when tracing is finished */
+ if (ring_buffer_empty(__stp_ring_buffer)) {
+ sret = 0;
+ goto out;
+ }
+
+ if (cnt >= PAGE_SIZE)
+ cnt = PAGE_SIZE - 1;
+
+ dbug_trans(1, "sret = %lu\n", (unsigned long)sret);
+ sret = 0;
+ while ((entry = _stp_find_next_entry()) != NULL) {
+ ssize_t len;
+
+ len = _stp_entry_to_user(entry, ubuf, cnt);
+ if (len <= 0)
+ break;
+
+ ring_buffer_consume(__stp_ring_buffer, _stp_iter.cpu,
+ &_stp_iter.ts);
+ ubuf += len;
+ cnt -= len;
+ sret += len;
+ if (cnt <= 0)
+ break;
+ }
+out:
+ return sret;
+}
+
+
+static unsigned int
+_stp_data_poll_trace(struct file *filp, poll_table *poll_table)
+{
+ dbug_trans(1, "entry\n");
+ if (! ring_buffer_empty(__stp_ring_buffer))
+ return POLLIN | POLLRDNORM;
+ poll_wait(filp, &_stp_poll_wait, poll_table);
+ if (! ring_buffer_empty(__stp_ring_buffer))
+ return POLLIN | POLLRDNORM;
+
+ dbug_trans(1, "exit\n");
+ return 0;
+}
+
+static struct file_operations __stp_data_fops = {
+ .owner = THIS_MODULE,
+ .open = _stp_data_open_trace,
+ .release = _stp_data_release_trace,
+ .poll = _stp_data_poll_trace,
+ .read = _stp_data_read_trace,
+#if 0
+ .splice_read = tracing_splice_read_pipe,
+#endif
+};
+
+/*
+ * This function prepares the cpu buffer to write a sample.
+ *
+ * Struct op_entry is used during operations on the ring buffer while
+ * struct op_sample contains the data that is stored in the ring
+ * buffer. Struct entry can be uninitialized. The function reserves a
+ * data array that is specified by size. Use
+ * op_cpu_buffer_write_commit() after preparing the sample. In case of
+ * errors a null pointer is returned, otherwise the pointer to the
+ * sample.
+ *
+ */
+static struct _stp_entry *
+_stp_data_write_reserve(size_t size)
+{
+ struct ring_buffer_event *event;
+ struct _stp_entry *entry;
+
+ event = ring_buffer_lock_reserve(__stp_ring_buffer,
+ (sizeof(struct _stp_entry) + size),
+ 0);
+ if (unlikely(! event)) {
+ dbug_trans(1, "event = NULL (%p)?\n", event);
+ return NULL;
+ }
+
+ entry = ring_buffer_event_data(event);
+ entry->event = event;
+ entry->len = size;
+ return entry;
+}
+
+static int _stp_data_write_commit(struct _stp_entry *entry)
+{
+ int ret;
+
+ if (unlikely(! entry)) {
+ dbug_trans(1, "entry = NULL, returning -EINVAL\n");
+ return -EINVAL;
+ }
+
+ ret = ring_buffer_unlock_commit(__stp_ring_buffer, entry->event, 0);
+ dbug_trans(1, "after commit, empty returns %d\n",
+ ring_buffer_empty(__stp_ring_buffer));
+
+ wake_up_interruptible(&_stp_poll_wait);
+ return ret;
+}
+
+
+static struct dentry *__stp_entry;
+
+static int _stp_transport_data_fs_init(void)
+{
+ int rc;
+
+ // allocate buffer
+ dbug_trans(1, "entry...\n");
+ rc = __stp_alloc_ring_buffer();
+ if (rc != 0)
+ return rc;
+
+ // create file(s)
+ __stp_entry = debugfs_create_file("trace0", 0600,
+ _stp_get_module_dir(),
+ NULL, &__stp_data_fops);
+ if (!__stp_entry)
+ pr_warning("Could not create debugfs 'trace' entry\n");
+ else {
+ __stp_entry->d_inode->i_uid = _stp_uid;
+ __stp_entry->d_inode->i_gid = _stp_gid;
+ }
+
+ dbug_trans(1, "returning 0...\n");
+ return 0;
+}
+
+static void _stp_transport_data_fs_close(void)
+{
+ if (__stp_entry)
+ debugfs_remove(__stp_entry);
+ __stp_entry = NULL;
+
+ __stp_free_ring_buffer();
+}
+
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 7fcebd42..c4c9da1e 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -14,19 +14,32 @@
#ifndef _TRANSPORT_TRANSPORT_C_
#define _TRANSPORT_TRANSPORT_C_
-#include <linux/delay.h>
-#include <linux/namei.h>
#include "transport.h"
-#include "time.c"
-#include "../mempool.c"
-#include "symbols.c"
+#include <linux/debugfs.h>
+#include <linux/namei.h>
+#include <linux/workqueue.h>
+
+static void utt_set_overwrite(int overwrite)
+{
+ return;
+}
+
+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;
+
+#if 0
+#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_called = 0;
-static int _stp_exit_flag = 0;
#include "control.h"
#ifdef STP_OLD_TRANSPORT
#include "relayfs.c"
@@ -37,6 +50,15 @@ static int _stp_exit_flag = 0;
#endif
#include "control.c"
+#else /* #if 0 */
+#include "control.h"
+#include "debugfs.c"
+#include "control.c"
+#include "ring_buffer.c"
+#endif /* if 0 */
+static unsigned _stp_nsubbufs = 8;
+static unsigned _stp_subbuf_size = 65536*4;
+
/* module parameters */
static int _stp_bufsize;
module_param(_stp_bufsize, int, 0);
@@ -45,7 +67,6 @@ MODULE_PARM_DESC(_stp_bufsize, "buffer size");
/* 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
@@ -89,6 +110,8 @@ 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 _stp_exit_called = 0;
+
if (!_stp_exit_called) {
int failures;
@@ -109,8 +132,10 @@ static void _stp_cleanup_and_exit(int send_exit)
_stp_warn("There were %d transport failures.\n", failures);
dbug_trans(1, "************** calling startstop 0 *************\n");
+#if 0
if (_stp_utt)
utt_trace_startstop(_stp_utt, 0, &utt_seq);
+#endif
dbug_trans(1, "ctl_send STP_EXIT\n");
if (send_exit)
@@ -125,7 +150,7 @@ static void _stp_cleanup_and_exit(int send_exit)
static void _stp_detach(void)
{
dbug_trans(1, "detach\n");
- _stp_attached = 0;
+ _stp_ctl_attached = 0;
_stp_pid = 0;
if (!_stp_exit_flag)
@@ -141,7 +166,7 @@ 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);
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
@@ -170,7 +195,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_cleanup_and_exit(1);
- if (likely(_stp_attached))
+ if (likely(_stp_ctl_attached))
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
}
@@ -180,19 +205,25 @@ 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 0
if (_stp_utt)
utt_trace_remove(_stp_utt);
+#endif /* #if 0 */
_stp_print_cleanup(); /* free print buffers */
_stp_mem_debug_done();
+ _stp_transport_fs_close();
+
dbug_trans(1, "---- CLOSED ----\n");
}
+#if 0
static struct utt_trace *_stp_utt_open(void)
{
struct utt_trace_setup utts;
@@ -209,6 +240,7 @@ static struct utt_trace *_stp_utt_open(void)
return utt_trace_setup(&utts);
}
+#endif /* #if 0 */
/**
* _stp_transport_init() is called from the module initialization.
@@ -217,7 +249,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;
@@ -226,6 +257,8 @@ static int _stp_transport_init(void)
_stp_gid = current_gid();
#endif
+// DRS: is RELAY_GUEST/RELAY_HOST documented? does it work? are there
+// test cases?
#ifdef RELAY_GUEST
/* Guest scripts use relay only for reporting warnings and errors */
_stp_subbuf_size = 65536;
@@ -243,12 +276,18 @@ static int _stp_transport_init(void)
dbug_trans(1, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size);
}
+ if (_stp_transport_fs_init(THIS_MODULE->name) != 0)
+ goto err0;
+
+#if 0
#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)
goto err0;
#endif
+#else /* #if 0 */
+#endif /* #if 0 */
/* create control channel */
if (_stp_register_ctl_channel() < 0)
@@ -258,29 +297,38 @@ static int _stp_transport_init(void)
if (_stp_print_init() < 0)
goto err2;
+#if 0
/* start transport */
utt_trace_startstop(_stp_utt, 1, &utt_seq);
+#endif /* #if 0 */
/* 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:
+ dbug_trans(1, "err3\n");
_stp_print_cleanup();
err2:
+ dbug_trans(1, "err2\n");
_stp_unregister_ctl_channel();
err1:
+#if 0
if (_stp_utt)
utt_trace_remove(_stp_utt);
+#else
+ dbug_trans(1, "err1\n");
+ _stp_transport_fs_close();
+#endif /* #if 0 */
err0:
+ dbug_trans(1, "err0\n");
return -1;
}
@@ -331,51 +379,124 @@ 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;
+
+/* _stp_get_root_dir() - creates root directory or returns
+ * a pointer to it if it already exists. */
-static struct dentry *_stp_get_root_dir(const char *name)
+static struct dentry *_stp_get_root_dir(void)
{
struct file_system_type *fs;
- struct dentry *root;
struct super_block *sb;
+ const char *name = "systemtap";
+
+ if (__stp_root_dir != NULL) {
+ return __stp_root_dir;
+ }
#ifdef STP_OLD_TRANSPORT
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);
+ __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");
}
}
_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))
+ debugfs_remove(__stp_root_dir);
+ _stp_unlock_transport_dir();
+ __stp_root_dir = NULL;
+ }
+}
+
+static struct dentry *__stp_module_dir = NULL;
+
+static inline 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;
+
+ __stp_module_dir = debugfs_create_dir(module_name, root_dir);
+ if (!__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) {
+ debugfs_remove(__stp_module_dir);
+ __stp_module_dir = NULL;
+ }
+
+ _stp_remove_root_dir();
+}
+
+
#endif /* _TRANSPORT_C_ */
diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h
index 7d249c45..feaa950c 100644
--- a/runtime/transport/transport.h
+++ b/runtime/transport/transport.h
@@ -11,6 +11,19 @@
/* amount of data a print can send. */
#define STP_BUFFER_SIZE 8192
+struct utt_trace;
+
+static int _stp_ctl_write(int type, void *data, unsigned len);
+
+static int _stp_transport_init(void);
+static void _stp_transport_close(void);
+
+static inline void *utt_reserve(struct utt_trace *utt, size_t length)
+{
+ return NULL;
+}
+
+
/* STP_CTL_BUFFER_SIZE is the maximum size of a message */
/* exchanged on the control channel. */
#ifdef STP_OLD_TRANSPORT
@@ -23,27 +36,41 @@
/* how often the work queue wakes up and checks buffers */
#define STP_WORK_TIMER (HZ/100)
-static unsigned _stp_nsubbufs = 8;
-static unsigned _stp_subbuf_size = 65536*4;
+static unsigned _stp_nsubbufs;
+static unsigned _stp_subbuf_size;
static int _stp_transport_init(void);
static void _stp_transport_close(void);
-static void _stp_warn (const char *fmt, ...);
-static int _stp_print_init(void);
-static void _stp_print_cleanup(void);
-static struct dentry *_stp_get_root_dir(const char *name);
-
static int _stp_lock_transport_dir(void);
static void _stp_unlock_transport_dir(void);
+static struct dentry *_stp_get_root_dir(void);
+static struct dentry *_stp_get_module_dir(void);
+
+static int _stp_transport_fs_init(const char *module_name);
+static void _stp_transport_fs_close(void);
+
static void _stp_attach(void);
static void _stp_detach(void);
static void _stp_handle_start(struct _stp_msg_start *st);
-static int _stp_pid = 0;
-static uid_t _stp_uid = 0;
-static gid_t _stp_gid = 0;
-static pid_t _stp_init_pid = 0;
-static int _stp_attached = 0;
+static uid_t _stp_uid;
+static gid_t _stp_gid;
+
+static int _stp_ctl_attached;
+
+static int _stp_bufsize;
+static int _stp_transport_data_fs_init(void);
+static void _stp_transport_data_fs_close(void);
+
+struct _stp_entry {
+ void *event;
+ size_t len;
+ char buf[];
+};
+
+static struct _stp_entry *_stp_data_write_reserve(size_t size);
+static int _stp_data_write_commit(struct _stp_entry *entry);
+
#endif /* _TRANSPORT_TRANSPORT_H_ */
diff --git a/runtime/transport/utt.c b/runtime/transport/utt.c
index 915662b2..2dd303a5 100644
--- a/runtime/transport/utt.c
+++ b/runtime/transport/utt.c
@@ -26,7 +26,6 @@
#include <linux/percpu.h>
#include <linux/init.h>
#include <linux/debugfs.h>
-#include <linux/relay.h>
#include <linux/mm.h>
#include "utt.h"
@@ -157,7 +156,7 @@ static struct dentry *utt_create_tree(struct utt_trace *utt, const char *root, c
return NULL;
if (!utt->utt_tree_root) {
- utt->utt_tree_root = _stp_get_root_dir(root);
+ utt->utt_tree_root = _stp_get_root_dir();
if (!utt->utt_tree_root)
goto err;
}
@@ -169,7 +168,6 @@ err:
return dir;
}
-
static void utt_trace_cleanup(struct utt_trace *utt)
{
if (utt == NULL)
diff --git a/runtime/transport/utt.h b/runtime/transport/utt.h
index 40e54919..0a0944c0 100644
--- a/runtime/transport/utt.h
+++ b/runtime/transport/utt.h
@@ -9,11 +9,11 @@ enum {
struct utt_trace {
int trace_state;
- struct rchan *rchan;
+// struct rchan *rchan;
struct dentry *dir; /* systemtap/module_name */
struct dentry *dropped_file;
atomic_t dropped;
- struct dentry *utt_tree_root; /* systemtap */
+ struct dentry *utt_tree_root; /* systemtap */
void *private_data;
atomic_t wakeup;
struct timer_list timer;
@@ -41,6 +41,7 @@ struct utt_trace_setup {
static struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts);
+
static int utt_trace_startstop(struct utt_trace *utt, int start,
unsigned int *trace_seq);
static void utt_trace_cleanup(struct utt_trace *utt);
@@ -60,6 +61,7 @@ static size_t utt_switch_subbuf(struct utt_trace *utt, struct rchan_buf *buf,
*/
static inline void *utt_reserve(struct utt_trace *utt, size_t length)
{
+#if 0
void *reserved;
struct rchan_buf *buf = utt->rchan->buf[smp_processor_id()];
@@ -72,6 +74,9 @@ static inline void *utt_reserve(struct utt_trace *utt, size_t length)
buf->offset += length;
return reserved;
+#else
+ return NULL;
+#endif
}
#endif
diff --git a/testsuite/systemtap.printf/end1.exp b/testsuite/systemtap.printf/end1.exp
index 0a4dd32e..e4f164f5 100644
--- a/testsuite/systemtap.printf/end1.exp
+++ b/testsuite/systemtap.printf/end1.exp
@@ -11,15 +11,15 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -o $tmpfile $tpath} res]} {
- untested $TEST_NAME
- puts "$res"
+ fail $TEST_NAME
+ puts "stap failed: $res"
catch {exec rm -f $tmpfile}
return
}
if {[catch {exec cmp $tmpfile $srcdir/$subdir/large_output} res]} {
- fail $TEST_NAME
puts "$res"
+ fail $TEST_NAME
catch {exec rm -f $tmpfile}
return
}
diff --git a/testsuite/systemtap.printf/end1b.exp b/testsuite/systemtap.printf/end1b.exp
index 1764a383..08cfa648 100644
--- a/testsuite/systemtap.printf/end1b.exp
+++ b/testsuite/systemtap.printf/end1b.exp
@@ -16,8 +16,8 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -b -o $tmpfile $test} res]} {
- untested $TEST_NAME
puts "stap failed: $res"
+ fail $TEST_NAME
as_root "/bin/rm -f [glob ${tmpfile}*]"
return
}
diff --git a/testsuite/systemtap.printf/mixed_out.exp b/testsuite/systemtap.printf/mixed_out.exp
index 093a8ca1..d73a55a6 100644
--- a/testsuite/systemtap.printf/mixed_out.exp
+++ b/testsuite/systemtap.printf/mixed_out.exp
@@ -11,8 +11,8 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -DMAXACTION=100000 -o $tmpfile $tpath} res]} {
- untested $TEST_NAME
- puts "$res"
+ fail $TEST_NAME
+ puts "stap failed: $res"
catch {exec rm -f $tmpfile}
return
}
diff --git a/testsuite/systemtap.printf/mixed_outb.exp b/testsuite/systemtap.printf/mixed_outb.exp
index cbf7b920..30c0c92f 100644
--- a/testsuite/systemtap.printf/mixed_outb.exp
+++ b/testsuite/systemtap.printf/mixed_outb.exp
@@ -16,7 +16,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -DMAXACTION=100000 -b -o $tmpfile $test} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "stap failed: $res"
as_root "/bin/rm -f [glob ${tmpfile}*]"
return
diff --git a/testsuite/systemtap.printf/out1.exp b/testsuite/systemtap.printf/out1.exp
index f89d39bf..d5728c0f 100644
--- a/testsuite/systemtap.printf/out1.exp
+++ b/testsuite/systemtap.printf/out1.exp
@@ -11,7 +11,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -o $tmpfile $tpath} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "$res"
catch {exec rm -f $tmpfile}
return
diff --git a/testsuite/systemtap.printf/out1b.exp b/testsuite/systemtap.printf/out1b.exp
index 378ea5cd..2f702a2f 100644
--- a/testsuite/systemtap.printf/out1b.exp
+++ b/testsuite/systemtap.printf/out1b.exp
@@ -16,7 +16,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -b -o $tmpfile $test} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "stap failed: $res"
as_root "/bin/rm -f [glob ${tmpfile}*]"
return
diff --git a/testsuite/systemtap.printf/out2.exp b/testsuite/systemtap.printf/out2.exp
index 7b312b11..dd96f394 100644
--- a/testsuite/systemtap.printf/out2.exp
+++ b/testsuite/systemtap.printf/out2.exp
@@ -11,7 +11,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -o $tmpfile $tpath} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "$res"
catch {exec rm -f $tmpfile}
return
diff --git a/testsuite/systemtap.printf/out2b.exp b/testsuite/systemtap.printf/out2b.exp
index f7fdef6b..0b56c940 100644
--- a/testsuite/systemtap.printf/out2b.exp
+++ b/testsuite/systemtap.printf/out2b.exp
@@ -16,7 +16,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -b -o $tmpfile $test} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "stap failed: $res"
as_root "/bin/rm -f [glob ${tmpfile}*]"
return
diff --git a/testsuite/systemtap.printf/out3.exp b/testsuite/systemtap.printf/out3.exp
index c16db391..96ca2bc5 100644
--- a/testsuite/systemtap.printf/out3.exp
+++ b/testsuite/systemtap.printf/out3.exp
@@ -11,7 +11,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -DMAXACTION=100000 -o $tmpfile $tpath} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "$res"
catch {exec rm -f $tmpfile}
return
diff --git a/testsuite/systemtap.printf/out3b.exp b/testsuite/systemtap.printf/out3b.exp
index 16ee2182..c42d03b7 100644
--- a/testsuite/systemtap.printf/out3b.exp
+++ b/testsuite/systemtap.printf/out3b.exp
@@ -16,7 +16,7 @@ if {[catch {exec mktemp -t staptestXXXXX} tmpfile]} {
}
if {[catch {exec stap -DMAXACTION=100000 -b -o $tmpfile $test} res]} {
- untested $TEST_NAME
+ fail $TEST_NAME
puts "stap failed: $res"
as_root "/bin/rm -f [glob ${tmpfile}*]"
return