From e57421f400d17786c1fdbead5fbca27a1fbe4ec5 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 22 May 2009 10:50:30 -0500 Subject: [PATCH] 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. --- runtime/transport/debugfs.c | 7 + runtime/transport/relay_v2.c | 11 +- runtime/transport/ring_buffer.c | 7 + runtime/transport/transport.c | 18 ++ runtime/transport/utt.c | 404 -------------------------------- runtime/transport/utt.h | 83 ------- runtime/vsprintf.c | 2 + 7 files changed, 44 insertions(+), 488 deletions(-) delete mode 100644 runtime/transport/utt.c delete mode 100644 runtime/transport/utt.h diff --git a/runtime/transport/debugfs.c b/runtime/transport/debugfs.c index 7a08982ae..6bbef53b1 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 c0a772edf..0c8d0955b 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 0385e7d31..217d07351 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 792ea815e..ab0806f2b 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 2dd303a51..000000000 --- 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 - * - * 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 -#include -#include -#include -#include -#include -#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 2a479d70b..000000000 --- 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 diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c index 23810e759..674946b9d 100644 --- a/runtime/vsprintf.c +++ b/runtime/vsprintf.c @@ -12,6 +12,8 @@ #ifndef _VSPRINTF_C_ #define _VSPRINTF_C_ +#include "transport/transport.h" + //forward declaration for _stp_vsnprintf static void * _stp_reserve_bytes (int); -- 2.43.5