@@ -1595,12 +1595,15 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
1595
1595
unsigned long ftrace_location_range (unsigned long start , unsigned long end )
1596
1596
{
1597
1597
struct dyn_ftrace * rec ;
1598
+ unsigned long ip = 0 ;
1598
1599
1600
+ rcu_read_lock ();
1599
1601
rec = lookup_rec (start , end );
1600
1602
if (rec )
1601
- return rec -> ip ;
1603
+ ip = rec -> ip ;
1604
+ rcu_read_unlock ();
1602
1605
1603
- return 0 ;
1606
+ return ip ;
1604
1607
}
1605
1608
1606
1609
/**
@@ -1614,25 +1617,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
1614
1617
*/
1615
1618
unsigned long ftrace_location (unsigned long ip )
1616
1619
{
1617
- struct dyn_ftrace * rec ;
1620
+ unsigned long loc ;
1618
1621
unsigned long offset ;
1619
1622
unsigned long size ;
1620
1623
1621
- rec = lookup_rec (ip , ip );
1622
- if (!rec ) {
1624
+ loc = ftrace_location_range (ip , ip );
1625
+ if (!loc ) {
1623
1626
if (!kallsyms_lookup_size_offset (ip , & size , & offset ))
1624
1627
goto out ;
1625
1628
1626
1629
/* map sym+0 to __fentry__ */
1627
1630
if (!offset )
1628
- rec = lookup_rec (ip , ip + size - 1 );
1631
+ loc = ftrace_location_range (ip , ip + size - 1 );
1629
1632
}
1630
1633
1631
- if (rec )
1632
- return rec -> ip ;
1633
-
1634
1634
out :
1635
- return 0 ;
1635
+ return loc ;
1636
1636
}
1637
1637
1638
1638
/**
@@ -2538,7 +2538,6 @@ ftrace_find_unique_ops(struct dyn_ftrace *rec)
2538
2538
/* Protected by rcu_tasks for reading, and direct_mutex for writing */
2539
2539
static struct ftrace_hash __rcu * direct_functions = EMPTY_HASH ;
2540
2540
static DEFINE_MUTEX (direct_mutex );
2541
- int ftrace_direct_func_count ;
2542
2541
2543
2542
/*
2544
2543
* Search the direct_functions hash to see if the given instruction pointer
@@ -4201,12 +4200,12 @@ static int
4201
4200
add_rec_by_index (struct ftrace_hash * hash , struct ftrace_glob * func_g ,
4202
4201
int clear_filter )
4203
4202
{
4204
- long index = simple_strtoul ( func_g -> search , NULL , 0 ) ;
4203
+ long index ;
4205
4204
struct ftrace_page * pg ;
4206
4205
struct dyn_ftrace * rec ;
4207
4206
4208
4207
/* The index starts at 1 */
4209
- if (-- index < 0 )
4208
+ if (kstrtoul ( func_g -> search , 0 , & index ) || -- index < 0 )
4210
4209
return 0 ;
4211
4210
4212
4211
do_for_each_ftrace_rec (pg , rec ) {
@@ -5317,14 +5316,6 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long *ips, unsigned int cnt,
5317
5316
5318
5317
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
5319
5318
5320
- struct ftrace_direct_func {
5321
- struct list_head next ;
5322
- unsigned long addr ;
5323
- int count ;
5324
- };
5325
-
5326
- static LIST_HEAD (ftrace_direct_funcs );
5327
-
5328
5319
static int register_ftrace_function_nolock (struct ftrace_ops * ops );
5329
5320
5330
5321
/*
@@ -5365,6 +5356,13 @@ static void remove_direct_functions_hash(struct ftrace_hash *hash, unsigned long
5365
5356
}
5366
5357
}
5367
5358
5359
+ static void register_ftrace_direct_cb (struct rcu_head * rhp )
5360
+ {
5361
+ struct ftrace_hash * fhp = container_of (rhp , struct ftrace_hash , rcu );
5362
+
5363
+ free_ftrace_hash (fhp );
5364
+ }
5365
+
5368
5366
/**
5369
5367
* register_ftrace_direct - Call a custom trampoline directly
5370
5368
* for multiple functions registered in @ops
@@ -5463,10 +5461,8 @@ int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
5463
5461
out_unlock :
5464
5462
mutex_unlock (& direct_mutex );
5465
5463
5466
- if (free_hash && free_hash != EMPTY_HASH ) {
5467
- synchronize_rcu_tasks ();
5468
- free_ftrace_hash (free_hash );
5469
- }
5464
+ if (free_hash && free_hash != EMPTY_HASH )
5465
+ call_rcu_tasks (& free_hash -> rcu , register_ftrace_direct_cb );
5470
5466
5471
5467
if (new_hash )
5472
5468
free_ftrace_hash (new_hash );
@@ -5816,9 +5812,8 @@ __setup("ftrace_graph_notrace=", set_graph_notrace_function);
5816
5812
5817
5813
static int __init set_graph_max_depth_function (char * str )
5818
5814
{
5819
- if (!str )
5815
+ if (!str || kstrtouint ( str , 0 , & fgraph_max_depth ) )
5820
5816
return 0 ;
5821
- fgraph_max_depth = simple_strtoul (str , NULL , 0 );
5822
5817
return 1 ;
5823
5818
}
5824
5819
__setup ("ftrace_graph_max_depth=" , set_graph_max_depth_function );
@@ -6595,6 +6590,8 @@ static int ftrace_process_locs(struct module *mod,
6595
6590
/* We should have used all pages unless we skipped some */
6596
6591
if (pg_unuse ) {
6597
6592
WARN_ON (!skipped );
6593
+ /* Need to synchronize with ftrace_location_range() */
6594
+ synchronize_rcu ();
6598
6595
ftrace_free_pages (pg_unuse );
6599
6596
}
6600
6597
return ret ;
@@ -6808,6 +6805,9 @@ void ftrace_release_mod(struct module *mod)
6808
6805
out_unlock :
6809
6806
mutex_unlock (& ftrace_lock );
6810
6807
6808
+ /* Need to synchronize with ftrace_location_range() */
6809
+ if (tmp_page )
6810
+ synchronize_rcu ();
6811
6811
for (pg = tmp_page ; pg ; pg = tmp_page ) {
6812
6812
6813
6813
/* Needs to be called outside of ftrace_lock */
@@ -7141,6 +7141,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
7141
7141
unsigned long start = (unsigned long )(start_ptr );
7142
7142
unsigned long end = (unsigned long )(end_ptr );
7143
7143
struct ftrace_page * * last_pg = & ftrace_pages_start ;
7144
+ struct ftrace_page * tmp_page = NULL ;
7144
7145
struct ftrace_page * pg ;
7145
7146
struct dyn_ftrace * rec ;
7146
7147
struct dyn_ftrace key ;
@@ -7182,12 +7183,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
7182
7183
ftrace_update_tot_cnt -- ;
7183
7184
if (!pg -> index ) {
7184
7185
* last_pg = pg -> next ;
7185
- if (pg -> records ) {
7186
- free_pages ((unsigned long )pg -> records , pg -> order );
7187
- ftrace_number_of_pages -= 1 << pg -> order ;
7188
- }
7189
- ftrace_number_of_groups -- ;
7190
- kfree (pg );
7186
+ pg -> next = tmp_page ;
7187
+ tmp_page = pg ;
7191
7188
pg = container_of (last_pg , struct ftrace_page , next );
7192
7189
if (!(* last_pg ))
7193
7190
ftrace_pages = pg ;
@@ -7204,6 +7201,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
7204
7201
clear_func_from_hashes (func );
7205
7202
kfree (func );
7206
7203
}
7204
+ /* Need to synchronize with ftrace_location_range() */
7205
+ if (tmp_page ) {
7206
+ synchronize_rcu ();
7207
+ ftrace_free_pages (tmp_page );
7208
+ }
7207
7209
}
7208
7210
7209
7211
void __init ftrace_free_init_mem (void )
0 commit comments