summaryrefslogtreecommitdiffstats
path: root/runtime/docs/html/relay-app_8h-source.html
blob: 16feefe0ab4936d7ef41a3628261083708876221 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
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>