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:
Steven Rostedt 2011-12-16 16:30:31 -05:00 committed by Steven Rostedt
parent a790087554
commit 85ae32ae01
2 changed files with 38 additions and 35 deletions

View File

@ -173,10 +173,7 @@ struct dyn_ftrace {
unsigned long ip; /* address of mcount call-site */
struct dyn_ftrace *freelist;
};
union {
unsigned long flags;
struct dyn_ftrace *newlist;
};
unsigned long flags;
struct dyn_arch_ftrace arch;
};

View File

@ -977,8 +977,6 @@ static struct ftrace_ops global_ops = {
.filter_hash = EMPTY_HASH,
};
static struct dyn_ftrace *ftrace_new_addrs;
static DEFINE_MUTEX(ftrace_regex_lock);
struct ftrace_page {
@ -988,6 +986,8 @@ struct ftrace_page {
int size;
};
static struct ftrace_page *ftrace_new_pgs;
#define ENTRY_SIZE sizeof(struct dyn_ftrace)
#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
@ -1445,8 +1445,6 @@ ftrace_record_ip(unsigned long ip)
return NULL;
rec->ip = ip;
rec->newlist = ftrace_new_addrs;
ftrace_new_addrs = rec;
return rec;
}
@ -1936,9 +1934,11 @@ static int ops_traces_mod(struct ftrace_ops *ops)
static int ftrace_update_code(struct module *mod)
{
struct ftrace_page *pg;
struct dyn_ftrace *p;
cycle_t start, stop;
unsigned long ref = 0;
int i;
/*
* 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());
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 */
if (unlikely(ftrace_disabled))
return -1;
for (i = 0; i < pg->index; i++) {
/* If something went wrong, bail without enabling anything */
if (unlikely(ftrace_disabled))
return -1;
p = ftrace_new_addrs;
ftrace_new_addrs = p->newlist;
p->flags = ref;
p = &pg->records[i];
p->flags = ref;
/*
* Do the initial record conversion from mcount jump
* to the NOP instructions.
*/
if (!ftrace_code_disable(mod, p))
break;
/*
* Do the initial record conversion from mcount jump
* to the NOP instructions.
*/
if (!ftrace_code_disable(mod, p))
break;
ftrace_update_cnt++;
ftrace_update_cnt++;
/*
* If the tracing is enabled, go ahead and enable the record.
*
* The reason not to enable the record immediatelly is the
* inherent check of ftrace_make_nop/ftrace_make_call for
* correct previous instructions. Making first the NOP
* conversion puts the module to the correct state, thus
* passing the ftrace_make_call check.
*/
if (ftrace_start_up && ref) {
int failed = __ftrace_replace_code(p, 1);
if (failed)
ftrace_bug(failed, p->ip);
/*
* If the tracing is enabled, go ahead and enable the record.
*
* The reason not to enable the record immediatelly is the
* inherent check of ftrace_make_nop/ftrace_make_call for
* correct previous instructions. Making first the NOP
* conversion puts the module to the correct state, thus
* passing the ftrace_make_call check.
*/
if (ftrace_start_up && ref) {
int failed = __ftrace_replace_code(p, 1);
if (failed)
ftrace_bug(failed, p->ip);
}
}
}
ftrace_new_pgs = NULL;
stop = ftrace_now(raw_smp_processor_id());
ftrace_update_time = stop - start;
ftrace_update_tot_cnt += ftrace_update_cnt;
@ -3632,6 +3635,9 @@ static int ftrace_process_locs(struct module *mod,
break;
}
/* These new locations need to be initialized */
ftrace_new_pgs = pg;
/*
* We only need to disable interrupts on start up
* because we are modifying code that an interrupt