ftrace: Replace record newlist with record page list
authorSteven Rostedt <srostedt@redhat.com>
Fri, 16 Dec 2011 21:30:31 +0000 (16:30 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Wed, 21 Dec 2011 12:19:03 +0000 (07:19 -0500)
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>
include/linux/ftrace.h
kernel/trace/ftrace.c

index 3f79bc458bffe46788a3a3ac674afa3e2f7a3d26..31b9fd7aedcd8cdfcb47adbe6e017c15bd3df4a7 100644 (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;
 };
 
index 2e7218869fe981776ea8fc186f2e78448434c252..366d7881f188078ffb9b4ccb12ad34cbc1f9d381 100644 (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