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