@@ -1360,6 +1360,8 @@ static const char *hist_field_name(struct hist_field *field,
13601360 field_name = field -> name ;
13611361 } else if (field -> flags & HIST_FIELD_FL_TIMESTAMP )
13621362 field_name = "common_timestamp" ;
1363+ else if (field -> flags & HIST_FIELD_FL_STACKTRACE )
1364+ field_name = "stacktrace" ;
13631365 else if (field -> flags & HIST_FIELD_FL_HITCOUNT )
13641366 field_name = "hitcount" ;
13651367
@@ -1980,6 +1982,10 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
19801982
19811983 if (flags & HIST_FIELD_FL_STACKTRACE ) {
19821984 hist_field -> fn_num = HIST_FIELD_FN_NOP ;
1985+ hist_field -> size = HIST_STACKTRACE_SIZE ;
1986+ hist_field -> type = kstrdup_const ("unsigned long[]" , GFP_KERNEL );
1987+ if (!hist_field -> type )
1988+ goto free ;
19831989 goto out ;
19841990 }
19851991
@@ -2351,6 +2357,8 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
23512357 hist_data -> enable_timestamps = true;
23522358 if (* flags & HIST_FIELD_FL_TIMESTAMP_USECS )
23532359 hist_data -> attrs -> ts_in_usecs = true;
2360+ } else if (strcmp (field_name , "stacktrace" ) == 0 ) {
2361+ * flags |= HIST_FIELD_FL_STACKTRACE ;
23542362 } else if (strcmp (field_name , "common_cpu" ) == 0 )
23552363 * flags |= HIST_FIELD_FL_CPU ;
23562364 else if (strcmp (field_name , "hitcount" ) == 0 )
@@ -3119,13 +3127,24 @@ static inline void __update_field_vars(struct tracing_map_elt *elt,
31193127 var_val = hist_fn_call (val , elt , buffer , rbe , rec );
31203128 var_idx = var -> var .idx ;
31213129
3122- if (val -> flags & HIST_FIELD_FL_STRING ) {
3130+ if (val -> flags & (HIST_FIELD_FL_STRING |
3131+ HIST_FIELD_FL_STACKTRACE )) {
31233132 char * str = elt_data -> field_var_str [j ++ ];
31243133 char * val_str = (char * )(uintptr_t )var_val ;
31253134 unsigned int size ;
31263135
3127- size = min (val -> size , STR_VAR_LEN_MAX );
3128- strscpy (str , val_str , size );
3136+ if (val -> flags & HIST_FIELD_FL_STRING ) {
3137+ size = min (val -> size , STR_VAR_LEN_MAX );
3138+ strscpy (str , val_str , size );
3139+ } else {
3140+ int e ;
3141+
3142+ e = stack_trace_save ((void * )str ,
3143+ HIST_STACKTRACE_DEPTH ,
3144+ HIST_STACKTRACE_SKIP );
3145+ if (e < HIST_STACKTRACE_DEPTH - 1 )
3146+ ((unsigned long * )str )[e ] = 0 ;
3147+ }
31293148 var_val = (u64 )(uintptr_t )str ;
31303149 }
31313150 tracing_map_set_var (elt , var_idx , var_val );
@@ -3824,7 +3843,8 @@ static void save_field_var(struct hist_trigger_data *hist_data,
38243843{
38253844 hist_data -> field_vars [hist_data -> n_field_vars ++ ] = field_var ;
38263845
3827- if (field_var -> val -> flags & HIST_FIELD_FL_STRING )
3846+ /* Stack traces are saved in the string storage too */
3847+ if (field_var -> val -> flags & (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE ))
38283848 hist_data -> n_field_var_str ++ ;
38293849}
38303850
@@ -4103,7 +4123,8 @@ static int action_create(struct hist_trigger_data *hist_data,
41034123 }
41044124
41054125 hist_data -> save_vars [hist_data -> n_save_vars ++ ] = field_var ;
4106- if (field_var -> val -> flags & HIST_FIELD_FL_STRING )
4126+ if (field_var -> val -> flags &
4127+ (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE ))
41074128 hist_data -> n_save_var_str ++ ;
41084129 kfree (param );
41094130 }
@@ -4351,7 +4372,8 @@ static int create_var_field(struct hist_trigger_data *hist_data,
43514372 if (!ret && hist_data -> fields [val_idx ]-> flags & HIST_FIELD_FL_EXECNAME )
43524373 update_var_execname (hist_data -> fields [val_idx ]);
43534374
4354- if (!ret && hist_data -> fields [val_idx ]-> flags & HIST_FIELD_FL_STRING )
4375+ if (!ret && hist_data -> fields [val_idx ]-> flags &
4376+ (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE ))
43554377 hist_data -> fields [val_idx ]-> var_str_idx = hist_data -> n_var_str ++ ;
43564378
43574379 return ret ;
@@ -5092,7 +5114,8 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
50925114 if (hist_field -> flags & HIST_FIELD_FL_VAR ) {
50935115 var_idx = hist_field -> var .idx ;
50945116
5095- if (hist_field -> flags & HIST_FIELD_FL_STRING ) {
5117+ if (hist_field -> flags &
5118+ (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE )) {
50965119 unsigned int str_start , var_str_idx , idx ;
50975120 char * str , * val_str ;
50985121 unsigned int size ;
@@ -5105,9 +5128,18 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
51055128 str = elt_data -> field_var_str [idx ];
51065129 val_str = (char * )(uintptr_t )hist_val ;
51075130
5108- size = min (hist_field -> size , STR_VAR_LEN_MAX );
5109- strscpy (str , val_str , size );
5110-
5131+ if (hist_field -> flags & HIST_FIELD_FL_STRING ) {
5132+ size = min (hist_field -> size , STR_VAR_LEN_MAX );
5133+ strscpy (str , val_str , size );
5134+ } else {
5135+ int e ;
5136+
5137+ e = stack_trace_save ((void * )str ,
5138+ HIST_STACKTRACE_DEPTH ,
5139+ HIST_STACKTRACE_SKIP );
5140+ if (e < HIST_STACKTRACE_DEPTH - 1 )
5141+ ((unsigned long * )str )[e ] = 0 ;
5142+ }
51115143 hist_val = (u64 )(uintptr_t )str ;
51125144 }
51135145 tracing_map_set_var (elt , var_idx , hist_val );
0 commit comments