diff options
Diffstat (limited to 'Documentation/s390/s390dbf.txt')
-rw-r--r-- | Documentation/s390/s390dbf.txt | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt new file mode 100644 index 000000000000..2d1cd939b4df --- /dev/null +++ b/Documentation/s390/s390dbf.txt | |||
@@ -0,0 +1,615 @@ | |||
1 | S390 Debug Feature | ||
2 | ================== | ||
3 | |||
4 | files: arch/s390/kernel/debug.c | ||
5 | include/asm-s390/debug.h | ||
6 | |||
7 | Description: | ||
8 | ------------ | ||
9 | The goal of this feature is to provide a kernel debug logging API | ||
10 | where log records can be stored efficiently in memory, where each component | ||
11 | (e.g. device drivers) can have one separate debug log. | ||
12 | One purpose of this is to inspect the debug logs after a production system crash | ||
13 | in order to analyze the reason for the crash. | ||
14 | If the system still runs but only a subcomponent which uses dbf failes, | ||
15 | it is possible to look at the debug logs on a live system via the Linux proc | ||
16 | filesystem. | ||
17 | The debug feature may also very useful for kernel and driver development. | ||
18 | |||
19 | Design: | ||
20 | ------- | ||
21 | Kernel components (e.g. device drivers) can register themselves at the debug | ||
22 | feature with the function call debug_register(). This function initializes a | ||
23 | debug log for the caller. For each debug log exists a number of debug areas | ||
24 | where exactly one is active at one time. Each debug area consists of contiguous | ||
25 | pages in memory. In the debug areas there are stored debug entries (log records) | ||
26 | which are written by event- and exception-calls. | ||
27 | |||
28 | An event-call writes the specified debug entry to the active debug | ||
29 | area and updates the log pointer for the active area. If the end | ||
30 | of the active debug area is reached, a wrap around is done (ring buffer) | ||
31 | and the next debug entry will be written at the beginning of the active | ||
32 | debug area. | ||
33 | |||
34 | An exception-call writes the specified debug entry to the log and | ||
35 | switches to the next debug area. This is done in order to be sure | ||
36 | that the records which describe the origin of the exception are not | ||
37 | overwritten when a wrap around for the current area occurs. | ||
38 | |||
39 | The debug areas itselve are also ordered in form of a ring buffer. | ||
40 | When an exception is thrown in the last debug area, the following debug | ||
41 | entries are then written again in the very first area. | ||
42 | |||
43 | There are three versions for the event- and exception-calls: One for | ||
44 | logging raw data, one for text and one for numbers. | ||
45 | |||
46 | Each debug entry contains the following data: | ||
47 | |||
48 | - Timestamp | ||
49 | - Cpu-Number of calling task | ||
50 | - Level of debug entry (0...6) | ||
51 | - Return Address to caller | ||
52 | - Flag, if entry is an exception or not | ||
53 | |||
54 | The debug logs can be inspected in a live system through entries in | ||
55 | the proc-filesystem. Under the path /proc/s390dbf there is | ||
56 | a directory for each registered component, which is named like the | ||
57 | corresponding component. | ||
58 | |||
59 | The content of the directories are files which represent different views | ||
60 | to the debug log. Each component can decide which views should be | ||
61 | used through registering them with the function debug_register_view(). | ||
62 | Predefined views for hex/ascii, sprintf and raw binary data are provided. | ||
63 | It is also possible to define other views. The content of | ||
64 | a view can be inspected simply by reading the corresponding proc file. | ||
65 | |||
66 | All debug logs have an an actual debug level (range from 0 to 6). | ||
67 | The default level is 3. Event and Exception functions have a 'level' | ||
68 | parameter. Only debug entries with a level that is lower or equal | ||
69 | than the actual level are written to the log. This means, when | ||
70 | writing events, high priority log entries should have a low level | ||
71 | value whereas low priority entries should have a high one. | ||
72 | The actual debug level can be changed with the help of the proc-filesystem | ||
73 | through writing a number string "x" to the 'level' proc file which is | ||
74 | provided for every debug log. Debugging can be switched off completely | ||
75 | by using "-" on the 'level' proc file. | ||
76 | |||
77 | Example: | ||
78 | |||
79 | > echo "-" > /proc/s390dbf/dasd/level | ||
80 | |||
81 | It is also possible to deactivate the debug feature globally for every | ||
82 | debug log. You can change the behavior using 2 sysctl parameters in | ||
83 | /proc/sys/s390dbf: | ||
84 | There are currently 2 possible triggers, which stop the debug feature | ||
85 | globally. The first possbility is to use the "debug_active" sysctl. If | ||
86 | set to 1 the debug feature is running. If "debug_active" is set to 0 the | ||
87 | debug feature is turned off. | ||
88 | The second trigger which stops the debug feature is an kernel oops. | ||
89 | That prevents the debug feature from overwriting debug information that | ||
90 | happened before the oops. After an oops you can reactivate the debug feature | ||
91 | by piping 1 to /proc/sys/s390dbf/debug_active. Nevertheless, its not | ||
92 | suggested to use an oopsed kernel in an production environment. | ||
93 | If you want to disallow the deactivation of the debug feature, you can use | ||
94 | the "debug_stoppable" sysctl. If you set "debug_stoppable" to 0 the debug | ||
95 | feature cannot be stopped. If the debug feature is already stopped, it | ||
96 | will stay deactivated. | ||
97 | |||
98 | Kernel Interfaces: | ||
99 | ------------------ | ||
100 | |||
101 | ---------------------------------------------------------------------------- | ||
102 | debug_info_t *debug_register(char *name, int pages_index, int nr_areas, | ||
103 | int buf_size); | ||
104 | |||
105 | Parameter: name: Name of debug log (e.g. used for proc entry) | ||
106 | pages_index: 2^pages_index pages will be allocated per area | ||
107 | nr_areas: number of debug areas | ||
108 | buf_size: size of data area in each debug entry | ||
109 | |||
110 | Return Value: Handle for generated debug area | ||
111 | NULL if register failed | ||
112 | |||
113 | Description: Allocates memory for a debug log | ||
114 | Must not be called within an interrupt handler | ||
115 | |||
116 | --------------------------------------------------------------------------- | ||
117 | void debug_unregister (debug_info_t * id); | ||
118 | |||
119 | Parameter: id: handle for debug log | ||
120 | |||
121 | Return Value: none | ||
122 | |||
123 | Description: frees memory for a debug log | ||
124 | Must not be called within an interrupt handler | ||
125 | |||
126 | --------------------------------------------------------------------------- | ||
127 | void debug_set_level (debug_info_t * id, int new_level); | ||
128 | |||
129 | Parameter: id: handle for debug log | ||
130 | new_level: new debug level | ||
131 | |||
132 | Return Value: none | ||
133 | |||
134 | Description: Sets new actual debug level if new_level is valid. | ||
135 | |||
136 | --------------------------------------------------------------------------- | ||
137 | +void debug_stop_all(void); | ||
138 | |||
139 | Parameter: none | ||
140 | |||
141 | Return Value: none | ||
142 | |||
143 | Description: stops the debug feature if stopping is allowed. Currently | ||
144 | used in case of a kernel oops. | ||
145 | |||
146 | --------------------------------------------------------------------------- | ||
147 | debug_entry_t* debug_event (debug_info_t* id, int level, void* data, | ||
148 | int length); | ||
149 | |||
150 | Parameter: id: handle for debug log | ||
151 | level: debug level | ||
152 | data: pointer to data for debug entry | ||
153 | length: length of data in bytes | ||
154 | |||
155 | Return Value: Address of written debug entry | ||
156 | |||
157 | Description: writes debug entry to active debug area (if level <= actual | ||
158 | debug level) | ||
159 | |||
160 | --------------------------------------------------------------------------- | ||
161 | debug_entry_t* debug_int_event (debug_info_t * id, int level, | ||
162 | unsigned int data); | ||
163 | debug_entry_t* debug_long_event(debug_info_t * id, int level, | ||
164 | unsigned long data); | ||
165 | |||
166 | Parameter: id: handle for debug log | ||
167 | level: debug level | ||
168 | data: integer value for debug entry | ||
169 | |||
170 | Return Value: Address of written debug entry | ||
171 | |||
172 | Description: writes debug entry to active debug area (if level <= actual | ||
173 | debug level) | ||
174 | |||
175 | --------------------------------------------------------------------------- | ||
176 | debug_entry_t* debug_text_event (debug_info_t * id, int level, | ||
177 | const char* data); | ||
178 | |||
179 | Parameter: id: handle for debug log | ||
180 | level: debug level | ||
181 | data: string for debug entry | ||
182 | |||
183 | Return Value: Address of written debug entry | ||
184 | |||
185 | Description: writes debug entry in ascii format to active debug area | ||
186 | (if level <= actual debug level) | ||
187 | |||
188 | --------------------------------------------------------------------------- | ||
189 | debug_entry_t* debug_sprintf_event (debug_info_t * id, int level, | ||
190 | char* string,...); | ||
191 | |||
192 | Parameter: id: handle for debug log | ||
193 | level: debug level | ||
194 | string: format string for debug entry | ||
195 | ...: varargs used as in sprintf() | ||
196 | |||
197 | Return Value: Address of written debug entry | ||
198 | |||
199 | Description: writes debug entry with format string and varargs (longs) to | ||
200 | active debug area (if level $<=$ actual debug level). | ||
201 | floats and long long datatypes cannot be used as varargs. | ||
202 | |||
203 | --------------------------------------------------------------------------- | ||
204 | |||
205 | debug_entry_t* debug_exception (debug_info_t* id, int level, void* data, | ||
206 | int length); | ||
207 | |||
208 | Parameter: id: handle for debug log | ||
209 | level: debug level | ||
210 | data: pointer to data for debug entry | ||
211 | length: length of data in bytes | ||
212 | |||
213 | Return Value: Address of written debug entry | ||
214 | |||
215 | Description: writes debug entry to active debug area (if level <= actual | ||
216 | debug level) and switches to next debug area | ||
217 | |||
218 | --------------------------------------------------------------------------- | ||
219 | debug_entry_t* debug_int_exception (debug_info_t * id, int level, | ||
220 | unsigned int data); | ||
221 | debug_entry_t* debug_long_exception(debug_info_t * id, int level, | ||
222 | unsigned long data); | ||
223 | |||
224 | Parameter: id: handle for debug log | ||
225 | level: debug level | ||
226 | data: integer value for debug entry | ||
227 | |||
228 | Return Value: Address of written debug entry | ||
229 | |||
230 | Description: writes debug entry to active debug area (if level <= actual | ||
231 | debug level) and switches to next debug area | ||
232 | |||
233 | --------------------------------------------------------------------------- | ||
234 | debug_entry_t* debug_text_exception (debug_info_t * id, int level, | ||
235 | const char* data); | ||
236 | |||
237 | Parameter: id: handle for debug log | ||
238 | level: debug level | ||
239 | data: string for debug entry | ||
240 | |||
241 | Return Value: Address of written debug entry | ||
242 | |||
243 | Description: writes debug entry in ascii format to active debug area | ||
244 | (if level <= actual debug level) and switches to next debug | ||
245 | area | ||
246 | |||
247 | --------------------------------------------------------------------------- | ||
248 | debug_entry_t* debug_sprintf_exception (debug_info_t * id, int level, | ||
249 | char* string,...); | ||
250 | |||
251 | Parameter: id: handle for debug log | ||
252 | level: debug level | ||
253 | string: format string for debug entry | ||
254 | ...: varargs used as in sprintf() | ||
255 | |||
256 | Return Value: Address of written debug entry | ||
257 | |||
258 | Description: writes debug entry with format string and varargs (longs) to | ||
259 | active debug area (if level $<=$ actual debug level) and | ||
260 | switches to next debug area. | ||
261 | floats and long long datatypes cannot be used as varargs. | ||
262 | |||
263 | --------------------------------------------------------------------------- | ||
264 | |||
265 | int debug_register_view (debug_info_t * id, struct debug_view *view); | ||
266 | |||
267 | Parameter: id: handle for debug log | ||
268 | view: pointer to debug view struct | ||
269 | |||
270 | Return Value: 0 : ok | ||
271 | < 0: Error | ||
272 | |||
273 | Description: registers new debug view and creates proc dir entry | ||
274 | |||
275 | --------------------------------------------------------------------------- | ||
276 | int debug_unregister_view (debug_info_t * id, struct debug_view *view); | ||
277 | |||
278 | Parameter: id: handle for debug log | ||
279 | view: pointer to debug view struct | ||
280 | |||
281 | Return Value: 0 : ok | ||
282 | < 0: Error | ||
283 | |||
284 | Description: unregisters debug view and removes proc dir entry | ||
285 | |||
286 | |||
287 | |||
288 | Predefined views: | ||
289 | ----------------- | ||
290 | |||
291 | extern struct debug_view debug_hex_ascii_view; | ||
292 | extern struct debug_view debug_raw_view; | ||
293 | extern struct debug_view debug_sprintf_view; | ||
294 | |||
295 | Examples | ||
296 | -------- | ||
297 | |||
298 | /* | ||
299 | * hex_ascii- + raw-view Example | ||
300 | */ | ||
301 | |||
302 | #include <linux/init.h> | ||
303 | #include <asm/debug.h> | ||
304 | |||
305 | static debug_info_t* debug_info; | ||
306 | |||
307 | static int init(void) | ||
308 | { | ||
309 | /* register 4 debug areas with one page each and 4 byte data field */ | ||
310 | |||
311 | debug_info = debug_register ("test", 0, 4, 4 ); | ||
312 | debug_register_view(debug_info,&debug_hex_ascii_view); | ||
313 | debug_register_view(debug_info,&debug_raw_view); | ||
314 | |||
315 | debug_text_event(debug_info, 4 , "one "); | ||
316 | debug_int_exception(debug_info, 4, 4711); | ||
317 | debug_event(debug_info, 3, &debug_info, 4); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static void cleanup(void) | ||
323 | { | ||
324 | debug_unregister (debug_info); | ||
325 | } | ||
326 | |||
327 | module_init(init); | ||
328 | module_exit(cleanup); | ||
329 | |||
330 | --------------------------------------------------------------------------- | ||
331 | |||
332 | /* | ||
333 | * sprintf-view Example | ||
334 | */ | ||
335 | |||
336 | #include <linux/init.h> | ||
337 | #include <asm/debug.h> | ||
338 | |||
339 | static debug_info_t* debug_info; | ||
340 | |||
341 | static int init(void) | ||
342 | { | ||
343 | /* register 4 debug areas with one page each and data field for */ | ||
344 | /* format string pointer + 2 varargs (= 3 * sizeof(long)) */ | ||
345 | |||
346 | debug_info = debug_register ("test", 0, 4, sizeof(long) * 3); | ||
347 | debug_register_view(debug_info,&debug_sprintf_view); | ||
348 | |||
349 | debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__); | ||
350 | debug_sprintf_exception(debug_info, 1, "pointer to debug info: %p\n",&debug_info); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static void cleanup(void) | ||
356 | { | ||
357 | debug_unregister (debug_info); | ||
358 | } | ||
359 | |||
360 | module_init(init); | ||
361 | module_exit(cleanup); | ||
362 | |||
363 | |||
364 | |||
365 | ProcFS Interface | ||
366 | ---------------- | ||
367 | Views to the debug logs can be investigated through reading the corresponding | ||
368 | proc-files: | ||
369 | |||
370 | Example: | ||
371 | |||
372 | > ls /proc/s390dbf/dasd | ||
373 | flush hex_ascii level raw | ||
374 | > cat /proc/s390dbf/dasd/hex_ascii | sort +1 | ||
375 | 00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | .... | ||
376 | 00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE | ||
377 | 00 00974733272:682213 2 - 02 0006adf6 07 ea 4a 90 | .... | ||
378 | 00 00974733272:682281 1 * 02 0006ab08 41 4c 4c 43 | EXCP | ||
379 | 01 00974733272:682284 2 - 02 0006ab16 45 43 4b 44 | ECKD | ||
380 | 01 00974733272:682287 2 - 02 0006ab28 00 00 00 04 | .... | ||
381 | 01 00974733272:682289 2 - 02 0006ab3e 00 00 00 20 | ... | ||
382 | 01 00974733272:682297 2 - 02 0006ad7e 07 ea 4a 90 | .... | ||
383 | 01 00974733272:684384 2 - 00 0006ade6 46 52 45 45 | FREE | ||
384 | 01 00974733272:684388 2 - 00 0006adf6 07 ea 4a 90 | .... | ||
385 | |||
386 | See section about predefined views for explanation of the above output! | ||
387 | |||
388 | Changing the debug level | ||
389 | ------------------------ | ||
390 | |||
391 | Example: | ||
392 | |||
393 | |||
394 | > cat /proc/s390dbf/dasd/level | ||
395 | 3 | ||
396 | > echo "5" > /proc/s390dbf/dasd/level | ||
397 | > cat /proc/s390dbf/dasd/level | ||
398 | 5 | ||
399 | |||
400 | Flushing debug areas | ||
401 | -------------------- | ||
402 | Debug areas can be flushed with piping the number of the desired | ||
403 | area (0...n) to the proc file "flush". When using "-" all debug areas | ||
404 | are flushed. | ||
405 | |||
406 | Examples: | ||
407 | |||
408 | 1. Flush debug area 0: | ||
409 | > echo "0" > /proc/s390dbf/dasd/flush | ||
410 | |||
411 | 2. Flush all debug areas: | ||
412 | > echo "-" > /proc/s390dbf/dasd/flush | ||
413 | |||
414 | Stooping the debug feature | ||
415 | -------------------------- | ||
416 | Example: | ||
417 | |||
418 | 1. Check if stopping is allowed | ||
419 | > cat /proc/sys/s390dbf/debug_stoppable | ||
420 | 2. Stop debug feature | ||
421 | > echo 0 > /proc/sys/s390dbf/debug_active | ||
422 | |||
423 | lcrash Interface | ||
424 | ---------------- | ||
425 | It is planned that the dump analysis tool lcrash gets an additional command | ||
426 | 's390dbf' to display all the debug logs. With this tool it will be possible | ||
427 | to investigate the debug logs on a live system and with a memory dump after | ||
428 | a system crash. | ||
429 | |||
430 | Investigating raw memory | ||
431 | ------------------------ | ||
432 | One last possibility to investigate the debug logs at a live | ||
433 | system and after a system crash is to look at the raw memory | ||
434 | under VM or at the Service Element. | ||
435 | It is possible to find the anker of the debug-logs through | ||
436 | the 'debug_area_first' symbol in the System map. Then one has | ||
437 | to follow the correct pointers of the data-structures defined | ||
438 | in debug.h and find the debug-areas in memory. | ||
439 | Normally modules which use the debug feature will also have | ||
440 | a global variable with the pointer to the debug-logs. Following | ||
441 | this pointer it will also be possible to find the debug logs in | ||
442 | memory. | ||
443 | |||
444 | For this method it is recommended to use '16 * x + 4' byte (x = 0..n) | ||
445 | for the length of the data field in debug_register() in | ||
446 | order to see the debug entries well formatted. | ||
447 | |||
448 | |||
449 | Predefined Views | ||
450 | ---------------- | ||
451 | |||
452 | There are three predefined views: hex_ascii, raw and sprintf. | ||
453 | The hex_ascii view shows the data field in hex and ascii representation | ||
454 | (e.g. '45 43 4b 44 | ECKD'). | ||
455 | The raw view returns a bytestream as the debug areas are stored in memory. | ||
456 | |||
457 | The sprintf view formats the debug entries in the same way as the sprintf | ||
458 | function would do. The sprintf event/expection fuctions write to the | ||
459 | debug entry a pointer to the format string (size = sizeof(long)) | ||
460 | and for each vararg a long value. So e.g. for a debug entry with a format | ||
461 | string plus two varargs one would need to allocate a (3 * sizeof(long)) | ||
462 | byte data area in the debug_register() function. | ||
463 | |||
464 | |||
465 | NOTE: If using the sprintf view do NOT use other event/exception functions | ||
466 | than the sprintf-event and -exception functions. | ||
467 | |||
468 | The format of the hex_ascii and sprintf view is as follows: | ||
469 | - Number of area | ||
470 | - Timestamp (formatted as seconds and microseconds since 00:00:00 Coordinated | ||
471 | Universal Time (UTC), January 1, 1970) | ||
472 | - level of debug entry | ||
473 | - Exception flag (* = Exception) | ||
474 | - Cpu-Number of calling task | ||
475 | - Return Address to caller | ||
476 | - data field | ||
477 | |||
478 | The format of the raw view is: | ||
479 | - Header as described in debug.h | ||
480 | - datafield | ||
481 | |||
482 | A typical line of the hex_ascii view will look like the following (first line | ||
483 | is only for explanation and will not be displayed when 'cating' the view): | ||
484 | |||
485 | area time level exception cpu caller data (hex + ascii) | ||
486 | -------------------------------------------------------------------------- | ||
487 | 00 00964419409:440690 1 - 00 88023fe | ||
488 | |||
489 | |||
490 | Defining views | ||
491 | -------------- | ||
492 | |||
493 | Views are specified with the 'debug_view' structure. There are defined | ||
494 | callback functions which are used for reading and writing the proc files: | ||
495 | |||
496 | struct debug_view { | ||
497 | char name[DEBUG_MAX_PROCF_LEN]; | ||
498 | debug_prolog_proc_t* prolog_proc; | ||
499 | debug_header_proc_t* header_proc; | ||
500 | debug_format_proc_t* format_proc; | ||
501 | debug_input_proc_t* input_proc; | ||
502 | void* private_data; | ||
503 | }; | ||
504 | |||
505 | where | ||
506 | |||
507 | typedef int (debug_header_proc_t) (debug_info_t* id, | ||
508 | struct debug_view* view, | ||
509 | int area, | ||
510 | debug_entry_t* entry, | ||
511 | char* out_buf); | ||
512 | |||
513 | typedef int (debug_format_proc_t) (debug_info_t* id, | ||
514 | struct debug_view* view, char* out_buf, | ||
515 | const char* in_buf); | ||
516 | typedef int (debug_prolog_proc_t) (debug_info_t* id, | ||
517 | struct debug_view* view, | ||
518 | char* out_buf); | ||
519 | typedef int (debug_input_proc_t) (debug_info_t* id, | ||
520 | struct debug_view* view, | ||
521 | struct file* file, const char* user_buf, | ||
522 | size_t in_buf_size, loff_t* offset); | ||
523 | |||
524 | |||
525 | The "private_data" member can be used as pointer to view specific data. | ||
526 | It is not used by the debug feature itself. | ||
527 | |||
528 | The output when reading a debug-proc file is structured like this: | ||
529 | |||
530 | "prolog_proc output" | ||
531 | |||
532 | "header_proc output 1" "format_proc output 1" | ||
533 | "header_proc output 2" "format_proc output 2" | ||
534 | "header_proc output 3" "format_proc output 3" | ||
535 | ... | ||
536 | |||
537 | When a view is read from the proc fs, the Debug Feature calls the | ||
538 | 'prolog_proc' once for writing the prolog. | ||
539 | Then 'header_proc' and 'format_proc' are called for each | ||
540 | existing debug entry. | ||
541 | |||
542 | The input_proc can be used to implement functionality when it is written to | ||
543 | the view (e.g. like with 'echo "0" > /proc/s390dbf/dasd/level). | ||
544 | |||
545 | For header_proc there can be used the default function | ||
546 | debug_dflt_header_fn() which is defined in in debug.h. | ||
547 | and which produces the same header output as the predefined views. | ||
548 | E.g: | ||
549 | 00 00964419409:440761 2 - 00 88023ec | ||
550 | |||
551 | In order to see how to use the callback functions check the implementation | ||
552 | of the default views! | ||
553 | |||
554 | Example | ||
555 | |||
556 | #include <asm/debug.h> | ||
557 | |||
558 | #define UNKNOWNSTR "data: %08x" | ||
559 | |||
560 | const char* messages[] = | ||
561 | {"This error...........\n", | ||
562 | "That error...........\n", | ||
563 | "Problem..............\n", | ||
564 | "Something went wrong.\n", | ||
565 | "Everything ok........\n", | ||
566 | NULL | ||
567 | }; | ||
568 | |||
569 | static int debug_test_format_fn( | ||
570 | debug_info_t * id, struct debug_view *view, | ||
571 | char *out_buf, const char *in_buf | ||
572 | ) | ||
573 | { | ||
574 | int i, rc = 0; | ||
575 | |||
576 | if(id->buf_size >= 4) { | ||
577 | int msg_nr = *((int*)in_buf); | ||
578 | if(msg_nr < sizeof(messages)/sizeof(char*) - 1) | ||
579 | rc += sprintf(out_buf, "%s", messages[msg_nr]); | ||
580 | else | ||
581 | rc += sprintf(out_buf, UNKNOWNSTR, msg_nr); | ||
582 | } | ||
583 | out: | ||
584 | return rc; | ||
585 | } | ||
586 | |||
587 | struct debug_view debug_test_view = { | ||
588 | "myview", /* name of view */ | ||
589 | NULL, /* no prolog */ | ||
590 | &debug_dflt_header_fn, /* default header for each entry */ | ||
591 | &debug_test_format_fn, /* our own format function */ | ||
592 | NULL, /* no input function */ | ||
593 | NULL /* no private data */ | ||
594 | }; | ||
595 | |||
596 | ===== | ||
597 | test: | ||
598 | ===== | ||
599 | debug_info_t *debug_info; | ||
600 | ... | ||
601 | debug_info = debug_register ("test", 0, 4, 4 )); | ||
602 | debug_register_view(debug_info, &debug_test_view); | ||
603 | for(i = 0; i < 10; i ++) debug_int_event(debug_info, 1, i); | ||
604 | |||
605 | > cat /proc/s390dbf/test/myview | ||
606 | 00 00964419734:611402 1 - 00 88042ca This error........... | ||
607 | 00 00964419734:611405 1 - 00 88042ca That error........... | ||
608 | 00 00964419734:611408 1 - 00 88042ca Problem.............. | ||
609 | 00 00964419734:611411 1 - 00 88042ca Something went wrong. | ||
610 | 00 00964419734:611414 1 - 00 88042ca Everything ok........ | ||
611 | 00 00964419734:611417 1 - 00 88042ca data: 00000005 | ||
612 | 00 00964419734:611419 1 - 00 88042ca data: 00000006 | ||
613 | 00 00964419734:611422 1 - 00 88042ca data: 00000007 | ||
614 | 00 00964419734:611425 1 - 00 88042ca data: 00000008 | ||
615 | 00 00964419734:611428 1 - 00 88042ca data: 00000009 | ||