diff options
Diffstat (limited to 'runtime/docs/html/relay-app_8h-source.html')
-rw-r--r-- | runtime/docs/html/relay-app_8h-source.html | 542 |
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 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 List</a> | <a class="qindex" href="globals.html">Globals</a> | <a class="qindex" href="pages.html">Related 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 <zanussi@us.ibm.com></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 <linux/inet.h></span> +00131 <span class="preprocessor">#include <linux/ip.h></span> +00132 <span class="preprocessor">#include <linux/netlink.h></span> +00133 <span class="preprocessor">#include <linux/relayfs_fs.h></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 >= 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->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->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 && app.cb->app_started && !app.mappings++) +00257 app.cb->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 && 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 <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, &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->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->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 <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->cpu, info->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->subbuf_size, info->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->len; +00412 +00413 <span class="keywordflow">if</span> (skblen < <span class="keyword">sizeof</span> (*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 <span class="keywordflow">return</span>; +00428 } +00429 +00430 <span class="keywordflow">if</span> (flags & 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->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->user_command || +00459 !app.cb->user_command(nlh->nlmsg_type, data)) +00460 netlink_ack(skb, nlh, -EINVAL); +00461 <span class="keywordflow">return</span>; +00462 } +00463 +00464 <span class="keywordflow">if</span> (flags & 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(&sk->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->sk_socket); +00533 destroy_app_chan(app.chan); +00534 } +</pre></div></body></html> |