diff options
Diffstat (limited to 'runtime/transport')
-rw-r--r-- | runtime/transport/ChangeLog | 11 | ||||
-rw-r--r-- | runtime/transport/Makefile | 14 | ||||
-rw-r--r-- | runtime/transport/control.c | 228 | ||||
-rw-r--r-- | runtime/transport/control.h | 23 | ||||
-rw-r--r-- | runtime/transport/netlink.c | 167 | ||||
-rw-r--r-- | runtime/transport/netlink.h | 16 | ||||
-rw-r--r-- | runtime/transport/procfs.c | 361 | ||||
-rw-r--r-- | runtime/transport/transport.c | 109 | ||||
-rw-r--r-- | runtime/transport/transport.h | 18 | ||||
-rw-r--r-- | runtime/transport/transport_msgs.h | 5 |
10 files changed, 436 insertions, 516 deletions
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog index 2f4dc6ba..ce011474 100644 --- a/runtime/transport/ChangeLog +++ b/runtime/transport/ChangeLog @@ -1,3 +1,14 @@ +2005-08-19 Martin Hunt <hunt@redhat.com> + + * transport.h: Remove netlink references. + * transport.c: Remove netlink references. Ifdef relayfs code. + * procfs.c: New file. + * Makefile: Deleted. + * control.c: Deleted. + * control.h: Deleted. + * netlink.c: Deleted. + * netlink.h: Deleted. + 2005-08-03 Martin Hunt <hunt@redhat.com> * transport.c: Comment out a couple printks. diff --git a/runtime/transport/Makefile b/runtime/transport/Makefile deleted file mode 100644 index e27569be..00000000 --- a/runtime/transport/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Makes stp-control.ko - -PWD := $(shell pwd) -KDIR := /lib/modules/$(shell uname -r)/build include - -stp-control-objs := control.o netlink.o - -obj-m := stp-control.o - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -clean: - /bin/rm -rf *.o *.ko *~ *.mod.c .*.cmd .tmp_versions diff --git a/runtime/transport/control.c b/runtime/transport/control.c deleted file mode 100644 index 23e99400..00000000 --- a/runtime/transport/control.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * stp-control - stp control channel - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright (C) IBM Corporation, 2005 - * Copyright (C) Redhat Inc, 2005 - * - */ - -/** @file control.c - * @brief Systemtap control channel functions - */ - -/** @addtogroup transport Transport Functions - * @{ - */ - -#include <linux/module.h> -#include <linux/hash.h> -#include "control.h" -#include "netlink.h" - -/* the control channel */ -struct sock *stp_control; - -/* the command handlers hash table */ -static struct hlist_head *handlers; - -/* protection for the handlers table */ -static spinlock_t handlers_lock = SPIN_LOCK_UNLOCKED; - -/** - * _stp_lookup_handler - look up the command handler in the handlers table - * @pid: the pid to find the corresponding handler of - * - * Returns the pointer to the cmd_handler struct, NULL if not - * found. - * - * NOTE: the handlers_lock must be held when calling this function - */ -static struct cmd_handler *_stp_lookup_handler(int pid) -{ - struct hlist_node *node; - struct cmd_handler *handler; - unsigned long key = hash_long((unsigned long)pid, HANDLER_SHIFT); - struct hlist_head *head = &handlers[key]; - - hlist_for_each(node, head) { - handler = hlist_entry(node, struct cmd_handler, hlist); - if (handler->pid == pid) { - return handler; - break; - } - } - - return NULL; -} - -/** - * _stp_handler_find - find the command handler for a given pid - * @pid: the pid to find the corresponding handler of - * - * Returns the pointer to the command handler callback, NULL if - * not found. - */ -static int (*_stp_handler_find(int pid))(int, int, void *) -{ - struct cmd_handler *cmd_handler; - - spin_lock(&handlers_lock); - cmd_handler = _stp_lookup_handler(pid); - spin_unlock(&handlers_lock); - - if (cmd_handler) - return cmd_handler->handler; - - return NULL; -} - -/** - * _stp_ctrl_register - register a command handler for a pid - * @pid: the pid to unregister - * @cmd_handler: the callback function to be called to handle commands - * - * Adds a pid's command handler to the handler table. The - * command handler will be called to handle commands from the - * daemon with the given pid. Should be called at probe module - * initialization before any commands are sent by the daemon. - */ -int _stp_ctrl_register(int pid, - int (*cmd_handler) (int pid, int cmd, void *data)) -{ - unsigned long key = hash_long((unsigned long)pid, HANDLER_SHIFT); - struct hlist_head *head = &handlers[key]; - struct cmd_handler *handler; - - spin_lock(&handlers_lock); - handler = _stp_lookup_handler(pid); - spin_unlock(&handlers_lock); - - if (handler) - return -EBUSY; - - handler = kmalloc(sizeof(struct cmd_handler), GFP_KERNEL); - if (!handler) - return -ENOMEM; - handler->pid = pid; - handler->handler = cmd_handler; - INIT_HLIST_NODE(&handler->hlist); - - spin_lock(&handlers_lock); - hlist_add_head(&handler->hlist, head); - spin_unlock(&handlers_lock); - - return 0; -} - -/** - * _stp_ctrl_unregister - unregister a pid's command handler - * @pid: the pid to unregister - * - * Removes the pid's handler from the handler table. Should be - * called when the daemon is no longer sending commands. - */ -void _stp_ctrl_unregister(int pid) -{ - struct cmd_handler *handler; - - spin_lock(&handlers_lock); - handler = _stp_lookup_handler(pid); - if (handler) { - hlist_del(&handler->hlist); - kfree(handler); - } - spin_unlock(&handlers_lock); -} - -/** - * _stp_ctrl_send - send data over the control channel - * @type: the type of data being sent - * @data: the data - * @len: the data length - * @pid: the pid to send the data to - * - * Returns the result of the transport's send function. - */ -int _stp_ctrl_send(int type, void *data, int len, int pid) -{ - return _stp_netlink_send(type, data, len, pid); -} - -/** - * _stp_ctrl_handler - control channel command dispatcher - * @pid: the pid the command is from - * @cmd: the command - * @data: command-specific data - * - * Returns the result from the pid's command handler, 0 if the - * command was handled, non-zero otherwise. - */ -static int _stp_ctrl_handler(int pid, int cmd, void *data) -{ - int (*cmd_handler) (int, int, void *); - - cmd_handler = _stp_handler_find(pid); - if (!cmd_handler) - return -EINVAL; - - return cmd_handler(pid, cmd, data); -} - -/** - * _stp_ctrl_init - module init function - */ -static int __init _stp_ctrl_init(void) -{ - int i; - - handlers = kmalloc(sizeof(struct hlist_head) * HANDLER_SLOTS, GFP_KERNEL); - if (!handlers) - return -ENOMEM; - - for (i = 0; i < HANDLER_SLOTS; i++) - INIT_HLIST_HEAD(&handlers[i]); - - stp_control = _stp_netlink_open(NETLINK_USERSOCK, _stp_ctrl_handler); - if (!stp_control) { - printk ("stp_ctrl: couldn't open netlink socket\n"); - kfree(handlers); - return -ENOMEM; - } - - return 0; -} - -/** - * _stp_ctrl_exit - module exit function - */ -static void _stp_ctrl_exit(void) -{ - _stp_netlink_close(stp_control); - kfree(handlers); -} - -module_init(_stp_ctrl_init); -module_exit(_stp_ctrl_exit); - -EXPORT_SYMBOL_GPL(_stp_ctrl_register); -EXPORT_SYMBOL_GPL(_stp_ctrl_unregister); -EXPORT_SYMBOL_GPL(_stp_ctrl_send); - -MODULE_DESCRIPTION("SystemTap control channel"); -MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com>"); -MODULE_LICENSE("GPL"); - diff --git a/runtime/transport/control.h b/runtime/transport/control.h deleted file mode 100644 index e19d7bcd..00000000 --- a/runtime/transport/control.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _TRANSPORT_CONTROL_H_ /* -*- linux-c -*- */ -#define _TRANSPORT_CONTROL_H_ - -/** @file control.h - * @brief Header file for transport control channel - */ - -/* command handlers hash table entry struct */ -struct cmd_handler -{ - struct hlist_node hlist; - int pid; - int (*handler) (int pid, int cmd, void *data); -}; - -#define HANDLER_SHIFT 5 -#define HANDLER_SLOTS (1 << HANDLER_SHIFT) - -extern int _stp_ctrl_register(int pid, int (*cmd_handler) (int pid, int cmd, void *data)); -extern void _stp_ctrl_unregister(int pid); -extern int _stp_ctrl_send(int type, void *reply, int len, int pid); - -#endif /* _TRANSPORT_CONTROL_H_ */ diff --git a/runtime/transport/netlink.c b/runtime/transport/netlink.c deleted file mode 100644 index cc6f15e4..00000000 --- a/runtime/transport/netlink.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * netlink.c - stp relayfs-related transport functions - * - * Copyright (C) IBM Corporation, 2005 - * Copyright (C) Redhat Inc, 2005 - * - * This file is released under the GPL. - */ - -/** @file netlink.c - * @brief Systemtap netlink-related transport functions - */ - -/** @addtogroup transport Transport Functions - * @{ - */ - -#include "netlink.h" - -/* the control socket */ -extern struct sock *stp_control; - -/* queued packets logged from irq context */ -static struct sk_buff_head delayed_pkts; - -/* for netlink sequence numbers */ -static int seq; - -/** - * _stp_msg_rcv_skb - dispatch netlink control channel requests - */ -static void _stp_msg_rcv_skb(struct sk_buff *skb, - int (*cmd_handler) (int pid, int cmd, void *data)) -{ - struct nlmsghdr *nlh = NULL; - int pid, flags; - int nlmsglen, skblen; - void *data; - - skblen = skb->len; - - if (skblen < sizeof (*nlh)) - return; - - nlh = (struct nlmsghdr *)skb->data; - nlmsglen = nlh->nlmsg_len; - - if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) - return; - - pid = nlh->nlmsg_pid; - flags = nlh->nlmsg_flags; - - if (pid <= 0 || !(flags & NLM_F_REQUEST)) { - netlink_ack(skb, nlh, -EINVAL); - return; - } - - if (flags & MSG_TRUNC) { - netlink_ack(skb, nlh, -ECOMM); - return; - } - - data = NLMSG_DATA(nlh); - - if (cmd_handler(pid, nlh->nlmsg_type, data)) - netlink_ack(skb, nlh, -EINVAL); - - if (flags & NLM_F_ACK) - netlink_ack(skb, nlh, 0); -} - -/** - * _stp_msg_rcv - handle netlink control channel requests - */ -static void _stp_msg_rcv(struct sock *sk, int len) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->sk_receive_queue))) { - _stp_msg_rcv_skb(skb, sk->sk_user_data); - kfree_skb(skb); - } -} - -/** - * _stp_send_delayed_packets - send delayed netlink packets - */ -static void _stp_send_delayed_pkts(unsigned long ignored) -{ - struct sk_buff *skb; - while ((skb = skb_dequeue(&delayed_pkts)) != NULL) { - struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; - int pid = nlh->nlmsg_pid; - netlink_unicast(stp_control, skb, pid, MSG_DONTWAIT); - } -} -static DECLARE_TASKLET(delayed_pkts_tasklet, _stp_send_delayed_pkts, 0); - -/** - * _stp_netlink_send - send data over netlink channel - * @type: message type - * @data: data to send - * @len: length of data - * @pid: pid to send data to - */ -int _stp_netlink_send(int type, void *data, int len, int pid) -{ - struct sk_buff *skb; - struct nlmsghdr *nlh; - void *d; - int size; - int err = 0; - - size = NLMSG_SPACE(len); - skb = alloc_skb(size, GFP_ATOMIC); - if (!skb) - return -ENOMEM; - - nlh = NLMSG_PUT(skb, pid, seq++, type, size - sizeof(*nlh)); - nlh->nlmsg_flags = 0; - d = NLMSG_DATA(nlh); - memcpy(d, data, len); - - if (in_irq()) { - skb_queue_tail(&delayed_pkts, skb); - tasklet_schedule(&delayed_pkts_tasklet); - } else - err = netlink_unicast(stp_control, skb, pid, MSG_DONTWAIT); - - return err; - -nlmsg_failure: - if (skb) - kfree_skb(skb); - - return -1; -} - -/** - * _stp_netlink_open - create netlink socket - * @unit: the netlink 'unit' to create - * @handler: handler function for stp 'commands' - */ -struct sock *_stp_netlink_open(int unit, - int (*handler) (int pid, int cmd, void *data)) -{ - struct sock *nl = netlink_kernel_create(unit, _stp_msg_rcv); - if (!nl) { - printk("stp-control: couldn't create netlink transport\n"); - return NULL; - } - nl->sk_user_data = handler; - - skb_queue_head_init(&delayed_pkts); - - return nl; -} - -/** - * _stp_netlink_close - close netlink socket - */ -void _stp_netlink_close (struct sock *nl) -{ - BUG_ON(!nl); - sock_release(nl->sk_socket); -} diff --git a/runtime/transport/netlink.h b/runtime/transport/netlink.h deleted file mode 100644 index 5f9514f1..00000000 --- a/runtime/transport/netlink.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _TRANSPORT_NETLINK_H_ /* -*- linux-c -*- */ -#define _TRANSPORT_NETLINK_H_ - -/** @file netlink.h - * @brief Header file for netlink transport - */ - -#include <linux/skbuff.h> -#include <linux/netlink.h> -#include <net/sock.h> - -extern struct sock *_stp_netlink_open(int unit, int (*handler) (int pid, int cmd, void *data)); -extern void _stp_netlink_close(struct sock *nl); -extern int _stp_netlink_send(int type, void *reply, int len, int pid); - -#endif /* _TRANSPORT_NETLINK_H_ */ diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c new file mode 100644 index 00000000..a091a88e --- /dev/null +++ b/runtime/transport/procfs.c @@ -0,0 +1,361 @@ +/* -*- linux-c -*- */ + * + * /proc transport and control + * Copyright (C) 2005 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. + */ + +#define STP_DEFAULT_BUFFERS 128 +static int _stp_current_buffers = STP_DEFAULT_BUFFERS; + +static struct list_head _stp_ready_q; +static struct list_head _stp_pool_q; +spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED; +spinlock_t _stp_ready_lock = SPIN_LOCK_UNLOCKED; + +#ifdef STP_RELAYFS +/* handle the per-cpu subbuf info read for relayfs */ +static ssize_t +_stp_proc_read (struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + int num; + struct buf_info out; + + int cpu = *(int *)(PDE(file->f_dentry->d_inode)->data); + + if (!_stp_chan) + return -EINVAL; + + out.cpu = cpu; + out.produced = atomic_read(&_stp_chan->buf[cpu]->subbufs_produced); + out.consumed = atomic_read(&_stp_chan->buf[cpu]->subbufs_consumed); + + num = sizeof(out); + if (copy_to_user(buf, &out, num)) + return -EFAULT; + + return num; +} + +/* handle the per-cpu subbuf info write for relayfs */ +static ssize_t _stp_proc_write (struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct consumed_info info; + int cpu = *(int *)(PDE(file->f_dentry->d_inode)->data); + if (copy_from_user(&info, buf, count)) + return -EFAULT; + + relay_subbufs_consumed(_stp_chan, cpu, info.consumed); + return count; +} + +static struct file_operations _stp_proc_fops = { + .read = _stp_proc_read, + .write = _stp_proc_write, +}; +#endif + +static ssize_t _stp_proc_write_cmd (struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int type; + + if (count < sizeof(int)) + return 0; + + if (get_user(type, (int __user *)buf)) + return -EFAULT; + + //printk ("_stp_proc_write_cmd. count:%d type:%d\n", count, type); + + count -= sizeof(int); + + switch (type) { + case STP_START: + { + struct transport_start st; + if (count < sizeof(struct transport_start)) + return 0; + if (copy_from_user (&st, buf, sizeof(struct transport_start))) + return -EFAULT; + _stp_handle_start (&st); + break; + } + case STP_EXIT: + _stp_handle_exit(NULL); + break; + case STP_TRANSPORT_INFO: + { + struct transport_info ti; + //printk("STP_TRANSPORT_INFO %d %d\n", count, sizeof(struct transport_info)); + if (count < sizeof(struct transport_info)) + return 0; + if (copy_from_user (&ti, &buf[4], sizeof(struct transport_info))) + return -EFAULT; + _stp_transport_open (&ti); + break; + } + default: + printk ("invalid command type %d\n", type); + return -EINVAL; + } + + return count; +} + +struct _stp_buffer { + struct list_head list; + int len; + char buf[STP_BUFFER_SIZE]; +}; + +static DECLARE_WAIT_QUEUE_HEAD(_stp_proc_wq); + +static int _stp_write (int type, void *data, int len) +{ + struct _stp_buffer *bptr; + + spin_lock(&_stp_pool_lock); + if (list_empty(&_stp_pool_q)) { + spin_unlock(&_stp_pool_lock); + return -1; + } + + /* get the next buffer from the pool */ + bptr = (struct _stp_buffer *)_stp_pool_q.next; + list_del_init(&bptr->list); + spin_unlock(&_stp_pool_lock); + + memcpy (bptr->buf, &type, 4); + memcpy (&bptr->buf[4], data, len); + bptr->len = len; + + + /* put it on the pool of ready buffers */ + spin_lock(&_stp_ready_lock); + list_add_tail(&bptr->list, &_stp_ready_q); + spin_unlock(&_stp_ready_lock); + + /* now wake up readers */ + wake_up_interruptible(&_stp_proc_wq); + + return len; +} + + +static ssize_t +_stp_proc_read_cmd (struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct _stp_buffer *bptr; + int len; + + /* wait for nonempty ready queue */ + spin_lock(&_stp_ready_lock); + while (list_empty(&_stp_ready_q)) { + spin_unlock(&_stp_ready_lock); + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(_stp_proc_wq, !list_empty(&_stp_ready_q))) + return -ERESTARTSYS; + spin_lock(&_stp_ready_lock); + } + + /* get the next buffer off the ready list */ + bptr = (struct _stp_buffer *)_stp_ready_q.next; + list_del_init(&bptr->list); + spin_unlock(&_stp_ready_lock); + + /* write it out */ + len = bptr->len + 4; + if (copy_to_user(buf, bptr->buf, len)) { + /* now what? We took it off the queue then failed to send it */ + /* we can't put it back on the queue because it will likely be out-of-order */ + /* fortunately this should never happen */ + /* FIXME need to mark this as a transport failure */ + return -EFAULT; + } + + /* put it on the pool of free buffers */ + spin_lock(&_stp_pool_lock); + list_add_tail(&bptr->list, &_stp_pool_q); + spin_unlock(&_stp_pool_lock); + + return len; +} + + + +static struct file_operations _stp_proc_fops_cmd = { + .read = _stp_proc_read_cmd, + .write = _stp_proc_write_cmd, +// .poll = _stp_proc_poll_cmd +}; + +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) +{ + if (de->namelen != len) + return 0; + return !memcmp(name, de->name, len); +} + +/* set the number of buffers to use to 'num' */ +static int _stp_set_buffers(int num) +{ + int i; + struct list_head *p; + + printk("stp_set_buffers %d\n", num); + + if (num == 0 || num == _stp_current_buffers) + return _stp_current_buffers;; + + spin_lock(&_stp_pool_lock); + if (num > _stp_current_buffers) { + for (i = 0; i < num - _stp_current_buffers; i++) { + p = (struct list_head *)vmalloc(sizeof(struct _stp_buffer)); + if (!p) { + _stp_current_buffers += i; + goto err; + } + list_add (p, &_stp_pool_q); + } + } else { + for (i = 0; i < _stp_current_buffers - num; i++) { + p = _stp_pool_q.next; + list_del(p); + vfree(p); + } + } + _stp_current_buffers = num; +err: + spin_unlock(&_stp_pool_lock); + return _stp_current_buffers; +} + +static int _stp_register_procfs (void) +{ + int i, j; + const char *dirname = "systemtap"; + char buf[8]; + struct proc_dir_entry *de; + struct list_head *p, *tmp; + + INIT_LIST_HEAD(&_stp_ready_q); + INIT_LIST_HEAD(&_stp_pool_q); + + /* allocate buffers */ + for (i = 0; i < STP_DEFAULT_BUFFERS; i++) { + p = (struct list_head *)vmalloc(sizeof(struct _stp_buffer)); + // printk("allocated buffer at %lx\n", (long)p); + if (!p) + goto err2; + list_add (p, &_stp_pool_q); + } + + + /* 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) + goto err0; + } + + /* 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_RELAYFS + /* 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_mod); + if (de == NULL) + goto err1; + de->proc_fops = &_stp_proc_fops; + de->data = kmalloc(sizeof(int), GFP_KERNEL); + if (de->data == NULL) { + remove_proc_entry (buf, _stp_proc_mod); + goto err1; + } + *(int *)de->data = i; + } +#endif + + /* 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; + return 0; + +err2: + list_for_each_safe(p, tmp, &_stp_pool_q) { + list_del(p); + vfree(p); + } + +err1: +#ifdef STP_RELAYFS + 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_mod); + + } +#endif + remove_proc_entry (THIS_MODULE->name, _stp_proc_root); +err0: + printk (KERN_ERR "Error creating systemtap /proc entries.\n"); + return -1; +} + + +static void _stp_unregister_procfs (void) +{ + int i; + char buf[8]; + struct list_head *p, *tmp; + struct proc_dir_entry *de; +#ifdef STP_RELAYFS + 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_mod); + } +#endif + 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) { + list_del(p); + vfree(p); + } + list_for_each_safe(p, tmp, &_stp_ready_q) { + list_del(p); + vfree(p); + } +} + diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index a0c1122e..b2df885c 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -12,19 +12,13 @@ #include <linux/delay.h> #include "transport.h" -#include "control.h" -#include "relayfs.c" - -enum _stp_tstate { STP_TRANS_NONE, - STP_TRANS_LOADED, /* module loaded */ - STP_TRANS_PARAM, /* parameters exchanged */ - STP_TRANS_START /* started */ -}; - -enum _stp_tstate _stp_transport_state = STP_TRANS_NONE; +#ifdef STP_RELAYFS +#include "relayfs.c" static struct rchan *_stp_chan; static struct dentry *_stp_dir; +#endif + static int _stp_dpid; static int _stp_pid; @@ -32,18 +26,24 @@ module_param(_stp_pid, int, 0); MODULE_PARM_DESC(_stp_pid, "daemon pid"); int _stp_target = 0; +int _stp_exit_called = 0; /* forward declarations */ void probe_exit(void); int probe_start(void); void _stp_exit(void); +void _stp_handle_start (struct transport_start *st); +static void _stp_handle_exit (void *data); +int _stp_transport_open(struct transport_info *info); + +#include "procfs.c" /* * _stp_streaming - boolean, are we using 'streaming' output? */ static inline int _stp_streaming(void) { - if (_stp_transport_mode == STP_TRANSPORT_NETLINK) + if (_stp_transport_mode == STP_TRANSPORT_PROC) return 1; return 0; } @@ -52,7 +52,7 @@ static inline int _stp_streaming(void) int _stp_transport_send (int type, void *data, int len) { int err, trylimit = 50; - while ((err = _stp_ctrl_send(type, data, len, _stp_pid)) < 0 && trylimit--) + while ((err = _stp_write(type, data, len)) < 0 && trylimit--) msleep (5); return err; } @@ -61,6 +61,7 @@ int _stp_transport_send (int type, void *data, int len) /* * _stp_handle_buf_info - handle STP_BUF_INFO */ +#ifdef STP_RELAYFS static void _stp_handle_buf_info(int *cpuptr) { struct buf_info out; @@ -70,6 +71,7 @@ static void _stp_handle_buf_info(int *cpuptr) _stp_transport_send(STP_BUF_INFO, &out, sizeof(out)); } +#endif /* * _stp_handle_start - handle STP_START @@ -79,14 +81,14 @@ void _stp_handle_start (struct transport_start *st) int err; //printk ("stp_handle_start pid=%d\n", st->pid); err = probe_start(); - if (err >= 0) - _stp_transport_state = STP_TRANS_START; - else { + if (err < 0) { st->pid = err; + _stp_exit_called = 1; _stp_transport_send(STP_START, st, sizeof(*st)); } } +#ifdef STP_RELAYFS /** * _stp_handle_subbufs_consumed - handle STP_SUBBUFS_CONSUMED */ @@ -94,14 +96,13 @@ static void _stp_handle_subbufs_consumed(int pid, struct consumed_info *info) { relay_subbufs_consumed(_stp_chan, info->cpu, info->consumed); } - - -int _stp_exit_called = 0; +#endif static void _stp_cleanup_and_exit (int closing) { int failures; + //printk("cleanup_and_exit (%d)\n", closing); if (!_stp_exit_called) { _stp_exit_called = 1; @@ -111,10 +112,15 @@ static void _stp_cleanup_and_exit (int closing) if (failures) _stp_warn ("There were %d transport failures.\n", failures); - if (_stp_transport_mode == STP_TRANSPORT_RELAYFS) +#ifdef STP_RELAYFS + if (_stp_transport_mode == STP_TRANSPORT_RELAYFS) { relay_flush(_stp_chan); - - _stp_transport_send(STP_EXIT, &closing, sizeof(int)); + ssleep(2); + } +#endif + + //printk ("SENDING STP_EXIT\n"); + _stp_transport_send(STP_EXIT, &closing, sizeof(int)); } } @@ -129,9 +135,8 @@ static void _stp_handle_exit (void *data) _stp_cleanup_and_exit(0); } - /** - * _stp_transport_close - close netlink and relayfs channels + * _stp_transport_close - close proc and relayfs channels * * This must be called after all I/O is done, probably at the end * of module cleanup. @@ -141,17 +146,18 @@ void _stp_transport_close() //printk("************** transport_close *************\n"); _stp_cleanup_and_exit(1); +#ifdef STP_RELAYFS if (_stp_transport_mode == STP_TRANSPORT_RELAYFS) _stp_relayfs_close(_stp_chan, _stp_dir); +#endif - _stp_ctrl_unregister(_stp_pid); + ssleep(1); + _stp_unregister_procfs(); //printk("---- CLOSED ----\n"); } - - /** - * _stp_transport_open - open netlink and relayfs channels + * _stp_transport_open - open proc and relayfs channels * with proper parameters * Returns negative on failure, 0 otherwise. * @@ -167,32 +173,37 @@ void _stp_transport_close() int _stp_transport_open(struct transport_info *info) { - //printk ("stp_transport_open: %d bufs of %d bytes. target=%d\n", info->n_subbufs, info->subbuf_size, info->target); + //printk ("stp_transport_open: %d byte buffer. target=%d\n", info->buf_size, info->target); info->transport_mode = _stp_transport_mode; + //printk("transport_mode=%d\n", info->transport_mode); _stp_target = info->target; +#ifdef STP_RELAYFS if (!_stp_streaming()) { - - /* if stpd specified subbufs, use those, otherwise use defaults */ - if (info->n_subbufs) { - n_subbufs = info->n_subbufs; - subbuf_size = info->subbuf_size; - } else { - info->n_subbufs = n_subbufs; - info->subbuf_size = subbuf_size; + if (info->buf_size) { + unsigned size = info->buf_size * 1024 * 1024; + subbuf_size = ((size >> 2) + 1) * 65536; + n_subbufs = size / subbuf_size; } + info->n_subbufs = n_subbufs; + info->subbuf_size = subbuf_size; _stp_chan = _stp_relayfs_open(n_subbufs, subbuf_size, _stp_pid, &_stp_dir); if (!_stp_chan) { - _stp_ctrl_unregister(_stp_pid); + _stp_unregister_procfs(); return -ENOMEM; } + } else +#endif + { + if (info->buf_size) + _stp_set_buffers(info->buf_size * 1024 * 1024 / STP_BUFFER_SIZE); } /* send reply */ return _stp_transport_send (STP_TRANSPORT_INFO, info, sizeof(*info)); -} + } /** @@ -209,12 +220,14 @@ static int _stp_cmd_handler(int pid, int cmd, void *data) int err = 0; switch (cmd) { +#ifdef STP_RELAYFS case STP_BUF_INFO: _stp_handle_buf_info(data); break; case STP_SUBBUFS_CONSUMED: _stp_handle_subbufs_consumed(pid, data); break; +#endif case STP_EXIT: _stp_handle_exit (data); break; @@ -240,29 +253,14 @@ int _stp_transport_init(void) { //printk("transport_init from %ld %ld\n", (long)_stp_pid, (long)current->pid); - _stp_ctrl_register(_stp_pid, _stp_cmd_handler); - - /* register procfs here */ - + _stp_register_procfs(); return 0; } -/* write DATA via netlink. used for streaming mode only */ -int _stp_netlink_write (void *data, int len) -{ - int err, trylimit; - if (_stp_exit_called) - trylimit = 50; - else - trylimit = 0; - - while ((err = _stp_ctrl_send(STP_REALTIME_DATA, data, len, _stp_pid)) < 0 && trylimit--) - msleep (5); - return err; -} /* like relay_write except returns an error code */ +#ifdef STP_RELAYFS static int _stp_relay_write (const void *data, unsigned length) { unsigned long flags; @@ -284,5 +282,6 @@ static int _stp_relay_write (const void *data, unsigned length) return length; } +#endif #endif /* _TRANSPORT_C_ */ diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h index 68eb4945..161eefa6 100644 --- a/runtime/transport/transport.h +++ b/runtime/transport/transport.h @@ -5,27 +5,21 @@ * @brief Header file for stp transport */ -#include "control.h" -#include "netlink.h" #include "relayfs.h" #include "transport_msgs.h" void _stp_warn (const char *fmt, ...); +#define STP_BUFFER_SIZE 8192 + +#ifdef STP_RELAYFS static unsigned n_subbufs = 4; static unsigned subbuf_size = 65536; - - -#ifdef STP_NETLINK_ONLY -static int _stp_transport_mode = STP_TRANSPORT_NETLINK; -#else +#define _stp_transport_write(data, len) _stp_relay_write(data, len) static int _stp_transport_mode = STP_TRANSPORT_RELAYFS; -#endif - -#ifdef STP_NETLINK_ONLY -#define _stp_transport_write(data, len) _stp_netlink_write(data, len) #else -#define _stp_transport_write(data, len) _stp_relay_write(data, len) +#define _stp_transport_write(data, len) _stp_write(STP_REALTIME_DATA, data, len) +static int _stp_transport_mode = STP_TRANSPORT_PROC; #endif extern void _stp_transport_cleanup(void); diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h index 11532b27..5f525706 100644 --- a/runtime/transport/transport_msgs.h +++ b/runtime/transport/transport_msgs.h @@ -1,7 +1,7 @@ /* SystemTap transport values */ enum { - STP_TRANSPORT_NETLINK = 1, + STP_TRANSPORT_PROC = 1, STP_TRANSPORT_RELAYFS }; @@ -32,11 +32,14 @@ struct consumed_info struct transport_info { + unsigned buf_size; unsigned subbuf_size; unsigned n_subbufs; int transport_mode; int target; // target pid +#if 0 char cmd[256]; // cmd to process data +#endif }; struct transport_start |