diff options
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 |