|
@@ -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
|