diff options
-rw-r--r-- | runtime/transport/ChangeLog | 8 | ||||
-rw-r--r-- | runtime/transport/control.c | 6 | ||||
-rw-r--r-- | runtime/transport/procfs.c | 59 | ||||
-rw-r--r-- | runtime/transport/relayfs.c | 50 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 2 | ||||
-rw-r--r-- | runtime/transport/transport.c | 108 | ||||
-rw-r--r-- | runtime/transport/transport.h | 3 | ||||
-rw-r--r-- | runtime/transport/utt.c | 40 | ||||
-rw-r--r-- | runtime/transport/utt.h | 7 |
9 files changed, 220 insertions, 63 deletions
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index f752ccd4..e588e546 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,11 @@ +2007-03-26 Martin Hunt <hunt@redhat.com> + + * symbols.c (_stp_do_module): If a module has no symbols, just + return NULL instead of an errorcode. + + * control.c, procfs.c, relayfs.c, transport.c, utt.c, utt.h: + Revert back to using systemtap/modulename instead of systemtap_pid. + 2007-03-21 Martin Hunt <hunt@redhat.com> * symbols.c (_stp_del_module): Add a call to _stp_module_relocate diff --git a/runtime/transport/control.c b/runtime/transport/control.c index 3ad3e309..2924edab 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -206,7 +206,6 @@ _stp_ctl_read_cmd (struct file *file, char __user *buf, size_t count, loff_t *pp return len; } - static struct file_operations _stp_ctl_fops_cmd = { .owner = THIS_MODULE, .read = _stp_ctl_read_cmd, @@ -240,11 +239,10 @@ static int _stp_register_ctl_channel (void) } - /* create [debugfs]/systemtap_[pid]/cmd */ - _stp_cmd_file = debugfs_create_file("cmd", 0444, _stp_utt->utt_tree_root, NULL, &_stp_ctl_fops_cmd); + /* create [debugfs]/systemtap/module_name/cmd */ + _stp_cmd_file = debugfs_create_file("cmd", 0444, _stp_utt->dir, NULL, &_stp_ctl_fops_cmd); if (_stp_cmd_file == NULL) goto err0; - return 0; err0: diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index bb97c411..92724f9f 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -244,7 +244,7 @@ static struct file_operations _stp_proc_fops_cmd = { .write = _stp_ctl_write_cmd, }; -static struct proc_dir_entry *_stp_proc_root, *_stp_proc_pid; +static struct proc_dir_entry *_stp_proc_root, *_stp_proc_mod; /* copy since proc_match is not MODULE_EXPORT'd */ static int my_proc_match(int len, const char *name, struct proc_dir_entry *de) @@ -295,6 +295,7 @@ err: static int _stp_register_ctl_channel (void) { int i; + const char *dirname = "systemtap"; char buf[32]; #ifdef STP_BULKMODE int j; @@ -316,30 +317,53 @@ static int _stp_register_ctl_channel (void) list_add (p, &_stp_pool_q); } - /* now create /proc/systemtap_[pid] */ - sprintf(buf, "systemtap_%d", _stp_pid); - _stp_proc_pid = proc_mkdir (buf, NULL); - if (!_stp_proc_pid) + if (!_stp_lock_debugfs()) { + errk("Unable to lock transport directory.\n"); goto err0; + } + + /* look for existing /proc/systemtap */ + for (de = proc_root.subdir; de; de = de->next) { + if (my_proc_match (strlen (dirname), dirname, de)) { + _stp_proc_root = de; + break; + } + } + + /* create /proc/systemtap if it doesn't exist */ + if (_stp_proc_root == NULL) { + _stp_proc_root = proc_mkdir (dirname, NULL); + if (_stp_proc_root == NULL) { + _stp_unlock_debugfs(); + goto err0; + } + } + _stp_unlock_debugfs(); + + /* now create /proc/systemtap/module_name */ + _stp_proc_mod = proc_mkdir (THIS_MODULE->name, _stp_proc_root); + if (_stp_proc_mod == NULL) + goto err0; + #ifdef STP_BULKMODE - /* now for each cpu "n", create /proc/systemtap_[pid]/n */ + /* now for each cpu "n", create /proc/systemtap/module_name/n */ for_each_cpu(i) { sprintf(buf, "%d", i); - de = create_proc_entry (buf, S_IFREG|S_IRUSR, _stp_proc_pid); + de = create_proc_entry (buf, S_IFREG|S_IRUSR, _stp_proc_mod); if (de == NULL) goto err1; de->proc_fops = &_stp_proc_fops; de->data = _stp_kmalloc(sizeof(int)); if (de->data == NULL) { - remove_proc_entry (buf, _stp_proc_pid); + remove_proc_entry (buf, _stp_proc_mod); goto err1; } *(int *)de->data = i; } #endif /* STP_BULKMODE */ - /* finally create /proc/systemtap_[pid]/cmd */ - de = create_proc_entry ("cmd", S_IFREG|S_IRUSR, _stp_proc_pid); + /* finally create /proc/systemtap/module_name/cmd */ + de = create_proc_entry ("cmd", S_IFREG|S_IRUSR, _stp_proc_mod); if (de == NULL) goto err1; de->proc_fops = &_stp_proc_fops_cmd; @@ -347,18 +371,16 @@ static int _stp_register_ctl_channel (void) err1: #ifdef STP_BULKMODE - for (de = _stp_proc_pid->subdir; de; de = de->next) + for (de = _stp_proc_mod->subdir; de; de = de->next) kfree (de->data); for_each_cpu(j) { if (j == i) break; sprintf(buf, "%d", i); - remove_proc_entry (buf, _stp_proc_pid); + remove_proc_entry (buf, _stp_proc_mod); } #endif /* STP_BULKMODE */ - sprintf(buf, "systemtap_%d", _stp_pid); - remove_proc_entry (buf, NULL); err0: list_for_each_safe(p, tmp, &_stp_pool_q) { list_del(p); @@ -378,18 +400,17 @@ static void _stp_unregister_ctl_channel (void) int i; struct proc_dir_entry *de; kbug("unregistering procfs\n"); - for (de = _stp_proc_pid->subdir; de; de = de->next) + for (de = _stp_proc_mod->subdir; de; de = de->next) kfree (de->data); for_each_cpu(i) { sprintf(buf, "%d", i); - remove_proc_entry (buf, _stp_proc_pid); + remove_proc_entry (buf, _stp_proc_mod); } #endif /* STP_BULKMODE */ - remove_proc_entry ("cmd", _stp_proc_pid); - sprintf(buf, "systemtap_%d", _stp_pid); - remove_proc_entry (buf, NULL); + remove_proc_entry ("cmd", _stp_proc_mod); + remove_proc_entry (THIS_MODULE->name, _stp_proc_root); /* free memory pools */ list_for_each_safe(p, tmp, &_stp_pool_q) { diff --git a/runtime/transport/relayfs.c b/runtime/transport/relayfs.c index ccbdc63e..2615145c 100644 --- a/runtime/transport/relayfs.c +++ b/runtime/transport/relayfs.c @@ -26,13 +26,6 @@ static int _stp_relay_flushing = 0; -static void _stp_remove_relay_dir(struct dentry *dir) -{ - if (dir) - relayfs_remove_dir(dir); -} - - /** * _stp_subbuf_start - subbuf_start() relayfs callback implementation */ @@ -66,10 +59,22 @@ static struct rchan_callbacks stp_rchan_callbacks = }; +static void _stp_remove_relay_dir(struct dentry *dir) +{ + if (dir) + relayfs_remove_dir(dir); +} + static void _stp_remove_relay_root(struct dentry *root) { - if (root) + if (root) { + if (!_stp_lock_debugfs()) { + errk("Unable to lock transport directory.\n"); + return; + } _stp_remove_relay_dir(root); + _stp_unlock_debugfs(); + } } struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts) @@ -80,25 +85,31 @@ struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts) if (!utt) return NULL; - utt->utt_tree_root = relayfs_create_dir(utts->root, NULL); - if (!utt->utt_tree_root) { - errk("couldn't get relay root dir.\n"); + utt->utt_tree_root = _stp_get_root_dir(utts->root); + if (!utt->utt_tree_root) return NULL; - } - + utt->dir = relayfs_create_dir(utts->name, utt->utt_tree_root); + if (!utt->dir) + goto err; + kbug("relay_open %d %d\n", utts->buf_size, utts->buf_nr); - utt->rchan = relay_open("trace", utt->utt_tree_root, utts->buf_size, utts->buf_nr, 0, &stp_rchan_callbacks); - if (!utt->rchan) { - errk("couldn't create relay channel.\n"); - _stp_remove_relay_root(utt->utt_tree_root); - return NULL; - } + + utt->rchan = relay_open("trace", utt->dir, utts->buf_size, utts->buf_nr, 0, &stp_rchan_callbacks); + if (!utt->rchan) + goto err1; utt->rchan->private_data = utt; utt->trace_state = Utt_trace_setup; utts->err = 0; return utt; + +err1: + errk("couldn't create relay channel.\n"); + _stp_remove_relay_dir(utt->dir); +err: + _stp_remove_relay_root(utt->utt_tree_root); + return NULL; } int utt_trace_startstop(struct utt_trace *utt, int start, @@ -141,6 +152,7 @@ int utt_trace_remove(struct utt_trace *utt) kbug("removing relayfs files. %d\n", utt->trace_state); if (utt && (utt->trace_state == Utt_trace_setup || utt->trace_state == Utt_trace_stopped)) { relay_close(utt->rchan); + _stp_remove_relay_dir(utt->dir); _stp_remove_relay_root(utt->utt_tree_root); kfree(utt); } diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index 9780b0b1..a91a8b70 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -387,7 +387,7 @@ static int _stp_do_module(const char __user *buf, int count) mod = _stp_load_module_symbols(&tmpmod); if (mod == NULL) { kfree(tmpmod.sections); - return -EFAULT; + return 0; } _stp_ins_module(mod); diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index 59402f6f..51586dbd 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -32,9 +32,7 @@ static int _stp_start_finished = 0; static int _stp_probes_started = 0; /* module parameters */ -static int _stp_pid, _stp_bufsize; -module_param(_stp_pid, int, 0); -MODULE_PARM_DESC(_stp_pid, "pid"); +static int _stp_bufsize; module_param(_stp_bufsize, int, 0); MODULE_PARM_DESC(_stp_bufsize, "buffer size"); @@ -208,8 +206,9 @@ void _stp_transport_close() static struct utt_trace *_stp_utt_open(void) { - struct utt_trace_setup utts; - sprintf(utts.root, "systemtap_%d", _stp_pid); + struct utt_trace_setup utts; + strlcpy(utts.root, "systemtap", sizeof(utts.root)); + strlcpy(utts.name, THIS_MODULE->name, sizeof(utts.name)); utts.buf_size = _stp_subbuf_size; utts.buf_nr = _stp_nsubbufs; @@ -230,7 +229,7 @@ int _stp_transport_init(void) { int ret; - kbug("transport_init from %ld %ld\n", (long)_stp_pid, (long)current->pid); + kbug("transport_init\n"); if (_stp_bufsize) { unsigned size = _stp_bufsize * 1024 * 1024; @@ -249,6 +248,7 @@ int _stp_transport_init(void) if (!_stp_utt) goto err0; #endif + /* create debugfs/procfs control channel */ if (_stp_register_ctl_channel() < 0) goto err1; @@ -281,4 +281,100 @@ err0: return -1; } + +static inline void _stp_lock_inode(struct inode *inode) +{ +#ifdef DEFINE_MUTEX + mutex_lock(&inode->i_mutex); +#else + down(&inode->i_sem); +#endif +} + +static inline void _stp_unlock_inode(struct inode *inode) +{ +#ifdef DEFINE_MUTEX + mutex_unlock(&inode->i_mutex); +#else + up(&inode->i_sem); +#endif +} + +static struct dentry *_stp_lockfile = NULL; + +static int _stp_lock_debugfs(void) +{ + int numtries = 0; +#ifdef STP_OLD_TRANSPORT + while ((_stp_lockfile = relayfs_create_dir("systemtap_lock", NULL)) == NULL) { +#else + while ((_stp_lockfile = debugfs_create_dir("systemtap_lock", NULL)) == NULL) { +#endif + if (numtries++ >= 50) + return 0; + msleep(50); + } + return 1; +} + +static void _stp_unlock_debugfs(void) +{ + if (_stp_lockfile) { +#ifdef STP_OLD_TRANSPORT + relayfs_remove_dir(_stp_lockfile); +#else + debugfs_remove(_stp_lockfile); +#endif + _stp_lockfile = NULL; + } +} + +/* _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_get_root_dir(const char *name) { + struct file_system_type *fs; + struct dentry *root; + struct super_block *sb; + +#ifdef STP_OLD_TRANSPORT + fs = get_fs_type("relayfs"); +#else + fs = get_fs_type("debugfs"); +#endif + if (!fs) { + errk("Couldn't find debugfs or relayfs filesystem.\n"); + return NULL; + } + + if (!_stp_lock_debugfs()) { + errk("Couldn't lock transport directory.\n"); + return NULL; + } + +#ifdef STP_OLD_TRANSPORT + root = relayfs_create_dir(name, NULL); +#else + root = 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); + _stp_lock_inode(sb->s_root->d_inode); + root = lookup_one_len(name, sb->s_root, strlen(name)); + _stp_unlock_inode(sb->s_root->d_inode); + kbug("root=%p\n", root); + if (!IS_ERR(root)) + dput(root); + else { + root = NULL; + kbug("Could not create or find transport directory.\n"); + } + } + _stp_unlock_debugfs(); + return root; +} + #endif /* _TRANSPORT_C_ */ diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h index 2d77414c..09a0615e 100644 --- a/runtime/transport/transport.h +++ b/runtime/transport/transport.h @@ -19,4 +19,7 @@ static unsigned _stp_subbuf_size = 65536*2; extern void _stp_transport_close(void); extern int _stp_print_init(void); extern void _stp_print_cleanup(void); +static struct dentry *_stp_get_root_dir(const char *name); +static int _stp_lock_debugfs(void); +static void _stp_unlock_debugfs(void); #endif /* _TRANSPORT_TRANSPORT_H_ */ diff --git a/runtime/transport/utt.c b/runtime/transport/utt.c index b23260d7..0c0dd02c 100644 --- a/runtime/transport/utt.c +++ b/runtime/transport/utt.c @@ -31,25 +31,43 @@ static void utt_remove_root(struct utt_trace *utt) { - if (utt->utt_tree_root && simple_empty(utt->utt_tree_root)) { - debugfs_remove(utt->utt_tree_root); + if (utt->utt_tree_root) { + if (!_stp_lock_debugfs()) { + errk("Unable to lock transport directory.\n"); + return; + } + if (simple_empty(utt->utt_tree_root)) + debugfs_remove(utt->utt_tree_root); + _stp_unlock_debugfs(); utt->utt_tree_root = NULL; } } static void utt_remove_tree(struct utt_trace *utt) { + debugfs_remove(utt->dir); utt_remove_root(utt); } -static struct dentry *utt_create_tree(struct utt_trace *utt, const char *root) +static struct dentry *utt_create_tree(struct utt_trace *utt, const char *root, const char *name) { - if (root == NULL) - return NULL; - - if (!utt->utt_tree_root) - utt->utt_tree_root = debugfs_create_dir(root, NULL); - return utt->utt_tree_root; + struct dentry *dir = NULL; + + if (root == NULL || name == NULL) + return NULL; + + if (!utt->utt_tree_root) { + utt->utt_tree_root = _stp_get_root_dir(root); + 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; } @@ -173,10 +191,10 @@ struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts) goto err; ret = -ENOENT; - dir = utt_create_tree(utt, utts->root); + dir = utt_create_tree(utt, utts->root, utts->name); if (!dir) goto err; - + utt->dir = dir; atomic_set(&utt->dropped, 0); ret = -EIO; diff --git a/runtime/transport/utt.h b/runtime/transport/utt.h index f6eba64b..a89b31f0 100644 --- a/runtime/transport/utt.h +++ b/runtime/transport/utt.h @@ -11,14 +11,15 @@ struct utt_trace { int trace_state; struct rchan *rchan; unsigned long *sequence; + struct dentry *dir; /* systemtap/module_name */ struct dentry *dropped_file; atomic_t dropped; - struct dentry *utt_tree_root; + struct dentry *utt_tree_root; /* systemtap */ void *private_data; }; -#define UTT_TRACE_ROOT_NAME_SIZE 32 /* Largest string for a root dir identifier */ -#define UTT_TRACE_NAME_SIZE 32 /* Largest string for a trace identifier */ +#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 */ /* * User setup structure |