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 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>
|