summaryrefslogtreecommitdiffstats
path: root/runtime/transport
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/transport')
-rw-r--r--runtime/transport/ChangeLog11
-rw-r--r--runtime/transport/Makefile14
-rw-r--r--runtime/transport/control.c228
-rw-r--r--runtime/transport/control.h23
-rw-r--r--runtime/transport/netlink.c167
-rw-r--r--runtime/transport/netlink.h16
-rw-r--r--runtime/transport/procfs.c361
-rw-r--r--runtime/transport/transport.c109
-rw-r--r--runtime/transport/transport.h18
-rw-r--r--runtime/transport/transport_msgs.h5
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