Skip to content

Commit a312a0f

Browse files
committed
fgraph: Use fgraph data to store subtime for profiler
Instead of having the "subtime" for the function profiler in the infrastructure ftrace_ret_stack structure, have it use the fgraph data reserve and retrieve functions. This will keep the limited shadow stack from wasting 8 bytes for something that is seldom used. Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Jiri Olsa <[email protected]> Link: https://lore.kernel.org/[email protected] Acked-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent a370b72 commit a312a0f

File tree

3 files changed

+62
-29
lines changed

3 files changed

+62
-29
lines changed

include/linux/ftrace.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ struct fgraph_ops {
10811081

10821082
void *fgraph_reserve_data(int idx, int size_bytes);
10831083
void *fgraph_retrieve_data(int idx, int *size_bytes);
1084+
void *fgraph_retrieve_parent_data(int idx, int *size_bytes, int depth);
10841085

10851086
/*
10861087
* Stack of return addresses for functions
@@ -1091,9 +1092,6 @@ struct ftrace_ret_stack {
10911092
unsigned long ret;
10921093
unsigned long func;
10931094
unsigned long long calltime;
1094-
#ifdef CONFIG_FUNCTION_PROFILER
1095-
unsigned long long subtime;
1096-
#endif
10971095
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
10981096
unsigned long fp;
10991097
#endif

kernel/trace/fgraph.c

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -390,21 +390,7 @@ void *fgraph_reserve_data(int idx, int size_bytes)
390390
*/
391391
void *fgraph_retrieve_data(int idx, int *size_bytes)
392392
{
393-
int offset = current->curr_ret_stack - 1;
394-
unsigned long val;
395-
396-
val = get_fgraph_entry(current, offset);
397-
while (__get_type(val) == FGRAPH_TYPE_DATA) {
398-
if (__get_data_index(val) == idx)
399-
goto found;
400-
offset -= __get_data_size(val) + 1;
401-
val = get_fgraph_entry(current, offset);
402-
}
403-
return NULL;
404-
found:
405-
if (size_bytes)
406-
*size_bytes = __get_data_size(val) * sizeof(long);
407-
return get_data_type_data(current, offset);
393+
return fgraph_retrieve_parent_data(idx, size_bytes, 0);
408394
}
409395

410396
/**
@@ -460,6 +446,54 @@ get_ret_stack(struct task_struct *t, int offset, int *frame_offset)
460446
return RET_STACK(t, offset);
461447
}
462448

449+
/**
450+
* fgraph_retrieve_parent_data - get data from a parent function
451+
* @idx: The index into the fgraph_array (fgraph_ops::idx)
452+
* @size_bytes: A pointer to retrieved data size
453+
* @depth: The depth to find the parent (0 is the current function)
454+
*
455+
* This is similar to fgraph_retrieve_data() but can be used to retrieve
456+
* data from a parent caller function.
457+
*
458+
* Return: a pointer to the specified parent data or NULL if not found
459+
*/
460+
void *fgraph_retrieve_parent_data(int idx, int *size_bytes, int depth)
461+
{
462+
struct ftrace_ret_stack *ret_stack = NULL;
463+
int offset = current->curr_ret_stack;
464+
unsigned long val;
465+
466+
if (offset <= 0)
467+
return NULL;
468+
469+
for (;;) {
470+
int next_offset;
471+
472+
ret_stack = get_ret_stack(current, offset, &next_offset);
473+
if (!ret_stack || --depth < 0)
474+
break;
475+
offset = next_offset;
476+
}
477+
478+
if (!ret_stack)
479+
return NULL;
480+
481+
offset--;
482+
483+
val = get_fgraph_entry(current, offset);
484+
while (__get_type(val) == FGRAPH_TYPE_DATA) {
485+
if (__get_data_index(val) == idx)
486+
goto found;
487+
offset -= __get_data_size(val) + 1;
488+
val = get_fgraph_entry(current, offset);
489+
}
490+
return NULL;
491+
found:
492+
if (size_bytes)
493+
*size_bytes = __get_data_size(val) * sizeof(long);
494+
return get_data_type_data(current, offset);
495+
}
496+
463497
/* Both enabled by default (can be cleared by function_graph tracer flags */
464498
static bool fgraph_sleep_time = true;
465499

kernel/trace/ftrace.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -823,29 +823,30 @@ void ftrace_graph_graph_time_control(bool enable)
823823
static int profile_graph_entry(struct ftrace_graph_ent *trace,
824824
struct fgraph_ops *gops)
825825
{
826-
struct ftrace_ret_stack *ret_stack;
826+
unsigned long long *subtime;
827827

828828
function_profile_call(trace->func, 0, NULL, NULL);
829829

830830
/* If function graph is shutting down, ret_stack can be NULL */
831831
if (!current->ret_stack)
832832
return 0;
833833

834-
ret_stack = ftrace_graph_get_ret_stack(current, 0);
835-
if (ret_stack)
836-
ret_stack->subtime = 0;
834+
subtime = fgraph_reserve_data(gops->idx, sizeof(*subtime));
835+
if (subtime)
836+
*subtime = 0;
837837

838838
return 1;
839839
}
840840

841841
static void profile_graph_return(struct ftrace_graph_ret *trace,
842842
struct fgraph_ops *gops)
843843
{
844-
struct ftrace_ret_stack *ret_stack;
845844
struct ftrace_profile_stat *stat;
846845
unsigned long long calltime;
846+
unsigned long long *subtime;
847847
struct ftrace_profile *rec;
848848
unsigned long flags;
849+
int size;
849850

850851
local_irq_save(flags);
851852
stat = this_cpu_ptr(&ftrace_profile_stats);
@@ -861,13 +862,13 @@ static void profile_graph_return(struct ftrace_graph_ret *trace,
861862
if (!fgraph_graph_time) {
862863

863864
/* Append this call time to the parent time to subtract */
864-
ret_stack = ftrace_graph_get_ret_stack(current, 1);
865-
if (ret_stack)
866-
ret_stack->subtime += calltime;
865+
subtime = fgraph_retrieve_parent_data(gops->idx, &size, 1);
866+
if (subtime)
867+
*subtime += calltime;
867868

868-
ret_stack = ftrace_graph_get_ret_stack(current, 0);
869-
if (ret_stack && ret_stack->subtime < calltime)
870-
calltime -= ret_stack->subtime;
869+
subtime = fgraph_retrieve_data(gops->idx, &size);
870+
if (subtime && *subtime && *subtime < calltime)
871+
calltime -= *subtime;
871872
else
872873
calltime = 0;
873874
}

0 commit comments

Comments
 (0)