summaryrefslogtreecommitdiffstats
path: root/runtime/transport
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2009-05-22 10:50:30 -0500
committerDavid Smith <dsmith@redhat.com>2009-05-22 10:50:30 -0500
commite57421f400d17786c1fdbead5fbca27a1fbe4ec5 (patch)
treedaefda43d0be0bbf3552d45101693cc07c480a14 /runtime/transport
parentc8e9eb18d8d13d099a4a177fe53de507c1d9ce8b (diff)
downloadsystemtap-steved-e57421f400d17786c1fdbead5fbca27a1fbe4ec5.tar.gz
systemtap-steved-e57421f400d17786c1fdbead5fbca27a1fbe4ec5.tar.xz
systemtap-steved-e57421f400d17786c1fdbead5fbca27a1fbe4ec5.zip
Added error checking and other updates.
* runtime/vsprintf.c: Added transport.h inclusion for STP_BUFFER_SIZE definition. * runtime/transport/debugfs.c (_stp_register_ctl_channel_fs): Added error checking. * runtime/transport/transport.c (_stp_get_root_dir): Ditto. (_stp_transport_fs_init): Added original transport support and error checking. * runtime/transport/relay_v2.c (__stp_relay_create_buf_file_callback): Added error checking. (_stp_transport_data_fs_init): Ditto. * runtime/transport/ring_buffer.c (_stp_transport_data_fs_init): Ditto. * runtime/transport/utt.c: Removed unused file. * runtime/transport/utt.h: Ditto.
Diffstat (limited to 'runtime/transport')
-rw-r--r--runtime/transport/debugfs.c7
-rw-r--r--runtime/transport/relay_v2.c11
-rw-r--r--runtime/transport/ring_buffer.c7
-rw-r--r--runtime/transport/transport.c18
-rw-r--r--runtime/transport/utt.c404
-rw-r--r--runtime/transport/utt.h83
6 files changed, 42 insertions, 488 deletions
diff --git a/runtime/transport/debugfs.c b/runtime/transport/debugfs.c
index 7a08982a..6bbef53b 100644
--- a/runtime/transport/debugfs.c
+++ b/runtime/transport/debugfs.c
@@ -36,6 +36,13 @@ static int _stp_register_ctl_channel_fs(void)
errk("Error creating systemtap debugfs entries.\n");
return -1;
}
+ else if (IS_ERR(_stp_cmd_file)) {
+ _stp_cmd_file = NULL;
+ errk("Error creating systemtap debugfs entries: %ld\n",
+ -PTR_ERR(_stp_cmd_file));
+ return -1;
+ }
+
_stp_cmd_file->d_inode->i_uid = _stp_uid;
_stp_cmd_file->d_inode->i_gid = _stp_gid;
diff --git a/runtime/transport/relay_v2.c b/runtime/transport/relay_v2.c
index c0a772ed..0c8d0955 100644
--- a/runtime/transport/relay_v2.c
+++ b/runtime/transport/relay_v2.c
@@ -204,7 +204,10 @@ __stp_relay_create_buf_file_callback(const char *filename,
{
struct dentry *file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
- if (file) {
+ if (IS_ERR(file)) {
+ file = NULL;
+ }
+ else if (file) {
file->d_inode->i_uid = _stp_uid;
file->d_inode->i_gid = _stp_gid;
}
@@ -251,6 +254,12 @@ static int _stp_transport_data_fs_init(void)
rc = -EIO;
goto err;
}
+ else if (IS_ERR(_stp_relay_data.dropped_file)) {
+ rc = PTR_ERR(_stp_relay_data.dropped_file);
+ _stp_relay_data.dropped_file = NULL;
+ goto err;
+ }
+
_stp_relay_data.dropped_file->d_inode->i_uid = _stp_uid;
_stp_relay_data.dropped_file->d_inode->i_gid = _stp_gid;
diff --git a/runtime/transport/ring_buffer.c b/runtime/transport/ring_buffer.c
index 0385e7d3..217d0735 100644
--- a/runtime/transport/ring_buffer.c
+++ b/runtime/transport/ring_buffer.c
@@ -405,6 +405,13 @@ static int _stp_transport_data_fs_init(void)
__stp_free_ring_buffer();
return -ENOENT;
}
+ else if (IS_ERR(__stp_entry[cpu])) {
+ rc = PTR_ERR(__stp_entry[cpu]);
+ pr_warning("Could not create debugfs 'trace' entry\n");
+ __stp_free_ring_buffer();
+ return rc;
+ }
+
__stp_entry[cpu]->d_inode->i_uid = _stp_uid;
__stp_entry[cpu]->d_inode->i_gid = _stp_gid;
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 792ea815..ab0806f2 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -453,6 +453,12 @@ static struct dentry *_stp_get_root_dir(void)
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 __stp_root_dir;
}
@@ -490,8 +496,20 @@ static int _stp_transport_fs_init(const char *module_name)
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;
}
diff --git a/runtime/transport/utt.c b/runtime/transport/utt.c
deleted file mode 100644
index 2dd303a5..00000000
--- a/runtime/transport/utt.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/* -*- linux-c -*-
- *
- * This is a modified version of the proposed utt interface. If that
- * interface makes it into the kernel, this file can go away.
- *
- * Copyright (C) 2006 Jens Axboe <axboe@suse.de>
- *
- * Moved to utt.c by Tom Zanussi, 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/percpu.h>
-#include <linux/init.h>
-#include <linux/debugfs.h>
-#include <linux/mm.h>
-#include "utt.h"
-
-static int utt_overwrite_flag = 0;
-
-/*
- * utt_switch_subbuf - switch to a new sub-buffer
- *
- * Most of this function is deadcopy of relay_switch_subbuf.
- */
-static size_t utt_switch_subbuf(struct utt_trace *utt, struct rchan_buf *buf,
- size_t length)
-{
- char *old, *new;
- size_t old_subbuf, new_subbuf;
-
- if (unlikely(buf == NULL))
- return 0;
-
- if (unlikely(length > buf->chan->subbuf_size))
- goto toobig;
-
- if (buf->offset != buf->chan->subbuf_size + 1) {
- buf->prev_padding = buf->chan->subbuf_size - buf->offset;
- old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
- buf->padding[old_subbuf] = buf->prev_padding;
- buf->subbufs_produced++;
- buf->dentry->d_inode->i_size += buf->chan->subbuf_size -
- buf->padding[old_subbuf];
- smp_mb();
- if (waitqueue_active(&buf->read_wait))
- /*
- * Calling wake_up_interruptible() and __mod_timer()
- * from here will deadlock if we happen to be logging
- * from the scheduler and timer (trying to re-grab
- * rq->lock/timer->base->lock), so just set a flag.
- */
- atomic_set(&utt->wakeup, 1);
- }
-
- old = buf->data;
- new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
- new = (char*)buf->start + new_subbuf * buf->chan->subbuf_size;
- buf->offset = 0;
- if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
- buf->offset = buf->chan->subbuf_size + 1;
- return 0;
- }
- buf->data = new;
- buf->padding[new_subbuf] = 0;
-
- if (unlikely(length + buf->offset > buf->chan->subbuf_size))
- goto toobig;
-
- return length;
-
-toobig:
- buf->chan->last_toobig = length;
- return 0;
-}
-
-static void __utt_wakeup_readers(struct rchan_buf *buf)
-{
- if (buf && waitqueue_active(&buf->read_wait) &&
- buf->subbufs_produced != buf->subbufs_consumed)
- wake_up_interruptible(&buf->read_wait);
-}
-
-static void __utt_wakeup_timer(unsigned long val)
-{
- struct utt_trace *utt = (struct utt_trace *)val;
- int i;
-
- if (atomic_read(&utt->wakeup)) {
- atomic_set(&utt->wakeup, 0);
- if (utt->is_global)
- __utt_wakeup_readers(utt->rchan->buf[0]);
- else
- for_each_possible_cpu(i)
- __utt_wakeup_readers(utt->rchan->buf[i]);
- }
-
- mod_timer(&utt->timer, jiffies + UTT_TIMER_INTERVAL);
-}
-
-static void __utt_timer_init(struct utt_trace * utt)
-{
- atomic_set(&utt->wakeup, 0);
- init_timer(&utt->timer);
- utt->timer.expires = jiffies + UTT_TIMER_INTERVAL;
- utt->timer.function = __utt_wakeup_timer;
- utt->timer.data = (unsigned long)utt;
- add_timer(&utt->timer);
-}
-
-static void utt_set_overwrite(int overwrite)
-{
- utt_overwrite_flag = overwrite;
-}
-
-static void utt_remove_root(struct utt_trace *utt)
-{
- if (utt->utt_tree_root) {
- if (!_stp_lock_transport_dir()) {
- errk("Unable to lock transport directory.\n");
- return;
- }
- if (simple_empty(utt->utt_tree_root))
- debugfs_remove(utt->utt_tree_root);
- _stp_unlock_transport_dir();
- utt->utt_tree_root = NULL;
- }
-}
-
-static void utt_remove_tree(struct utt_trace *utt)
-{
- if (utt == NULL || utt->dir == NULL)
- return;
- debugfs_remove(utt->dir);
- utt_remove_root(utt);
-}
-
-static struct dentry *utt_create_tree(struct utt_trace *utt, const char *root, const char *name)
-{
- struct dentry *dir = NULL;
-
- if (root == NULL || name == NULL)
- return NULL;
-
- if (!utt->utt_tree_root) {
- utt->utt_tree_root = _stp_get_root_dir();
- if (!utt->utt_tree_root)
- goto err;
- }
-
- dir = debugfs_create_dir(name, utt->utt_tree_root);
- if (!dir)
- utt_remove_root(utt);
-err:
- return dir;
-}
-
-static void utt_trace_cleanup(struct utt_trace *utt)
-{
- if (utt == NULL)
- return;
- if (utt->rchan)
- relay_close(utt->rchan);
- if (utt->dropped_file)
- debugfs_remove(utt->dropped_file);
- utt_remove_tree(utt);
- _stp_kfree(utt);
-}
-
-static int utt_trace_remove(struct utt_trace *utt)
-{
- if (utt->trace_state == Utt_trace_setup ||
- utt->trace_state == Utt_trace_stopped)
- utt_trace_cleanup(utt);
-
- return 0;
-}
-
-static int utt_dropped_open(struct inode *inode, struct file *filp)
-{
-#ifdef STAPCONF_INODE_PRIVATE
- filp->private_data = inode->i_private;
-#else
- filp->private_data = inode->u.generic_ip;
-#endif
- return 0;
-}
-
-static ssize_t utt_dropped_read(struct file *filp, char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct utt_trace *utt = filp->private_data;
- char buf[16];
-
- snprintf(buf, sizeof(buf), "%u\n", atomic_read(&utt->dropped));
-
- return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
-}
-
-static struct file_operations utt_dropped_fops = {
- .owner = THIS_MODULE,
- .open = utt_dropped_open,
- .read = utt_dropped_read,
-};
-
-/*
- * Keep track of how many times we encountered a full subbuffer, to aid
- * the user space app in telling how many lost events there were.
- */
-static int utt_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
- void *prev_subbuf, size_t prev_padding)
-{
- struct utt_trace *utt;
-
- if (utt_overwrite_flag || !relay_buf_full(buf))
- return 1;
-
- utt = buf->chan->private_data;
- atomic_inc(&utt->dropped);
- return 0;
-}
-
-static int utt_remove_buf_file_callback(struct dentry *dentry)
-{
- debugfs_remove(dentry);
- return 0;
-}
-
-static struct dentry *utt_create_buf_file_callback(const char *filename,
- struct dentry *parent,
- int mode,
- struct rchan_buf *buf,
- int *is_global)
-{
- struct dentry *file = debugfs_create_file(filename, mode, parent, buf,
- &relay_file_operations);
- if (file) {
- file->d_inode->i_uid = _stp_uid;
- file->d_inode->i_gid = _stp_gid;
- }
- return file;
-}
-
-static struct dentry *utt_create_global_buf_file_callback(const char *filename,
- struct dentry *parent,
- int mode,
- struct rchan_buf *buf,
- int *is_global)
-{
- struct dentry *file;
- *is_global = 1;
- file = debugfs_create_file(filename, mode, parent, buf,
- &relay_file_operations);
- if (file) {
- file->d_inode->i_uid = _stp_uid;
- file->d_inode->i_gid = _stp_gid;
- }
- return file;
-}
-
-static struct rchan_callbacks utt_relay_callbacks = {
- .subbuf_start = utt_subbuf_start_callback,
- .create_buf_file = utt_create_buf_file_callback,
- .remove_buf_file = utt_remove_buf_file_callback,
-};
-
-static struct rchan_callbacks utt_relay_callbacks_global = {
- .subbuf_start = utt_subbuf_start_callback,
- .create_buf_file = utt_create_global_buf_file_callback,
- .remove_buf_file = utt_remove_buf_file_callback,
-};
-
-/*
- * Setup everything required to start tracing
- */
-static struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
-{
- struct utt_trace *utt = NULL;
- struct dentry *dir = NULL;
- int ret = -EINVAL;
- u64 npages;
- struct sysinfo si;
-
- if (!utts->buf_size || !utts->buf_nr)
- goto err;
-
- ret = -ENOMEM;
- utt = _stp_kzalloc(sizeof(*utt));
- if (!utt)
- goto err;
-
- ret = -ENOENT;
- dir = utt_create_tree(utt, utts->root, utts->name);
- if (!dir)
- goto err;
- utt->dir = dir;
- atomic_set(&utt->dropped, 0);
-
- ret = -EIO;
- utt->dropped_file = debugfs_create_file("dropped", 0444, dir, utt, &utt_dropped_fops);
- if (!utt->dropped_file)
- goto err;
-
- npages = utts->buf_size * utts->buf_nr;
- if (!utts->is_global)
- npages *= num_possible_cpus();
- npages >>= PAGE_SHIFT;
- si_meminfo(&si);
-#define MB(i) (unsigned long)((i) >> (20 - PAGE_SHIFT))
- if (npages > (si.freeram + si.bufferram)) {
- errk("Not enough free+buffered memory(%luMB) for log buffer(%luMB)\n",
- MB(si.freeram + si.bufferram),
- MB(npages));
- ret = -ENOMEM;
- goto err;
- } else if (npages > si.freeram) {
- /* exceeds freeram, but below freeram+bufferram */
- printk(KERN_WARNING
- "log buffer size exceeds free memory(%luMB)\n",
- MB(si.freeram));
- }
-
-#if (RELAYFS_CHANNEL_VERSION >= 7)
- if (utts->is_global)
- utt->rchan = relay_open("trace", dir, utts->buf_size, utts->buf_nr,
- &utt_relay_callbacks_global, NULL);
- else
- utt->rchan = relay_open("trace", dir, utts->buf_size, utts->buf_nr,
- &utt_relay_callbacks, NULL);
-#else
- if (utts->is_global)
- utt->rchan = relay_open("trace", dir, utts->buf_size, utts->buf_nr, &utt_relay_callbacks_global);
- else
- utt->rchan = relay_open("trace", dir, utts->buf_size, utts->buf_nr, &utt_relay_callbacks);
-#endif
-
- if (!utt->rchan)
- goto err;
- utt->rchan->private_data = utt;
-
- utt->is_global = utts->is_global;
-
- utt->trace_state = Utt_trace_setup;
-
- utts->err = 0;
- return utt;
-err:
- if (utt) {
- if (utt->dropped_file)
- debugfs_remove(utt->dropped_file);
- if (utt->rchan)
- relay_close(utt->rchan);
- _stp_kfree(utt);
- }
- if (dir)
- utt_remove_tree(utt);
- utts->err = ret;
- return NULL;
-}
-
-static int utt_trace_startstop(struct utt_trace *utt, int start,
- unsigned int *trace_seq)
-{
- int ret;
-
- /*
- * For starting a trace, we can transition from a setup or stopped
- * trace. For stopping a trace, the state must be running
- */
- ret = -EINVAL;
- if (start) {
- if (utt->trace_state == Utt_trace_setup ||
- utt->trace_state == Utt_trace_stopped) {
- if (trace_seq)
- (*trace_seq)++;
- __utt_timer_init(utt);
- smp_mb();
- utt->trace_state = Utt_trace_running;
- ret = 0;
- }
- } else {
- if (utt->trace_state == Utt_trace_running) {
- utt->trace_state = Utt_trace_stopped;
- del_timer_sync(&utt->timer);
- relay_flush(utt->rchan);
- ret = 0;
- }
- }
-
- return ret;
-}
diff --git a/runtime/transport/utt.h b/runtime/transport/utt.h
deleted file mode 100644
index 2a479d70..00000000
--- a/runtime/transport/utt.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef UTT_H
-#define UTT_H
-
-enum {
- Utt_trace_setup = 1,
- Utt_trace_running,
- Utt_trace_stopped,
-};
-
-struct utt_trace {
- int trace_state;
-// struct rchan *rchan;
- struct dentry *dir; /* systemtap/module_name */
- struct dentry *dropped_file;
- atomic_t dropped;
- struct dentry *utt_tree_root; /* systemtap */
- void *private_data;
- atomic_t wakeup;
- struct timer_list timer;
- int is_global;
-};
-
-#define UTT_TRACE_ROOT_NAME_SIZE 64 /* Largest string for a root dir identifier */
-#define UTT_TRACE_NAME_SIZE 64 /* Largest string for a trace identifier */
-
-#ifndef UTT_TIMER_INTERVAL
-#define UTT_TIMER_INTERVAL ((HZ + 99) / 100) /* Wakeup timer interval in jiffies (default 10 ms)*/
-#endif
-
-/*
- * User setup structure
- */
-struct utt_trace_setup {
- char root[UTT_TRACE_ROOT_NAME_SIZE]; /* input */
- char name[UTT_TRACE_NAME_SIZE]; /* input */
- u32 buf_size; /* input */
- u32 buf_nr; /* input */
- int is_global; /* input */
- int err; /* output */
-};
-
-
-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);
-static int utt_trace_remove(struct utt_trace *utt);
-
-#if STP_TRANSPORT_VERSION == 2
-static size_t utt_switch_subbuf(struct utt_trace *utt, struct rchan_buf *buf,
- size_t length);
-/**
- * utt_reserve - reserve slot in channel buffer
- * @utt: utt channel
- * @length: number of bytes to reserve
- *
- * Returns pointer to reserved slot, NULL if full.
- *
- * This function is utt_switch_subbuf version of relay_reserve.
- */
-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()];
-
- if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
- length = utt_switch_subbuf(utt, buf, length);
- if (!length)
- return NULL;
- }
- reserved = (char*)buf->data + buf->offset;
- buf->offset += length;
-
- return reserved;
-#else
- return NULL;
-#endif
-}
-#endif
-
-#endif