]> sourceware.org Git - systemtap.git/commitdiff
initial revision
authortrz <trz>
Fri, 6 May 2005 19:16:07 +0000 (19:16 +0000)
committertrz <trz>
Fri, 6 May 2005 19:16:07 +0000 (19:16 +0000)
runtime/transport/Makefile [new file with mode: 0644]
runtime/transport/control.c [new file with mode: 0644]
runtime/transport/control.h [new file with mode: 0644]
runtime/transport/netlink.c [new file with mode: 0644]
runtime/transport/netlink.h [new file with mode: 0644]
runtime/transport/relayfs.c [new file with mode: 0644]
runtime/transport/relayfs.h [new file with mode: 0644]
runtime/transport/transport.c [new file with mode: 0644]
runtime/transport/transport.h [new file with mode: 0644]

diff --git a/runtime/transport/Makefile b/runtime/transport/Makefile
new file mode 100644 (file)
index 0000000..37268a2
--- /dev/null
@@ -0,0 +1,14 @@
+# Makes stp-control.ko
+
+PWD     := $(shell pwd)
+KDIR   := /usr/local/src/linux-$(shell uname -r)
+
+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
new file mode 100644 (file)
index 0000000..1699f54
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ *  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 DEFINE_SPINLOCK(handlers_lock);
+
+/**
+ *     _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
new file mode 100644 (file)
index 0000000..a614ecb
--- /dev/null
@@ -0,0 +1,32 @@
+#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)
+
+/* stp control channel command values */
+enum
+{
+       STP_BUF_INFO = 1,
+       STP_SUBBUFS_CONSUMED,
+        STP_REALTIME_DATA,
+        STP_EXIT,
+};
+
+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
new file mode 100644 (file)
index 0000000..bfb9d22
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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;
+
+       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
new file mode 100644 (file)
index 0000000..5f9514f
--- /dev/null
@@ -0,0 +1,16 @@
+#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/relayfs.c b/runtime/transport/relayfs.c
new file mode 100644 (file)
index 0000000..181a130
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef _TRANSPORT_RELAYFS_C_ /* -*- linux-c -*- */
+#define _TRANSPORT_RELAYFS_C_
+
+/*
+ * relayfs.c - stp relayfs-related transport functions
+ *
+ * Copyright (C) IBM Corporation, 2005
+ * Copyright (C) Redhat Inc, 2005
+ *
+ * This file is released under the GPL.
+ */
+
+/** @file relayfs.c
+ * @brief Systemtap relayfs-related transport functions
+ */
+
+/** @addtogroup transport Transport Functions
+ * @{
+ */
+
+#include "relayfs.h"
+
+/**
+ *     _stp_subbuf_start - subbuf_start() relayfs callback implementation
+ */
+static int _stp_subbuf_start(struct rchan_buf *buf,
+                            void *subbuf,
+                            unsigned prev_subbuf_idx,
+                            void *prev_subbuf)
+{
+       unsigned padding = buf->padding[prev_subbuf_idx];
+       if (prev_subbuf)
+               *((unsigned *)prev_subbuf) = padding;
+
+       return sizeof(padding); /* reserve space for padding */
+}
+
+/**
+ *     _stp_buf_full - buf_full() relayfs callback implementation
+ */
+static void _stp_buf_full(struct rchan_buf *buf,
+                         unsigned subbuf_idx,
+                         void *subbuf)
+{
+       unsigned padding = buf->padding[subbuf_idx];
+       *((unsigned *)subbuf) = padding;
+}
+
+/* relayfs callback functions */
+static struct rchan_callbacks stp_rchan_callbacks =
+{
+       .subbuf_start = _stp_subbuf_start,
+       .buf_full = _stp_buf_full,
+};
+
+/**
+ *     _stp_relayfs_close - destroys relayfs channel
+ *     @chan: the relayfs channel
+ *     @dir: the directory containing the relayfs files
+ */
+void _stp_relayfs_close(struct rchan *chan, struct dentry *dir)
+{
+       if (!chan)
+               return;
+
+       relay_close(chan);
+       if (dir)
+               relayfs_remove_dir(dir);
+}
+
+/**
+ *     _stp_relayfs_open - create relayfs channel
+ *     @n_subbufs: number of relayfs sub-buffers
+ *     @subbuf_size: size of relayfs sub-buffers
+ *     @pid: daemon pid
+ *     @outdir: receives directory dentry
+ *
+ *     Returns relay channel, NULL on failure
+ *
+ *     Creates relayfs files as /systemtap/pid/cpuX in relayfs root
+ */
+struct rchan *_stp_relayfs_open(unsigned n_subbufs,
+                               unsigned subbuf_size,
+                               int pid,
+                               struct dentry **outdir)
+{
+       char dirname[16];
+       struct rchan *chan;
+       struct dentry* dir = NULL;
+
+       sprintf(dirname, "%d", pid);
+       
+       /* TODO: need to create systemtap dir */
+       dir = relayfs_create_dir(dirname, NULL);
+       if (!dir) {
+               printk("STP: couldn't create relayfs dir %s.\n", dirname);
+               return NULL;
+       }
+
+       chan = relay_open("cpu", dir, subbuf_size,
+                         n_subbufs, 0, &stp_rchan_callbacks);
+       if (!chan) {
+               printk("STP: couldn't create relayfs channel.\n");
+               if (dir)
+                       relayfs_remove_dir(dir);
+       }
+
+       *outdir = dir;
+       return chan;
+}
+
+#endif /* _TRANSPORT_RELAYFS_C_ */
+
diff --git a/runtime/transport/relayfs.h b/runtime/transport/relayfs.h
new file mode 100644 (file)
index 0000000..2f30138
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _TRANSPORT_RELAYFS_H_ /* -*- linux-c -*- */
+#define _TRANSPORT_RELAYFS_H_
+
+/** @file relayfs.h
+ * @brief Header file for relayfs transport
+ */
+
+#include <linux/relayfs_fs.h>
+
+struct rchan *_stp_relayfs_open(unsigned n_subbufs,
+                               unsigned subbuf_size,
+                               int pid,
+                               struct dentry **outdir);
+void _stp_relayfs_close(struct rchan *chan, struct dentry *dir);
+
+#endif /* _TRANSPORT_RELAYFS_H_ */
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
new file mode 100644 (file)
index 0000000..080469a
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef _TRANSPORT_TRANSPORT_C_ /* -*- linux-c -*- */
+#define _TRANSPORT_TRANSPORT_C_
+
+/*
+ * transport.c - stp transport functions
+ *
+ * Copyright (C) IBM Corporation, 2005
+ * Copyright (C) Redhat Inc, 2005
+ *
+ * This file is released under the GPL.
+ */
+
+/** @file transport.c
+ * @brief Systemtap transport functions
+ */
+
+/** @addtogroup transport Transport Functions
+ * @{
+ */
+
+#include <linux/delay.h>
+#include "transport.h"
+#include "control.h"
+#include "relayfs.c"
+
+/** @file transport.c
+ * @brief transport functions
+ */
+/** @addtogroup io transport
+ * transport functions
+ * @{
+ */
+
+/* transport-related data for this probe */
+struct stp_transport *t;
+
+/* forward declaration of probe-defined exit function */
+static void probe_exit(void);
+
+/**
+ *     _stp_handle_buf_info - handle relayfs buffer info command
+ */
+static void _stp_handle_buf_info(int pid, struct buf_info *in)
+{
+       struct buf_info out;
+       BUG_ON(!(t && t->chan));
+
+       out.cpu = in->cpu;
+       out.produced = atomic_read(&t->chan->buf[in->cpu]->subbufs_produced);
+       out.consumed = atomic_read(&t->chan->buf[in->cpu]->subbufs_consumed);
+
+       _stp_ctrl_send(STP_BUF_INFO, &out, sizeof(out), pid);
+}
+
+/**
+ *     _stp_handle_subbufs_consumed - handle relayfs subbufs consumed command
+ */
+static void _stp_handle_subbufs_consumed(int pid, struct consumed_info *info)
+{
+       BUG_ON(!(t && t->chan));
+       relay_subbufs_consumed(t->chan, info->cpu, info->consumed);
+}
+
+/**
+ *     _stp_handle_exit - handle exit command
+ */
+static void _stp_handle_exit(int pid)
+{
+       BUG_ON(!t);
+       probe_exit();
+       _stp_transport_flush();
+       _stp_ctrl_send(STP_EXIT, __this_module.name,
+                      strlen(__this_module.name) + 1, pid);
+}
+
+/**
+ *     _stp_cmd_handler - control channel command handler callback
+ *     @pid: the pid of the daemon the command was sent from
+ *     @cmd: the command id
+ *     @data: command-specific data
+ *
+ *     This function must return 0 if the command was handled, nonzero
+ *     otherwise.
+ */
+static int _stp_cmd_handler(int pid, int cmd, void *data)
+{
+       int err = 0;
+
+       switch (cmd) {
+       case STP_BUF_INFO:
+               _stp_handle_buf_info(pid, data);
+               break;
+       case STP_SUBBUFS_CONSUMED:
+               _stp_handle_subbufs_consumed(pid, data);
+               break;
+       case STP_EXIT:
+               _stp_handle_exit(pid);
+               break;
+       default:
+               err = -1;
+               break;
+       }
+       
+       return err;
+}
+
+/**
+ *     _stp_transport_close - close netlink and relayfs channels
+ *
+ *     This must be called after all I/O is done, probably at the end
+ *     of module cleanup.
+ */
+void _stp_transport_close()
+{
+       if (!t)
+               return;
+
+       _stp_ctrl_unregister(t->pid);
+       if (!_stp_streaming())
+               _stp_relayfs_close(t->chan, t->dir);
+
+       /* in case the module has been manually removed */
+       _stp_ctrl_send(STP_EXIT, __this_module.name,
+                      strlen(__this_module.name) + 1, t->pid);
+       kfree(t);
+}
+
+/**
+ *     _stp_transport_open - open netlink and relayfs channels
+ *     @n_subbufs: number of relayfs sub-buffers
+ *     @subbuf_size: size of relayfs sub-buffers
+ *     @pid: daemon pid
+ *
+ *     Returns negative on failure, 0 otherwise.
+ *
+ *     This function registers the probe with the control channel,
+ *     and if the probe output will not be 'streaming', creates a
+ *     relayfs channel for it.  This must be called before any I/O is
+ *     done, probably at the start of module initialization.
+ */
+int _stp_transport_open(unsigned n_subbufs, unsigned subbuf_size, int pid)
+{
+       BUG_ON(!(n_subbufs && subbuf_size));
+       
+       t = kcalloc(1, sizeof(struct stp_transport), GFP_KERNEL);
+       if (!t)
+               return -ENOMEM;
+
+       t->pid = pid;
+       _stp_ctrl_register(t->pid, _stp_cmd_handler);
+
+       if (_stp_streaming())
+               return 0;
+
+       t->chan = _stp_relayfs_open(n_subbufs, subbuf_size, t->pid, &t->dir);
+       if (!t->chan) {
+               _stp_ctrl_unregister(t->pid);
+               kfree(t);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/** @} */
+#endif /* _TRANSPORT_C_ */
diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h
new file mode 100644 (file)
index 0000000..6e0550b
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _TRANSPORT_TRANSPORT_H_ /* -*- linux-c -*- */
+#define _TRANSPORT_TRANSPORT_H_
+
+/** @file transport.h
+ * @brief Header file for stp transport
+ */
+
+#include "control.h"
+#include "netlink.h"
+#include "relayfs.h"
+
+/* transport data structure */
+struct stp_transport
+{
+       struct rchan *chan;
+       struct dentry *dir;
+       int pid;
+};
+
+/* control channel command structs */
+struct buf_info
+{
+       int cpu;
+       unsigned produced;
+       unsigned consumed;
+};
+
+struct consumed_info
+{
+       int cpu;
+       unsigned consumed;
+};
+
+/**
+ *     _stp_transport_write - write data to the transport
+ *     @t: the transport struct
+ *     @data: the data to send
+ *     @len: length of the data to send
+ */
+#ifdef STP_NETLINK_ONLY
+#define _stp_transport_write(t, data, len) \
+       _stp_ctrl_send(STP_REALTIME_DATA, data, len, t->pid)
+#else
+#define _stp_transport_write(t, data, len) \
+       relay_write(t->chan, data, len)
+#endif
+
+/**
+ *     _stp_streaming - boolean, are we using 'streaming' output?
+ */
+#ifdef STP_NETLINK_ONLY
+#define _stp_streaming()       (1)
+#else
+#define _stp_streaming()       (0)
+#endif
+
+/**
+ *     _stp_transport_flush - flush the transport, if applicable
+ */
+static inline void _stp_transport_flush(void)
+{
+#ifndef STP_NETLINK_ONLY
+       extern struct stp_transport *t;
+
+       BUG_ON(!t->chan);
+       relay_flush(t->chan);
+       ssleep(1); /* FIXME: time for data to be flushed */
+#endif
+}
+
+extern int _stp_transport_open(unsigned n_subbufs, unsigned subbuf_size,
+                              int pid);
+extern void _stp_transport_close(void);
+
+#endif /* _TRANSPORT_TRANSPORT_H_ */
This page took 0.042287 seconds and 5 git commands to generate.