@@ -123,6 +123,42 @@ enum ftrace_dump_mode ftrace_dump_on_oops;
123
123
/* When set, tracing will stop when a WARN*() is hit */
124
124
int __disable_trace_on_warning ;
125
125
126
+ #ifdef CONFIG_TRACE_ENUM_MAP_FILE
127
+ /* Map of enums to their values, for "enum_map" file */
128
+ struct trace_enum_map_head {
129
+ struct module * mod ;
130
+ unsigned long length ;
131
+ };
132
+
133
+ union trace_enum_map_item ;
134
+
135
+ struct trace_enum_map_tail {
136
+ /*
137
+ * "end" is first and points to NULL as it must be different
138
+ * than "mod" or "enum_string"
139
+ */
140
+ union trace_enum_map_item * next ;
141
+ const char * end ; /* points to NULL */
142
+ };
143
+
144
+ static DEFINE_MUTEX (trace_enum_mutex );
145
+
146
+ /*
147
+ * The trace_enum_maps are saved in an array with two extra elements,
148
+ * one at the beginning, and one at the end. The beginning item contains
149
+ * the count of the saved maps (head.length), and the module they
150
+ * belong to if not built in (head.mod). The ending item contains a
151
+ * pointer to the next array of saved enum_map items.
152
+ */
153
+ union trace_enum_map_item {
154
+ struct trace_enum_map map ;
155
+ struct trace_enum_map_head head ;
156
+ struct trace_enum_map_tail tail ;
157
+ };
158
+
159
+ static union trace_enum_map_item * trace_enum_maps ;
160
+ #endif /* CONFIG_TRACE_ENUM_MAP_FILE */
161
+
126
162
static int tracing_set_tracer (struct trace_array * tr , const char * buf );
127
163
128
164
#define MAX_TRACER_SIZE 100
@@ -3908,7 +3944,169 @@ static const struct file_operations tracing_saved_cmdlines_size_fops = {
3908
3944
.write = tracing_saved_cmdlines_size_write ,
3909
3945
};
3910
3946
3911
- static void trace_insert_enum_map (struct trace_enum_map * * start , int len )
3947
+ #ifdef CONFIG_TRACE_ENUM_MAP_FILE
3948
+ static union trace_enum_map_item *
3949
+ update_enum_map (union trace_enum_map_item * ptr )
3950
+ {
3951
+ if (!ptr -> map .enum_string ) {
3952
+ if (ptr -> tail .next ) {
3953
+ ptr = ptr -> tail .next ;
3954
+ /* Set ptr to the next real item (skip head) */
3955
+ ptr ++ ;
3956
+ } else
3957
+ return NULL ;
3958
+ }
3959
+ return ptr ;
3960
+ }
3961
+
3962
+ static void * enum_map_next (struct seq_file * m , void * v , loff_t * pos )
3963
+ {
3964
+ union trace_enum_map_item * ptr = v ;
3965
+
3966
+ /*
3967
+ * Paranoid! If ptr points to end, we don't want to increment past it.
3968
+ * This really should never happen.
3969
+ */
3970
+ ptr = update_enum_map (ptr );
3971
+ if (WARN_ON_ONCE (!ptr ))
3972
+ return NULL ;
3973
+
3974
+ ptr ++ ;
3975
+
3976
+ (* pos )++ ;
3977
+
3978
+ ptr = update_enum_map (ptr );
3979
+
3980
+ return ptr ;
3981
+ }
3982
+
3983
+ static void * enum_map_start (struct seq_file * m , loff_t * pos )
3984
+ {
3985
+ union trace_enum_map_item * v ;
3986
+ loff_t l = 0 ;
3987
+
3988
+ mutex_lock (& trace_enum_mutex );
3989
+
3990
+ v = trace_enum_maps ;
3991
+ if (v )
3992
+ v ++ ;
3993
+
3994
+ while (v && l < * pos ) {
3995
+ v = enum_map_next (m , v , & l );
3996
+ }
3997
+
3998
+ return v ;
3999
+ }
4000
+
4001
+ static void enum_map_stop (struct seq_file * m , void * v )
4002
+ {
4003
+ mutex_unlock (& trace_enum_mutex );
4004
+ }
4005
+
4006
+ static int enum_map_show (struct seq_file * m , void * v )
4007
+ {
4008
+ union trace_enum_map_item * ptr = v ;
4009
+
4010
+ seq_printf (m , "%s %ld (%s)\n" ,
4011
+ ptr -> map .enum_string , ptr -> map .enum_value ,
4012
+ ptr -> map .system );
4013
+
4014
+ return 0 ;
4015
+ }
4016
+
4017
+ static const struct seq_operations tracing_enum_map_seq_ops = {
4018
+ .start = enum_map_start ,
4019
+ .next = enum_map_next ,
4020
+ .stop = enum_map_stop ,
4021
+ .show = enum_map_show ,
4022
+ };
4023
+
4024
+ static int tracing_enum_map_open (struct inode * inode , struct file * filp )
4025
+ {
4026
+ if (tracing_disabled )
4027
+ return - ENODEV ;
4028
+
4029
+ return seq_open (filp , & tracing_enum_map_seq_ops );
4030
+ }
4031
+
4032
+ static const struct file_operations tracing_enum_map_fops = {
4033
+ .open = tracing_enum_map_open ,
4034
+ .read = seq_read ,
4035
+ .llseek = seq_lseek ,
4036
+ .release = seq_release ,
4037
+ };
4038
+
4039
+ static inline union trace_enum_map_item *
4040
+ trace_enum_jmp_to_tail (union trace_enum_map_item * ptr )
4041
+ {
4042
+ /* Return tail of array given the head */
4043
+ return ptr + ptr -> head .length + 1 ;
4044
+ }
4045
+
4046
+ static void
4047
+ trace_insert_enum_map_file (struct module * mod , struct trace_enum_map * * start ,
4048
+ int len )
4049
+ {
4050
+ struct trace_enum_map * * stop ;
4051
+ struct trace_enum_map * * map ;
4052
+ union trace_enum_map_item * map_array ;
4053
+ union trace_enum_map_item * ptr ;
4054
+
4055
+ stop = start + len ;
4056
+
4057
+ /*
4058
+ * The trace_enum_maps contains the map plus a head and tail item,
4059
+ * where the head holds the module and length of array, and the
4060
+ * tail holds a pointer to the next list.
4061
+ */
4062
+ map_array = kmalloc (sizeof (* map_array ) * (len + 2 ), GFP_KERNEL );
4063
+ if (!map_array ) {
4064
+ pr_warning ("Unable to allocate trace enum mapping\n" );
4065
+ return ;
4066
+ }
4067
+
4068
+ mutex_lock (& trace_enum_mutex );
4069
+
4070
+ if (!trace_enum_maps )
4071
+ trace_enum_maps = map_array ;
4072
+ else {
4073
+ ptr = trace_enum_maps ;
4074
+ for (;;) {
4075
+ ptr = trace_enum_jmp_to_tail (ptr );
4076
+ if (!ptr -> tail .next )
4077
+ break ;
4078
+ ptr = ptr -> tail .next ;
4079
+
4080
+ }
4081
+ ptr -> tail .next = map_array ;
4082
+ }
4083
+ map_array -> head .mod = mod ;
4084
+ map_array -> head .length = len ;
4085
+ map_array ++ ;
4086
+
4087
+ for (map = start ; (unsigned long )map < (unsigned long )stop ; map ++ ) {
4088
+ map_array -> map = * * map ;
4089
+ map_array ++ ;
4090
+ }
4091
+ memset (map_array , 0 , sizeof (* map_array ));
4092
+
4093
+ mutex_unlock (& trace_enum_mutex );
4094
+ }
4095
+
4096
+ static void trace_create_enum_file (struct dentry * d_tracer )
4097
+ {
4098
+ trace_create_file ("enum_map" , 0444 , d_tracer ,
4099
+ NULL , & tracing_enum_map_fops );
4100
+ }
4101
+
4102
+ #else /* CONFIG_TRACE_ENUM_MAP_FILE */
4103
+ static inline void trace_create_enum_file (struct dentry * d_tracer ) { }
4104
+ static inline void trace_insert_enum_map_file (struct module * mod ,
4105
+ struct trace_enum_map * * start , int len ) { }
4106
+ #endif /* !CONFIG_TRACE_ENUM_MAP_FILE */
4107
+
4108
+ static void trace_insert_enum_map (struct module * mod ,
4109
+ struct trace_enum_map * * start , int len )
3912
4110
{
3913
4111
struct trace_enum_map * * map ;
3914
4112
@@ -3918,6 +4116,8 @@ static void trace_insert_enum_map(struct trace_enum_map **start, int len)
3918
4116
map = start ;
3919
4117
3920
4118
trace_event_enum_update (map , len );
4119
+
4120
+ trace_insert_enum_map_file (mod , start , len );
3921
4121
}
3922
4122
3923
4123
static ssize_t
@@ -6562,7 +6762,7 @@ static void __init trace_enum_init(void)
6562
6762
int len ;
6563
6763
6564
6764
len = __stop_ftrace_enum_maps - __start_ftrace_enum_maps ;
6565
- trace_insert_enum_map (__start_ftrace_enum_maps , len );
6765
+ trace_insert_enum_map (NULL , __start_ftrace_enum_maps , len );
6566
6766
}
6567
6767
6568
6768
#ifdef CONFIG_MODULES
@@ -6578,9 +6778,41 @@ static void trace_module_add_enums(struct module *mod)
6578
6778
if (trace_module_has_bad_taint (mod ))
6579
6779
return ;
6580
6780
6581
- trace_insert_enum_map (mod -> trace_enums , mod -> num_trace_enums );
6781
+ trace_insert_enum_map (mod , mod -> trace_enums , mod -> num_trace_enums );
6582
6782
}
6583
6783
6784
+ #ifdef CONFIG_TRACE_ENUM_MAP_FILE
6785
+ static void trace_module_remove_enums (struct module * mod )
6786
+ {
6787
+ union trace_enum_map_item * map ;
6788
+ union trace_enum_map_item * * last = & trace_enum_maps ;
6789
+
6790
+ if (!mod -> num_trace_enums )
6791
+ return ;
6792
+
6793
+ mutex_lock (& trace_enum_mutex );
6794
+
6795
+ map = trace_enum_maps ;
6796
+
6797
+ while (map ) {
6798
+ if (map -> head .mod == mod )
6799
+ break ;
6800
+ map = trace_enum_jmp_to_tail (map );
6801
+ last = & map -> tail .next ;
6802
+ map = map -> tail .next ;
6803
+ }
6804
+ if (!map )
6805
+ goto out ;
6806
+
6807
+ * last = trace_enum_jmp_to_tail (map )-> tail .next ;
6808
+ kfree (map );
6809
+ out :
6810
+ mutex_unlock (& trace_enum_mutex );
6811
+ }
6812
+ #else
6813
+ static inline void trace_module_remove_enums (struct module * mod ) { }
6814
+ #endif /* CONFIG_TRACE_ENUM_MAP_FILE */
6815
+
6584
6816
static int trace_module_notify (struct notifier_block * self ,
6585
6817
unsigned long val , void * data )
6586
6818
{
@@ -6590,6 +6822,9 @@ static int trace_module_notify(struct notifier_block *self,
6590
6822
case MODULE_STATE_COMING :
6591
6823
trace_module_add_enums (mod );
6592
6824
break ;
6825
+ case MODULE_STATE_GOING :
6826
+ trace_module_remove_enums (mod );
6827
+ break ;
6593
6828
}
6594
6829
6595
6830
return 0 ;
@@ -6599,7 +6834,7 @@ static struct notifier_block trace_module_nb = {
6599
6834
.notifier_call = trace_module_notify ,
6600
6835
.priority = 0 ,
6601
6836
};
6602
- #endif
6837
+ #endif /* CONFIG_MODULES */
6603
6838
6604
6839
static __init int tracer_init_debugfs (void )
6605
6840
{
@@ -6627,6 +6862,8 @@ static __init int tracer_init_debugfs(void)
6627
6862
6628
6863
trace_enum_init ();
6629
6864
6865
+ trace_create_enum_file (d_tracer );
6866
+
6630
6867
#ifdef CONFIG_MODULES
6631
6868
register_module_notifier (& trace_module_nb );
6632
6869
#endif
0 commit comments