ftrace: Replace record newlist with record page list
As new functions come in to be initalized from mcount to nop, they are done by groups of pages. Whether it is the core kernel or a module. There's no need to keep track of these on a per record basis. At startup, and as any module is loaded, the functions to be traced are stored in a group of pages and added to the function list at the end. We just need to keep a pointer to the first page of the list that was added, and use that to know where to start on the list for initializing functions. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
Родитель
a790087554
Коммит
85ae32ae01
|
@ -173,10 +173,7 @@ struct dyn_ftrace {
|
||||||
unsigned long ip; /* address of mcount call-site */
|
unsigned long ip; /* address of mcount call-site */
|
||||||
struct dyn_ftrace *freelist;
|
struct dyn_ftrace *freelist;
|
||||||
};
|
};
|
||||||
union {
|
unsigned long flags;
|
||||||
unsigned long flags;
|
|
||||||
struct dyn_ftrace *newlist;
|
|
||||||
};
|
|
||||||
struct dyn_arch_ftrace arch;
|
struct dyn_arch_ftrace arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -977,8 +977,6 @@ static struct ftrace_ops global_ops = {
|
||||||
.filter_hash = EMPTY_HASH,
|
.filter_hash = EMPTY_HASH,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dyn_ftrace *ftrace_new_addrs;
|
|
||||||
|
|
||||||
static DEFINE_MUTEX(ftrace_regex_lock);
|
static DEFINE_MUTEX(ftrace_regex_lock);
|
||||||
|
|
||||||
struct ftrace_page {
|
struct ftrace_page {
|
||||||
|
@ -988,6 +986,8 @@ struct ftrace_page {
|
||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ftrace_page *ftrace_new_pgs;
|
||||||
|
|
||||||
#define ENTRY_SIZE sizeof(struct dyn_ftrace)
|
#define ENTRY_SIZE sizeof(struct dyn_ftrace)
|
||||||
#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
|
#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
|
||||||
|
|
||||||
|
@ -1445,8 +1445,6 @@ ftrace_record_ip(unsigned long ip)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rec->ip = ip;
|
rec->ip = ip;
|
||||||
rec->newlist = ftrace_new_addrs;
|
|
||||||
ftrace_new_addrs = rec;
|
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
@ -1936,9 +1934,11 @@ static int ops_traces_mod(struct ftrace_ops *ops)
|
||||||
|
|
||||||
static int ftrace_update_code(struct module *mod)
|
static int ftrace_update_code(struct module *mod)
|
||||||
{
|
{
|
||||||
|
struct ftrace_page *pg;
|
||||||
struct dyn_ftrace *p;
|
struct dyn_ftrace *p;
|
||||||
cycle_t start, stop;
|
cycle_t start, stop;
|
||||||
unsigned long ref = 0;
|
unsigned long ref = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When adding a module, we need to check if tracers are
|
* When adding a module, we need to check if tracers are
|
||||||
|
@ -1960,41 +1960,44 @@ static int ftrace_update_code(struct module *mod)
|
||||||
start = ftrace_now(raw_smp_processor_id());
|
start = ftrace_now(raw_smp_processor_id());
|
||||||
ftrace_update_cnt = 0;
|
ftrace_update_cnt = 0;
|
||||||
|
|
||||||
while (ftrace_new_addrs) {
|
for (pg = ftrace_new_pgs; pg; pg = pg->next) {
|
||||||
|
|
||||||
/* If something went wrong, bail without enabling anything */
|
for (i = 0; i < pg->index; i++) {
|
||||||
if (unlikely(ftrace_disabled))
|
/* If something went wrong, bail without enabling anything */
|
||||||
return -1;
|
if (unlikely(ftrace_disabled))
|
||||||
|
return -1;
|
||||||
|
|
||||||
p = ftrace_new_addrs;
|
p = &pg->records[i];
|
||||||
ftrace_new_addrs = p->newlist;
|
p->flags = ref;
|
||||||
p->flags = ref;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the initial record conversion from mcount jump
|
* Do the initial record conversion from mcount jump
|
||||||
* to the NOP instructions.
|
* to the NOP instructions.
|
||||||
*/
|
*/
|
||||||
if (!ftrace_code_disable(mod, p))
|
if (!ftrace_code_disable(mod, p))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ftrace_update_cnt++;
|
ftrace_update_cnt++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the tracing is enabled, go ahead and enable the record.
|
* If the tracing is enabled, go ahead and enable the record.
|
||||||
*
|
*
|
||||||
* The reason not to enable the record immediatelly is the
|
* The reason not to enable the record immediatelly is the
|
||||||
* inherent check of ftrace_make_nop/ftrace_make_call for
|
* inherent check of ftrace_make_nop/ftrace_make_call for
|
||||||
* correct previous instructions. Making first the NOP
|
* correct previous instructions. Making first the NOP
|
||||||
* conversion puts the module to the correct state, thus
|
* conversion puts the module to the correct state, thus
|
||||||
* passing the ftrace_make_call check.
|
* passing the ftrace_make_call check.
|
||||||
*/
|
*/
|
||||||
if (ftrace_start_up && ref) {
|
if (ftrace_start_up && ref) {
|
||||||
int failed = __ftrace_replace_code(p, 1);
|
int failed = __ftrace_replace_code(p, 1);
|
||||||
if (failed)
|
if (failed)
|
||||||
ftrace_bug(failed, p->ip);
|
ftrace_bug(failed, p->ip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftrace_new_pgs = NULL;
|
||||||
|
|
||||||
stop = ftrace_now(raw_smp_processor_id());
|
stop = ftrace_now(raw_smp_processor_id());
|
||||||
ftrace_update_time = stop - start;
|
ftrace_update_time = stop - start;
|
||||||
ftrace_update_tot_cnt += ftrace_update_cnt;
|
ftrace_update_tot_cnt += ftrace_update_cnt;
|
||||||
|
@ -3632,6 +3635,9 @@ static int ftrace_process_locs(struct module *mod,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These new locations need to be initialized */
|
||||||
|
ftrace_new_pgs = pg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only need to disable interrupts on start up
|
* We only need to disable interrupts on start up
|
||||||
* because we are modifying code that an interrupt
|
* because we are modifying code that an interrupt
|
||||||
|
|
Загрузка…
Ссылка в новой задаче