6
6
*/
7
7
#include <getopt.h>
8
8
#include <stdlib.h>
9
+ #include <stdio.h>
9
10
#include <string.h>
10
11
#include <errno.h>
11
12
#include <unistd.h>
13
+ #include <dirent.h>
12
14
13
15
#include <trace.h>
14
16
#include <utils.h>
15
17
#include <rv.h>
16
18
17
19
static int config_has_id ;
20
+ static int config_is_container ;
18
21
static int config_my_pid ;
19
22
static int config_trace ;
20
23
@@ -44,6 +47,51 @@ static int __ikm_read_enable(char *monitor_name)
44
47
return enabled ;
45
48
}
46
49
50
+ /*
51
+ * __ikm_find_monitor - find the full name of a possibly nested module
52
+ *
53
+ * __does not log errors.
54
+ *
55
+ * Returns 1 if we found the monitor, -1 on error and 0 if it does not exist.
56
+ * The string out_name is populated with the full name, which can be
57
+ * equal to monitor_name or container/monitor_name if nested
58
+ */
59
+ static int __ikm_find_monitor_name (char * monitor_name , char * out_name )
60
+ {
61
+ char * available_monitors , container [MAX_DA_NAME_LEN + 1 ], * cursor , * end ;
62
+ int retval = 1 ;
63
+
64
+ available_monitors = tracefs_instance_file_read (NULL , "rv/available_monitors" , NULL );
65
+ if (!available_monitors )
66
+ return -1 ;
67
+
68
+ cursor = strstr (available_monitors , monitor_name );
69
+ if (!cursor ) {
70
+ retval = 0 ;
71
+ goto out_free ;
72
+ }
73
+
74
+ for (; cursor > available_monitors ; cursor -- )
75
+ if (* (cursor - 1 ) == '\n' )
76
+ break ;
77
+ end = strstr (cursor , "\n" );
78
+ memcpy (out_name , cursor , end - cursor );
79
+ out_name [end - cursor ] = '\0' ;
80
+
81
+ cursor = strstr (out_name , ":" );
82
+ if (cursor )
83
+ * cursor = '/' ;
84
+ else {
85
+ sprintf (container , "%s:" , monitor_name );
86
+ if (strstr (available_monitors , container ))
87
+ config_is_container = 1 ;
88
+ }
89
+
90
+ out_free :
91
+ free (available_monitors );
92
+ return retval ;
93
+ }
94
+
47
95
/*
48
96
* ikm_read_enable - reads monitor's enable status
49
97
*
@@ -137,7 +185,17 @@ static char *ikm_read_desc(char *monitor_name)
137
185
static int ikm_fill_monitor_definition (char * name , struct monitor * ikm )
138
186
{
139
187
int enabled ;
140
- char * desc ;
188
+ char * desc , * nested_name ;
189
+
190
+ nested_name = strstr (name , ":" );
191
+ if (nested_name ) {
192
+ * nested_name = '/' ;
193
+ ++ nested_name ;
194
+ ikm -> nested = 1 ;
195
+ } else {
196
+ nested_name = name ;
197
+ ikm -> nested = 0 ;
198
+ }
141
199
142
200
enabled = ikm_read_enable (name );
143
201
if (enabled < 0 ) {
@@ -151,7 +209,7 @@ static int ikm_fill_monitor_definition(char *name, struct monitor *ikm)
151
209
return -1 ;
152
210
}
153
211
154
- strncpy (ikm -> name , name , MAX_DA_NAME_LEN );
212
+ strncpy (ikm -> name , nested_name , MAX_DA_NAME_LEN );
155
213
ikm -> enabled = enabled ;
156
214
strncpy (ikm -> desc , desc , MAX_DESCRIPTION );
157
215
@@ -273,7 +331,7 @@ static int ikm_has_id(char *monitor_name)
273
331
int ikm_list_monitors (void )
274
332
{
275
333
char * available_monitors ;
276
- struct monitor ikm ;
334
+ struct monitor ikm = { 0 } ;
277
335
char * curr , * next ;
278
336
int retval ;
279
337
@@ -293,7 +351,9 @@ int ikm_list_monitors(void)
293
351
if (retval )
294
352
err_msg ("ikm: error reading %d in kernel monitor, skipping\n" , curr );
295
353
296
- printf ("%-24s %s %s\n" , ikm .name , ikm .desc , ikm .enabled ? "[ON]" : "[OFF]" );
354
+ printf ("%s%-*s %s %s\n" , ikm .nested ? " - " : "" ,
355
+ ikm .nested ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN ,
356
+ ikm .name , ikm .desc , ikm .enabled ? "[ON]" : "[OFF]" );
297
357
curr = ++ next ;
298
358
299
359
} while (strlen (curr ));
@@ -343,11 +403,11 @@ ikm_event_handler(struct trace_seq *s, struct tep_record *record,
343
403
unsigned long long final_state ;
344
404
unsigned long long pid ;
345
405
unsigned long long id ;
346
- int cpu = record -> cpu ;
347
406
int val ;
407
+ bool missing_id ;
348
408
349
409
if (config_has_id )
350
- tep_get_field_val (s , trace_event , "id" , record , & id , 1 );
410
+ missing_id = tep_get_field_val (s , trace_event , "id" , record , & id , 1 );
351
411
352
412
tep_get_common_field_val (s , trace_event , "common_pid" , record , & pid , 1 );
353
413
@@ -356,12 +416,21 @@ ikm_event_handler(struct trace_seq *s, struct tep_record *record,
356
416
else if (config_my_pid && (config_my_pid == pid ))
357
417
return 0 ;
358
418
359
- tep_print_event (trace_event -> tep , s , record , "%16s-%-8d " , TEP_PRINT_COMM , TEP_PRINT_PID );
419
+ tep_print_event (trace_event -> tep , s , record , "%16s-%-8d [%.3d] " ,
420
+ TEP_PRINT_COMM , TEP_PRINT_PID , TEP_PRINT_CPU );
360
421
361
- trace_seq_printf (s , "[%.3d] event " , cpu );
422
+ if (config_is_container )
423
+ tep_print_event (trace_event -> tep , s , record , "%s " , TEP_PRINT_NAME );
424
+ else
425
+ trace_seq_printf (s , "event " );
362
426
363
- if (config_has_id )
364
- trace_seq_printf (s , "%8llu " , id );
427
+ if (config_has_id ) {
428
+ if (missing_id )
429
+ /* placeholder if we are dealing with a mixed-type container*/
430
+ trace_seq_printf (s , " " );
431
+ else
432
+ trace_seq_printf (s , "%8llu " , id );
433
+ }
365
434
366
435
state = tep_get_field_raw (s , trace_event , "state" , record , & val , 0 );
367
436
event = tep_get_field_raw (s , trace_event , "event" , record , & val , 0 );
@@ -394,9 +463,10 @@ ikm_error_handler(struct trace_seq *s, struct tep_record *record,
394
463
int cpu = record -> cpu ;
395
464
char * state , * event ;
396
465
int val ;
466
+ bool missing_id ;
397
467
398
468
if (config_has_id )
399
- tep_get_field_val (s , trace_event , "id" , record , & id , 1 );
469
+ missing_id = tep_get_field_val (s , trace_event , "id" , record , & id , 1 );
400
470
401
471
tep_get_common_field_val (s , trace_event , "common_pid" , record , & pid , 1 );
402
472
@@ -405,10 +475,20 @@ ikm_error_handler(struct trace_seq *s, struct tep_record *record,
405
475
else if (config_my_pid == pid )
406
476
return 0 ;
407
477
408
- trace_seq_printf (s , "%8lld [%03d] error " , pid , cpu );
478
+ trace_seq_printf (s , "%8lld [%03d] " , pid , cpu );
409
479
410
- if (config_has_id )
411
- trace_seq_printf (s , "%8llu " , id );
480
+ if (config_is_container )
481
+ tep_print_event (trace_event -> tep , s , record , "%s " , TEP_PRINT_NAME );
482
+ else
483
+ trace_seq_printf (s , "error " );
484
+
485
+ if (config_has_id ) {
486
+ if (missing_id )
487
+ /* placeholder if we are dealing with a mixed-type container*/
488
+ trace_seq_printf (s , " " );
489
+ else
490
+ trace_seq_printf (s , "%8llu " , id );
491
+ }
412
492
413
493
state = tep_get_field_raw (s , trace_event , "state" , record , & val , 0 );
414
494
event = tep_get_field_raw (s , trace_event , "event" , record , & val , 0 );
@@ -421,6 +501,64 @@ ikm_error_handler(struct trace_seq *s, struct tep_record *record,
421
501
return 0 ;
422
502
}
423
503
504
+ static int ikm_enable_trace_events (char * monitor_name , struct trace_instance * inst )
505
+ {
506
+ char event [MAX_DA_NAME_LEN + 7 ]; /* max(error_,event_) + '0' = 7 */
507
+ int retval ;
508
+
509
+ snprintf (event , sizeof (event ), "event_%s" , monitor_name );
510
+ retval = tracefs_event_enable (inst -> inst , "rv" , event );
511
+ if (retval )
512
+ return -1 ;
513
+
514
+ tep_register_event_handler (inst -> tep , -1 , "rv" , event ,
515
+ ikm_event_handler , NULL );
516
+
517
+ snprintf (event , sizeof (event ), "error_%s" , monitor_name );
518
+ retval = tracefs_event_enable (inst -> inst , "rv" , event );
519
+ if (retval )
520
+ return -1 ;
521
+
522
+ tep_register_event_handler (inst -> tep , -1 , "rv" , event ,
523
+ ikm_error_handler , NULL );
524
+
525
+ /* set if at least 1 monitor has id in case of a container */
526
+ config_has_id = ikm_has_id (monitor_name );
527
+ if (config_has_id < 0 )
528
+ return -1 ;
529
+
530
+
531
+ return 0 ;
532
+ }
533
+
534
+ static int ikm_enable_trace_container (char * monitor_name ,
535
+ struct trace_instance * inst )
536
+ {
537
+ DIR * dp ;
538
+ char * abs_path , rv_path [MAX_PATH ];
539
+ struct dirent * ep ;
540
+ int retval = 0 ;
541
+
542
+ snprintf (rv_path , MAX_PATH , "rv/monitors/%s" , monitor_name );
543
+ abs_path = tracefs_instance_get_file (NULL , rv_path );
544
+ if (!abs_path )
545
+ return -1 ;
546
+ dp = opendir (abs_path );
547
+ if (!dp )
548
+ goto out_free ;
549
+
550
+ while (!retval && (ep = readdir (dp ))) {
551
+ if (ep -> d_type != DT_DIR || ep -> d_name [0 ] == '.' )
552
+ continue ;
553
+ retval = ikm_enable_trace_events (ep -> d_name , inst );
554
+ }
555
+
556
+ closedir (dp );
557
+ out_free :
558
+ free (abs_path );
559
+ return retval ;
560
+ }
561
+
424
562
/*
425
563
* ikm_setup_trace_instance - set up a tracing instance to collect data
426
564
*
@@ -430,19 +568,12 @@ ikm_error_handler(struct trace_seq *s, struct tep_record *record,
430
568
*/
431
569
static struct trace_instance * ikm_setup_trace_instance (char * monitor_name )
432
570
{
433
- char event [MAX_DA_NAME_LEN + 7 ]; /* max(error_,event_) + '0' = 7 */
434
571
struct trace_instance * inst ;
435
572
int retval ;
436
573
437
574
if (!config_trace )
438
575
return NULL ;
439
576
440
- config_has_id = ikm_has_id (monitor_name );
441
- if (config_has_id < 0 ) {
442
- err_msg ("ikm: failed to read monitor %s event format\n" , monitor_name );
443
- goto out_err ;
444
- }
445
-
446
577
/* alloc data */
447
578
inst = calloc (1 , sizeof (* inst ));
448
579
if (!inst ) {
@@ -454,23 +585,13 @@ static struct trace_instance *ikm_setup_trace_instance(char *monitor_name)
454
585
if (retval )
455
586
goto out_free ;
456
587
457
- /* enable events */
458
- snprintf (event , sizeof (event ), "event_%s" , monitor_name );
459
- retval = tracefs_event_enable (inst -> inst , "rv" , event );
460
- if (retval )
461
- goto out_inst ;
462
-
463
- tep_register_event_handler (inst -> tep , -1 , "rv" , event ,
464
- ikm_event_handler , NULL );
465
-
466
- snprintf (event , sizeof (event ), "error_%s" , monitor_name );
467
- retval = tracefs_event_enable (inst -> inst , "rv" , event );
588
+ if (config_is_container )
589
+ retval = ikm_enable_trace_container (monitor_name , inst );
590
+ else
591
+ retval = ikm_enable_trace_events (monitor_name , inst );
468
592
if (retval )
469
593
goto out_inst ;
470
594
471
- tep_register_event_handler (inst -> tep , -1 , "rv" , event ,
472
- ikm_error_handler , NULL );
473
-
474
595
/* ready to enable */
475
596
tracefs_trace_on (inst -> inst );
476
597
@@ -633,32 +754,41 @@ static int parse_arguments(char *monitor_name, int argc, char **argv)
633
754
int ikm_run_monitor (char * monitor_name , int argc , char * * argv )
634
755
{
635
756
struct trace_instance * inst = NULL ;
757
+ char * nested_name , full_name [2 * MAX_DA_NAME_LEN ];
636
758
int retval ;
637
759
638
- /*
639
- * Check if monitor exists by seeing it is enabled.
640
- */
641
- retval = __ikm_read_enable (monitor_name );
642
- if (retval < 0 )
760
+ nested_name = strstr (monitor_name , ":" );
761
+ if (nested_name )
762
+ ++ nested_name ;
763
+ else
764
+ nested_name = monitor_name ;
765
+
766
+ retval = __ikm_find_monitor_name (monitor_name , full_name );
767
+ if (!retval )
643
768
return 0 ;
769
+ if (retval < 0 ) {
770
+ err_msg ("ikm: error finding monitor %s\n" , nested_name );
771
+ return -1 ;
772
+ }
644
773
774
+ retval = __ikm_read_enable (full_name );
645
775
if (retval ) {
646
- err_msg ("ikm: monitor %s (in-kernel) is already enabled\n" , monitor_name );
776
+ err_msg ("ikm: monitor %s (in-kernel) is already enabled\n" , nested_name );
647
777
return -1 ;
648
778
}
649
779
650
780
/* we should be good to go */
651
- retval = parse_arguments (monitor_name , argc , argv );
781
+ retval = parse_arguments (full_name , argc , argv );
652
782
if (retval )
653
- ikm_usage (1 , monitor_name , "ikm: failed parsing arguments" );
783
+ ikm_usage (1 , nested_name , "ikm: failed parsing arguments" );
654
784
655
785
if (config_trace ) {
656
- inst = ikm_setup_trace_instance (monitor_name );
786
+ inst = ikm_setup_trace_instance (nested_name );
657
787
if (!inst )
658
788
return -1 ;
659
789
}
660
790
661
- retval = ikm_enable (monitor_name );
791
+ retval = ikm_enable (full_name );
662
792
if (retval < 0 )
663
793
goto out_free_instance ;
664
794
@@ -682,17 +812,17 @@ int ikm_run_monitor(char *monitor_name, int argc, char **argv)
682
812
sleep (1 );
683
813
}
684
814
685
- ikm_disable (monitor_name );
815
+ ikm_disable (full_name );
686
816
ikm_destroy_trace_instance (inst );
687
817
688
818
if (config_reactor && config_initial_reactor )
689
- ikm_write_reactor (monitor_name , config_initial_reactor );
819
+ ikm_write_reactor (full_name , config_initial_reactor );
690
820
691
821
return 1 ;
692
822
693
823
out_free_instance :
694
824
ikm_destroy_trace_instance (inst );
695
825
if (config_reactor && config_initial_reactor )
696
- ikm_write_reactor (monitor_name , config_initial_reactor );
826
+ ikm_write_reactor (full_name , config_initial_reactor );
697
827
return -1 ;
698
828
}
0 commit comments