From 655ee2825121e149a9976e562946892efb20aea1 Mon Sep 17 00:00:00 2001 From: hunt Date: Thu, 7 Apr 2005 21:48:47 +0000 Subject: *** empty log message *** --- runtime/docs/html/relay-app_8h-source.html | 542 +++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 runtime/docs/html/relay-app_8h-source.html (limited to 'runtime/docs/html/relay-app_8h-source.html') diff --git a/runtime/docs/html/relay-app_8h-source.html b/runtime/docs/html/relay-app_8h-source.html new file mode 100644 index 00000000..16feefe0 --- /dev/null +++ b/runtime/docs/html/relay-app_8h-source.html @@ -0,0 +1,542 @@ + + +SystemTap: relay-app.h Source File + + + +
Main Page | Modules | Directories | File List | Globals | Related Pages
+

relay-app.h

00001 /*
+00002  *  relay-app.h - kernel 'library' functions for typical relayfs applications
+00003  *
+00004  * This program is free software; you can redistribute it and/or modify
+00005  * it under the terms of the GNU General Public License as published by
+00006  * the Free Software Foundation; either version 2 of the License, or
+00007  * (at your option) any later version.
+00008  *
+00009  * This program is distributed in the hope that it will be useful,
+00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+00012  * GNU General Public License for more details.
+00013  *
+00014  * You should have received a copy of the GNU General Public License
+00015  * along with this program; if not, write to the Free Software
+00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+00017  *
+00018  * Copyright (C) IBM Corporation, 2005
+00019  *
+00020  * 2005-Feb     Created by Tom Zanussi <zanussi@us.ibm.com>
+00021  *
+00022  * This header file encapsulates the details of channel setup and
+00023  * teardown and communication between the kernel and user parts of a
+00024  * typical and common type of relayfs application, which is that
+00025  * kernel logging is kicked off when a userspace data collection
+00026  * application starts and stopped when the collection app exits, and
+00027  * data is automatically logged to disk in-between.  Channels are
+00028  * created when the collection app is started and destroyed when it
+00029  * exits, not when the kernel module is inserted, so different channel
+00030  * buffer sizes can be specified for each separate run via
+00031  * command-line options for instance.
+00032  *
+00033  * Writing to the channel is done using 2 macros, relayapp_write() and
+00034  * _relayapp_write(), which are just wrappers around relay_write() and
+00035  * _relay_write() but without the channel param.  You can safely call
+00036  * these at any time - if there's no channel yet, they'll just be
+00037  * ignored.
+00038  *
+00039  * To create a relay-app application, do the following:
+00040  *
+00041  * In your kernel module:
+00042  *
+00043  * - #include "relay-app.h"
+00044  *
+00045  * - Call init_relay_app() in your module_init function, with the
+00046  *   names of the directory to create relayfs files in and the base name
+00047  *   of the per-cpu relayfs files e.g. to have /mnt/relay/myapp/cpuXXX
+00048  *   created call init_relay_app("myapp", "cpu", callbacks).
+00049  *
+00050  *   NOTE: The callbacks are entirely optional - pass NULL if you
+00051  *   don't want to define any.  If you want to define some but not
+00052  *   others, just set the ones you want, and ignore or NULL out the
+00053  *   others.
+00054  *
+00055  *   NOTE: This won't actually create the relayfs files - that will
+00056  *   happen when the userspace application starts (i.e. you can supply
+00057  *   the buffer sizes on the application command-line for each new run
+00058  *   of your program).
+00059  *
+00060  *   NOTE: If you pass in NULL for the directory name, the relay files
+00061  *   will be created in the root directory of the relayfs filesystem.
+00062  *
+00063  * - Call close_relay_app() in your module_exit function - this cleans
+00064  *   up the control channel and the relay files from the previous run,
+00065  *   if any.
+00066  *
+00067  * - relay-apps use a control channel to communicate initialization
+00068  *   and status information between the kernel module and user space
+00069  *   program.  This is hidden beneath the API so you normally don't need
+00070  *   to know anything about it, but if you want you can also use it to
+00071  *   send user-defined commands from your user space application.  To do
+00072  *   this, you need to define a definition for the user_command()
+00073  *   callback and in the callback sort out and handle handle the
+00074  *   commands you send from user space (via send_request()).  The
+00075  *   callback must return 1 if the command was handled, or 0 if not
+00076  *   (which will result in a send_error in the user space program,
+00077  *   alerting you to the fact that you're sending something bogus).
+00078  *
+00079  *   NOTE: Currently commands can only be sent before the user space
+00080  *   application enters relay_app_main_loop() i.e. for initialization
+00081  *   purposes only.
+00082  *
+00083  * - the app_started() and app_stopped() callbacks provide an
+00084  *   opportunity for your kernel module to perform app-specific
+00085  *   initialization and cleanup, if desired.  They are purely
+00086  *   informational.  app_started() is called when the user space
+00087  *   application has started and app_stopped() is called when the user
+00088  *   space application has stopped.
+00089  *
+00090  * In your user space application do the following:
+00091  *
+00092  * - Call init_relay_app() with the names of the relayfs file base
+00093  *   name and the base filename of the output files that will be
+00094  *   created, as well as the sub-buffer size and count for the current
+00095  *   run (which can be passed in on the command-line if you want).  This
+00096  *   will create the channel and set up the ouptut files and buffer
+00097  *   mappings.  e.g. to set up reading from the relayfs files specified in the
+00098  *   above example and write them to a set of per-cpu output files named
+00099  *   myoutputXXX:
+00100  * 
+00101  *   init_relay_app("/mnt/relay/myapp/cpu", "myoutput",
+00102  *                  subbuf_size_opt, n_subbufs_opt, 1);
+00103  *
+00104  *   (the last parameter just specifies whether or not to print out a
+00105  *   summary of the number of buffers processed, and the maximum backlog
+00106  *   of sub-buffers encountered e.g. if you have 4 sub-buffers, a
+00107  *   maximum backlog of 3 would mean that you came close to having a
+00108  *   full buffer, so you might want to use more or bigger sub-buffers
+00109  *   next time.  Of course, if the buffers actually filled up, the
+00110  *   maximum backlog would be 4 and you'd have lost data).
+00111  *
+00112  * - Call relay_app_main_loop().  This will set up an infinite loop
+00113  *   (press Control-C to break out and finalize the data) which
+00114  *   automatically reads the data from the relayfs buffers as it becomes
+00115  *   available and and writes it out to per-cpu output files.
+00116  *
+00117  *   NOTE: The control channel is implemented as a netlink socket.
+00118  *   relay-app defaults to using NETLINK_USERSOCK for all
+00119  *   applications, which means that you can't have more than 1
+00120  *   relay-app in use at a time, unless you use different netlink
+00121  *   'units' for each one.  If you want to have more than one
+00122  *   relay-app in use at a time, you can specify a different netlink
+00123  *   'unit' by using the _init_relay_app() versions of the
+00124  *   init_relay_app() functions, on both the kernel and user sides,
+00125  *   which are the same as the init_relay_app() functions but add a
+00126  *   netlink unit param.  See netlink.h for the currently unused
+00127  *   numbers.
+00128  */
+00129 
+00130 #include <linux/inet.h>
+00131 #include <linux/ip.h>
+00132 #include <linux/netlink.h>
+00133 #include <linux/relayfs_fs.h>
+00134 
+00135 /* relay-app pseudo-API */
+00136 
+00137 /*
+00138  * relay-app callbacks
+00139  */
+00140 struct relay_app_callbacks
+00141 {
+00142         /*
+00143          *      user_command - app-specific command callback
+00144          *      @command: user-defined command id
+00145          *      @data: user-defined data associated with the command
+00146          *
+00147          *      Return value: 1 if this callback handled it, 0 if not
+00148          *
+00149          *      define this callback to handle user-defined commands sent
+00150          *      from the user space application via send_request()
+00151          *
+00152          *      NOTE: user commands must be >= RELAY_APP_USERCMD_START
+00153          */
+00154         int (*user_command) (int command, void *data);
+00155 
+00156         /*
+00157          *      app_started - the user-space application has started
+00158          *
+00159          *      Do app-specific initializations now, if desired
+00160          */
+00161         void (*app_started) (void);
+00162 
+00163         /*
+00164          *      app_stopped - the user-space application has stopped
+00165          *
+00166          *      Do app-specific cleanup now, if desired
+00167          */
+00168         void (*app_stopped) (void);
+00169 };
+00170 
+00171 /*
+00172  * relay-app API functions
+00173  */
+00174 static int init_relay_app(const char *dirname,
+00175                           const char *file_basename,
+00176                           struct relay_app_callbacks *callbacks);
+00177 static void close_relay_app(void);
+00178 
+00179 /*
+00180  * relay-app write wrapper macros - use these instead of directly
+00181  * using relay_write() and _relay_write() relayfs functions.
+00182  */
+00183 #define relayapp_write(data, len) \
+00184         if (app.logging) relay_write(app.chan, data, len)
+00185 
+00186 #define _relayapp_write(data, len) \
+00187         if (app.logging) _relay_write(app.chan, data, len)
+00188 
+00189 /* relay-app control channel command values */
+00190 enum
+00191 {
+00192         RELAY_APP_BUF_INFO = 1,
+00193         RELAY_APP_SUBBUFS_CONSUMED,
+00194         RELAY_APP_START,
+00195         RELAY_APP_STOP,
+00196         RELAY_APP_CHAN_CREATE,
+00197         RELAY_APP_CHAN_DESTROY,
+00198         RELAY_APP_USERCMD_START = 32
+00199 };
+00200 
+00201 /* SystemTap extensions */
+00202 enum
+00203 {
+00204         STP_REALTIME_DATA = RELAY_APP_USERCMD_START,
+00205         STP_EXIT,
+00206         STP_DONE
+00207 };
+00208 
+00209 /* internal stuff below here */
+00210 
+00211 /* netlink control channel */
+00212 static struct sock *control;
+00213 static int seq;
+00214 static int stpd_pid = 0;
+00215 
+00216 /* info for this application */
+00217 static struct relay_app
+00218 {
+00219         char dirname[1024];
+00220         char file_basename[1024];
+00221         struct relay_app_callbacks *cb;
+00222         struct rchan *chan;
+00223         struct dentry *dir;
+00224         int logging;
+00225         int mappings;
+00226 } app;
+00227 
+00228 /*
+00229  * subbuf_start() relayfs callback.
+00230  */
+00231 static int relay_app_subbuf_start(struct rchan_buf *buf,
+00232                                   void *subbuf,
+00233                                   unsigned prev_subbuf_idx,
+00234                                   void *prev_subbuf)
+00235 {
+00236         unsigned padding = buf->padding[prev_subbuf_idx];
+00237         if (prev_subbuf)
+00238                 *((unsigned *)prev_subbuf) = padding;
+00239 
+00240         return sizeof(padding); /* reserve space for padding */
+00241 }
+00242 
+00243 /*
+00244  * buf_full() relayfs callback.
+00245  */
+00246 static void relay_app_buf_full(struct rchan_buf *buf,
+00247                                unsigned subbuf_idx,
+00248                                void *subbuf)
+00249 {
+00250         unsigned padding = buf->padding[subbuf_idx];
+00251         *((unsigned *)subbuf) = padding;
+00252 }
+00253 
+00254 static void relay_app_buf_mapped(struct rchan_buf *buf, struct file *filp)
+00255 {
+00256         if (app.cb && app.cb->app_started && !app.mappings++)
+00257                 app.cb->app_started();
+00258 }
+00259 
+00260 static void relay_app_buf_unmapped(struct rchan_buf *buf, struct file *filp)
+00261 {
+00262         if (app.cb && app.cb->app_started && !--app.mappings)
+00263                 app.cb->app_stopped();
+00264 }
+00265 
+00266 static struct rchan_callbacks app_rchan_callbacks =
+00267 {
+00268         .subbuf_start = relay_app_subbuf_start,
+00269         .buf_full = relay_app_buf_full,
+00270         .buf_mapped = relay_app_buf_mapped,
+00271         .buf_unmapped = relay_app_buf_unmapped
+00272 };
+00273 
+00274 /**
+00275  *      create_app_chan - creates channel /mnt/relay/dirname/filebaseXXX
+00276  *
+00277  *      Returns channel on success, NULL otherwise.
+00278  */
+00279 static struct rchan *create_app_chan(unsigned subbuf_size,
+00280                                      unsigned n_subbufs)
+00281 {
+00282         struct rchan *chan;
+00283 
+00284         if (strlen(app.dirname)) {
+00285                 app.dir = relayfs_create_dir(app.dirname, NULL);
+00286                 if (!app.dir) {
+00287                         printk("Couldn't create relayfs app directory %s.\n", app.dirname);
+00288                         return NULL;
+00289                 }
+00290         }
+00291 
+00292         chan = relay_open(app.file_basename, app.dir, subbuf_size,
+00293                               n_subbufs, 0, &app_rchan_callbacks);
+00294         
+00295         if (!chan) {
+00296                 printk("relay app channel creation failed\n");
+00297                 if (app.dir)
+00298                         relayfs_remove_dir(app.dir);
+00299                 return NULL;
+00300         }
+00301 
+00302         return chan;
+00303 }
+00304 
+00305 /**
+00306  *      destroy_app_chan - destroys channel /mnt/relay/dirname/filebaseXXX
+00307  */
+00308 static void destroy_app_chan(struct rchan *chan)
+00309 {
+00310         if (chan)
+00311                 relay_close(chan);
+00312         if (app.dir)
+00313                 relayfs_remove_dir(app.dir);
+00314 
+00315         app.chan = NULL;
+00316         app.dir = NULL;
+00317 }
+00318 
+00319 /* netlink control channel communication with userspace */
+00320 
+00321 struct buf_info
+00322 {
+00323         int cpu;
+00324         unsigned produced;
+00325         unsigned consumed;
+00326 };
+00327 
+00328 struct consumed_info
+00329 {
+00330         int cpu;
+00331         unsigned consumed;
+00332 };
+00333 
+00334 struct channel_create_info
+00335 {
+00336         unsigned subbuf_size;
+00337         unsigned n_subbufs;
+00338 };
+00339 
+00340 /*
+00341  * send_reply - send reply to userspace over netlink control channel
+00342  */
+00343 static int send_reply(int type, void *reply, int len, int pid)
+00344 {
+00345         struct sk_buff *skb;
+00346         struct nlmsghdr *nlh;
+00347         void *data;
+00348         int size;
+00349         int err;
+00350                 
+00351         size = NLMSG_SPACE(len);
+00352         skb = alloc_skb(size, GFP_ATOMIC);
+00353         if (!skb)
+00354                 return -1;
+00355         nlh = NLMSG_PUT(skb, pid, seq++, type, size - sizeof(*nlh));
+00356         nlh->nlmsg_flags = 0;
+00357         data = NLMSG_DATA(nlh);
+00358         memcpy(data, reply, len);
+00359         err = netlink_unicast(control, skb, pid, MSG_DONTWAIT);
+00360 
+00361         return 0;
+00362 
+00363 nlmsg_failure:
+00364         if (skb)
+00365                 kfree_skb(skb);
+00366         
+00367         return -1;
+00368 }
+00369 
+00370 static void handle_buf_info(struct buf_info *in, int pid)
+00371 {
+00372         struct buf_info out;
+00373 
+00374         if (!app.chan)
+00375                 return;
+00376 
+00377         out.cpu = in->cpu;
+00378         out.produced = atomic_read(&app.chan->buf[in->cpu]->subbufs_produced);
+00379         out.consumed = atomic_read(&app.chan->buf[in->cpu]->subbufs_consumed);
+00380 
+00381         send_reply(RELAY_APP_BUF_INFO, &out, sizeof(out), pid);
+00382 }
+00383 
+00384 static inline void handle_subbufs_consumed(struct consumed_info *info)
+00385 {
+00386         if (!app.chan)
+00387                 return;
+00388 
+00389         relay_subbufs_consumed(app.chan, info->cpu, info->consumed);
+00390 }
+00391 
+00392 static inline void handle_create(struct channel_create_info *info)
+00393 {
+00394         destroy_app_chan(app.chan);
+00395         app.chan = create_app_chan(info->subbuf_size, info->n_subbufs);
+00396         if(!app.chan)
+00397                 return;
+00398         app.mappings = 0;
+00399 }
+00400 
+00401 /*
+00402  * msg_rcv_skb - dispatch userspace requests from netlink control channel
+00403  */
+00404 static void msg_rcv_skb(struct sk_buff *skb)
+00405 {
+00406         struct nlmsghdr *nlh = NULL;
+00407         int pid, flags;
+00408         int nlmsglen, skblen;
+00409         void *data;
+00410         
+00411         skblen = skb->len;
+00412         
+00413         if (skblen < sizeof (*nlh))
+00414                 return; 
+00415 
+00416         nlh = (struct nlmsghdr *)skb->data;
+00417         nlmsglen = nlh->nlmsg_len;
+00418         
+00419         if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
+00420                 return;
+00421 
+00422         stpd_pid = pid = nlh->nlmsg_pid;
+00423         flags = nlh->nlmsg_flags;
+00424 
+00425         if (pid <= 0 || !(flags & NLM_F_REQUEST)) {
+00426                 netlink_ack(skb, nlh, -EINVAL);
+00427                 return;
+00428         }
+00429 
+00430         if (flags & MSG_TRUNC) {
+00431                 netlink_ack(skb, nlh, -ECOMM);
+00432                 return;
+00433         }
+00434         
+00435         data = NLMSG_DATA(nlh);
+00436 
+00437         switch (nlh->nlmsg_type) {
+00438         case RELAY_APP_CHAN_CREATE:
+00439                 handle_create(data);
+00440                 break;
+00441         case RELAY_APP_CHAN_DESTROY:
+00442                 destroy_app_chan(app.chan);
+00443                 break;
+00444         case RELAY_APP_START:
+00445                 app.logging = 1;
+00446                 break;
+00447         case RELAY_APP_STOP:
+00448                 app.logging = 0;
+00449                 relay_flush(app.chan);
+00450                 break;
+00451         case RELAY_APP_BUF_INFO:
+00452                 handle_buf_info(data, pid);
+00453                 break;
+00454         case RELAY_APP_SUBBUFS_CONSUMED:
+00455                 handle_subbufs_consumed(data);
+00456                 break;
+00457         default:
+00458                 if (!app.cb || !app.cb->user_command ||
+00459                     !app.cb->user_command(nlh->nlmsg_type, data))
+00460                         netlink_ack(skb, nlh, -EINVAL);
+00461                 return;
+00462         }
+00463         
+00464         if (flags & NLM_F_ACK)
+00465                 netlink_ack(skb, nlh, 0);
+00466 }
+00467 
+00468 /*
+00469  * msg_rcv - handle netlink control channel requests
+00470  */
+00471 static void msg_rcv(struct sock *sk, int len)
+00472 {
+00473         struct sk_buff *skb;
+00474         
+00475         while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
+00476                 msg_rcv_skb(skb);
+00477                 kfree_skb(skb);
+00478         }
+00479 }
+00480 
+00481 /*
+00482  * _init_relay_app - adds netlink 'unit' if other than NETLINK_USERSOCK wanted
+00483  */
+00484 static int _init_relay_app(const char *dirname,
+00485                            const char *file_basename,
+00486                            struct relay_app_callbacks *callbacks,
+00487                            int unit)
+00488 {
+00489         if (!file_basename)
+00490                 return -1;
+00491 
+00492         if (dirname)
+00493                 strncpy(app.dirname, dirname, 1024);
+00494         strncpy(app.file_basename, file_basename, 1024);
+00495         app.cb = callbacks;
+00496 
+00497         control = netlink_kernel_create(unit, msg_rcv);
+00498         if (!control) {
+00499                 printk("Couldn't create control channel\n");
+00500                 return -1;
+00501         }
+00502 
+00503         return 0;
+00504 }
+00505 
+00506 /**
+00507  *      init_relay_app - initialize /mnt/relay/dirname/file_basenameXXX
+00508  *      @dirname: the directory to contain relayfs files for this app
+00509  *      @file_basename: the base filename of the relayfs files for this app
+00510  *      @callbacks: the relay_app_callbacks implemented for this app
+00511  *
+00512  *      Returns 0 on success, -1 otherwise.
+00513  *
+00514  *      NOTE: this doesn't create the relayfs files.  That happens via the
+00515  *      control channel protocol.
+00516  */
+00517 static int init_relay_app(const char *dirname,
+00518                           const char *file_basename,
+00519                           struct relay_app_callbacks *callbacks)
+00520 {
+00521         return _init_relay_app(dirname, file_basename, callbacks, NETLINK_USERSOCK);
+00522 }
+00523 
+00524 /**
+00525  *      close_relay_app - close netlink socket and destroy channel if it exists
+00526  *
+00527  *      Returns 0 on success, -1 otherwise.
+00528  */
+00529 static void close_relay_app(void)
+00530 {
+00531         if (control)
+00532                 sock_release(control->sk_socket);
+00533         destroy_app_chan(app.chan);
+00534 }
+
-- cgit