Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into for-linus
[cascardo/linux.git] / kernel / trace / ftrace.c
index 065f1e6..d017c2c 100644 (file)
@@ -87,23 +87,29 @@ static struct ftrace_ops ftrace_list_end __read_mostly =
        .func           = ftrace_stub,
 };
 
-static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
+static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end;
+static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
+static struct ftrace_ops global_ops;
+
+static void
+ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip);
 
 /*
- * Traverse the ftrace_list, invoking all entries.  The reason that we
+ * Traverse the ftrace_global_list, invoking all entries.  The reason that we
  * can use rcu_dereference_raw() is that elements removed from this list
  * are simply leaked, so there is no need to interact with a grace-period
  * mechanism.  The rcu_dereference_raw() calls are needed to handle
- * concurrent insertions into the ftrace_list.
+ * concurrent insertions into the ftrace_global_list.
  *
  * Silly Alpha and silly pointer-speculation compiler optimizations!
  */
-static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
+static void ftrace_global_list_func(unsigned long ip,
+                                   unsigned long parent_ip)
 {
-       struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/
+       struct ftrace_ops *op = rcu_dereference_raw(ftrace_global_list); /*see above*/
 
        while (op != &ftrace_list_end) {
                op->func(ip, parent_ip);
@@ -153,7 +159,7 @@ static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip)
 }
 #endif
 
-static void update_ftrace_function(void)
+static void update_global_ops(void)
 {
        ftrace_func_t func;
 
@@ -162,17 +168,39 @@ static void update_ftrace_function(void)
         * function directly. Otherwise, we need to iterate over the
         * registered callers.
         */
-       if (ftrace_list == &ftrace_list_end ||
-           ftrace_list->next == &ftrace_list_end)
-               func = ftrace_list->func;
+       if (ftrace_global_list == &ftrace_list_end ||
+           ftrace_global_list->next == &ftrace_list_end)
+               func = ftrace_global_list->func;
        else
-               func = ftrace_list_func;
+               func = ftrace_global_list_func;
 
        /* If we filter on pids, update to use the pid function */
        if (!list_empty(&ftrace_pids)) {
                set_ftrace_pid_function(func);
                func = ftrace_pid_func;
        }
+
+       global_ops.func = func;
+}
+
+static void update_ftrace_function(void)
+{
+       ftrace_func_t func;
+
+       update_global_ops();
+
+       /*
+        * If we are at the end of the list and this ops is
+        * not dynamic, then have the mcount trampoline call
+        * the function directly
+        */
+       if (ftrace_ops_list == &ftrace_list_end ||
+           (ftrace_ops_list->next == &ftrace_list_end &&
+            !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC)))
+               func = ftrace_ops_list->func;
+       else
+               func = ftrace_ops_list_func;
+
 #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
        ftrace_trace_function = func;
 #else
@@ -181,24 +209,19 @@ static void update_ftrace_function(void)
 #endif
 }
 
-static int __register_ftrace_function(struct ftrace_ops *ops)
+static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
 {
-       ops->next = ftrace_list;
+       ops->next = *list;
        /*
-        * We are entering ops into the ftrace_list but another
+        * We are entering ops into the list but another
         * CPU might be walking that list. We need to make sure
         * the ops->next pointer is valid before another CPU sees
-        * the ops pointer included into the ftrace_list.
+        * the ops pointer included into the list.
         */
-       rcu_assign_pointer(ftrace_list, ops);
-
-       if (ftrace_enabled)
-               update_ftrace_function();
-
-       return 0;
+       rcu_assign_pointer(*list, ops);
 }
 
-static int __unregister_ftrace_function(struct ftrace_ops *ops)
+static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
 {
        struct ftrace_ops **p;
 
@@ -206,13 +229,12 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
         * If we are removing the last function, then simply point
         * to the ftrace_stub.
         */
-       if (ftrace_list == ops && ops->next == &ftrace_list_end) {
-               ftrace_trace_function = ftrace_stub;
-               ftrace_list = &ftrace_list_end;
+       if (*list == ops && ops->next == &ftrace_list_end) {
+               *list = &ftrace_list_end;
                return 0;
        }
 
-       for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next)
+       for (p = list; *p != &ftrace_list_end; p = &(*p)->next)
                if (*p == ops)
                        break;
 
@@ -220,10 +242,73 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
                return -1;
 
        *p = (*p)->next;
+       return 0;
+}
+
+static int __register_ftrace_function(struct ftrace_ops *ops)
+{
+       if (ftrace_disabled)
+               return -ENODEV;
+
+       if (FTRACE_WARN_ON(ops == &global_ops))
+               return -EINVAL;
+
+       if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED))
+               return -EBUSY;
+
+       if (!core_kernel_data((unsigned long)ops))
+               ops->flags |= FTRACE_OPS_FL_DYNAMIC;
+
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               int first = ftrace_global_list == &ftrace_list_end;
+               add_ftrace_ops(&ftrace_global_list, ops);
+               ops->flags |= FTRACE_OPS_FL_ENABLED;
+               if (first)
+                       add_ftrace_ops(&ftrace_ops_list, &global_ops);
+       } else
+               add_ftrace_ops(&ftrace_ops_list, ops);
+
+       if (ftrace_enabled)
+               update_ftrace_function();
+
+       return 0;
+}
+
+static int __unregister_ftrace_function(struct ftrace_ops *ops)
+{
+       int ret;
+
+       if (ftrace_disabled)
+               return -ENODEV;
+
+       if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
+               return -EBUSY;
+
+       if (FTRACE_WARN_ON(ops == &global_ops))
+               return -EINVAL;
+
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ret = remove_ftrace_ops(&ftrace_global_list, ops);
+               if (!ret && ftrace_global_list == &ftrace_list_end)
+                       ret = remove_ftrace_ops(&ftrace_ops_list, &global_ops);
+               if (!ret)
+                       ops->flags &= ~FTRACE_OPS_FL_ENABLED;
+       } else
+               ret = remove_ftrace_ops(&ftrace_ops_list, ops);
+
+       if (ret < 0)
+               return ret;
 
        if (ftrace_enabled)
                update_ftrace_function();
 
+       /*
+        * Dynamic ops may be freed, we must make sure that all
+        * callers are done before leaving this function.
+        */
+       if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
+               synchronize_sched();
+
        return 0;
 }
 
@@ -876,6 +961,7 @@ struct ftrace_hash {
        unsigned long           size_bits;
        struct hlist_head       *buckets;
        unsigned long           count;
+       struct rcu_head         rcu;
 };
 
 /*
@@ -890,11 +976,7 @@ static const struct ftrace_hash empty_hash = {
 };
 #define EMPTY_HASH     ((struct ftrace_hash *)&empty_hash)
 
-enum {
-       FTRACE_OPS_FL_ENABLED           = 1,
-};
-
-struct ftrace_ops global_ops = {
+static struct ftrace_ops global_ops = {
        .func                   = ftrace_stub,
        .notrace_hash           = EMPTY_HASH,
        .filter_hash            = EMPTY_HASH,
@@ -1021,6 +1103,21 @@ static void free_ftrace_hash(struct ftrace_hash *hash)
        kfree(hash);
 }
 
+static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
+{
+       struct ftrace_hash *hash;
+
+       hash = container_of(rcu, struct ftrace_hash, rcu);
+       free_ftrace_hash(hash);
+}
+
+static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
+{
+       if (!hash || hash == EMPTY_HASH)
+               return;
+       call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu);
+}
+
 static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
 {
        struct ftrace_hash *hash;
@@ -1085,7 +1182,8 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
        struct ftrace_func_entry *entry;
        struct hlist_node *tp, *tn;
        struct hlist_head *hhd;
-       struct ftrace_hash *hash = *dst;
+       struct ftrace_hash *old_hash;
+       struct ftrace_hash *new_hash;
        unsigned long key;
        int size = src->count;
        int bits = 0;
@@ -1096,13 +1194,11 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
         * the empty_hash.
         */
        if (!src->count) {
-               free_ftrace_hash(*dst);
-               *dst = EMPTY_HASH;
+               free_ftrace_hash_rcu(*dst);
+               rcu_assign_pointer(*dst, EMPTY_HASH);
                return 0;
        }
 
-       ftrace_hash_clear(hash);
-
        /*
         * Make the hash size about 1/2 the # found
         */
@@ -1113,27 +1209,9 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
        if (bits > FTRACE_HASH_MAX_BITS)
                bits = FTRACE_HASH_MAX_BITS;
 
-       /* We can't modify the empty_hash */
-       if (hash == EMPTY_HASH) {
-               /* Create a new hash */
-               *dst = alloc_ftrace_hash(bits);
-               if (!*dst) {
-                       *dst = EMPTY_HASH;
-                       return -ENOMEM;
-               }
-               hash = *dst;
-       } else {
-               size = 1 << bits;
-
-               /* Use the old hash, but create new buckets */
-               hhd = kzalloc(sizeof(*hhd) * size, GFP_KERNEL);
-               if (!hhd)
-                       return -ENOMEM;
-
-               kfree(hash->buckets);
-               hash->buckets = hhd;
-               hash->size_bits = bits;
-       }
+       new_hash = alloc_ftrace_hash(bits);
+       if (!new_hash)
+               return -ENOMEM;
 
        size = 1 << src->size_bits;
        for (i = 0; i < size; i++) {
@@ -1144,13 +1222,50 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
                        else
                                key = 0;
                        remove_hash_entry(src, entry);
-                       __add_hash_entry(hash, entry);
+                       __add_hash_entry(new_hash, entry);
                }
        }
 
+       old_hash = *dst;
+       rcu_assign_pointer(*dst, new_hash);
+       free_ftrace_hash_rcu(old_hash);
+
        return 0;
 }
 
+/*
+ * Test the hashes for this ops to see if we want to call
+ * the ops->func or not.
+ *
+ * It's a match if the ip is in the ops->filter_hash or
+ * the filter_hash does not exist or is empty,
+ *  AND
+ * the ip is not in the ops->notrace_hash.
+ *
+ * This needs to be called with preemption disabled as
+ * the hashes are freed with call_rcu_sched().
+ */
+static int
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+{
+       struct ftrace_hash *filter_hash;
+       struct ftrace_hash *notrace_hash;
+       int ret;
+
+       filter_hash = rcu_dereference_raw(ops->filter_hash);
+       notrace_hash = rcu_dereference_raw(ops->notrace_hash);
+
+       if ((!filter_hash || !filter_hash->count ||
+            ftrace_lookup_ip(filter_hash, ip)) &&
+           (!notrace_hash || !notrace_hash->count ||
+            !ftrace_lookup_ip(notrace_hash, ip)))
+               ret = 1;
+       else
+               ret = 0;
+
+       return ret;
+}
+
 /*
  * This is a double for. Do not use 'break' to break out of the loop,
  * you must use a goto.
@@ -1194,7 +1309,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
        if (filter_hash) {
                hash = ops->filter_hash;
                other_hash = ops->notrace_hash;
-               if (!hash->count)
+               if (!hash || !hash->count)
                        all = 1;
        } else {
                inc = !inc;
@@ -1204,7 +1319,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
                 * If the notrace hash has no items,
                 * then there's nothing to do.
                 */
-               if (!hash->count)
+               if (hash && !hash->count)
                        return;
        }
 
@@ -1218,11 +1333,11 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
                         * Only the filter_hash affects all records.
                         * Update if the record is not in the notrace hash.
                         */
-                       if (!ftrace_lookup_ip(other_hash, rec->ip))
+                       if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
                                match = 1;
                } else {
-                       in_hash = !!ftrace_lookup_ip(hash, rec->ip);
-                       in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip);
+                       in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip);
+                       in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip);
 
                        /*
                         *
@@ -1508,6 +1623,7 @@ static void ftrace_run_update_code(int command)
 
 static ftrace_func_t saved_ftrace_func;
 static int ftrace_start_up;
+static int global_start_up;
 
 static void ftrace_startup_enable(int command)
 {
@@ -1522,9 +1638,9 @@ static void ftrace_startup_enable(int command)
        ftrace_run_update_code(command);
 }
 
-static void ftrace_startup(int command)
+static void ftrace_startup(struct ftrace_ops *ops, int command)
 {
-       struct ftrace_ops *ops = &global_ops;
+       bool hash_enable = true;
 
        if (unlikely(ftrace_disabled))
                return;
@@ -1532,16 +1648,25 @@ static void ftrace_startup(int command)
        ftrace_start_up++;
        command |= FTRACE_ENABLE_CALLS;
 
+       /* ops marked global share the filter hashes */
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ops = &global_ops;
+               /* Don't update hash if global is already set */
+               if (global_start_up)
+                       hash_enable = false;
+               global_start_up++;
+       }
+
        ops->flags |= FTRACE_OPS_FL_ENABLED;
-       if (ftrace_start_up == 1)
+       if (hash_enable)
                ftrace_hash_rec_enable(ops, 1);
 
        ftrace_startup_enable(command);
 }
 
-static void ftrace_shutdown(int command)
+static void ftrace_shutdown(struct ftrace_ops *ops, int command)
 {
-       struct ftrace_ops *ops = &global_ops;
+       bool hash_disable = true;
 
        if (unlikely(ftrace_disabled))
                return;
@@ -1554,13 +1679,25 @@ static void ftrace_shutdown(int command)
         */
        WARN_ON_ONCE(ftrace_start_up < 0);
 
-       if (!ftrace_start_up)
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
+               ops = &global_ops;
+               global_start_up--;
+               WARN_ON_ONCE(global_start_up < 0);
+               /* Don't update hash if global still has users */
+               if (global_start_up) {
+                       WARN_ON_ONCE(!ftrace_start_up);
+                       hash_disable = false;
+               }
+       }
+
+       if (hash_disable)
                ftrace_hash_rec_disable(ops, 1);
 
-       if (!ftrace_start_up) {
-               command |= FTRACE_DISABLE_CALLS;
+       if (ops != &global_ops || !global_start_up)
                ops->flags &= ~FTRACE_OPS_FL_ENABLED;
-       }
+
+       if (!ftrace_start_up)
+               command |= FTRACE_DISABLE_CALLS;
 
        if (saved_ftrace_func != ftrace_trace_function) {
                saved_ftrace_func = ftrace_trace_function;
@@ -2347,6 +2484,7 @@ static int ftrace_probe_registered;
 
 static void __enable_ftrace_function_probe(void)
 {
+       int ret;
        int i;
 
        if (ftrace_probe_registered)
@@ -2361,13 +2499,16 @@ static void __enable_ftrace_function_probe(void)
        if (i == FTRACE_FUNC_HASHSIZE)
                return;
 
-       __register_ftrace_function(&trace_probe_ops);
-       ftrace_startup(0);
+       ret = __register_ftrace_function(&trace_probe_ops);
+       if (!ret)
+               ftrace_startup(&trace_probe_ops, 0);
+
        ftrace_probe_registered = 1;
 }
 
 static void __disable_ftrace_function_probe(void)
 {
+       int ret;
        int i;
 
        if (!ftrace_probe_registered)
@@ -2380,8 +2521,10 @@ static void __disable_ftrace_function_probe(void)
        }
 
        /* no more funcs left */
-       __unregister_ftrace_function(&trace_probe_ops);
-       ftrace_shutdown(0);
+       ret = __unregister_ftrace_function(&trace_probe_ops);
+       if (!ret)
+               ftrace_shutdown(&trace_probe_ops, 0);
+
        ftrace_probe_registered = 0;
 }
 
@@ -2683,6 +2826,10 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
        struct ftrace_hash *hash;
        int ret;
 
+       /* All global ops uses the global ops filters */
+       if (ops->flags & FTRACE_OPS_FL_GLOBAL)
+               ops = &global_ops;
+
        if (unlikely(ftrace_disabled))
                return -ENODEV;
 
@@ -2713,6 +2860,7 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
 
 /**
  * ftrace_set_filter - set a function to filter on in ftrace
+ * @ops - the ops to set the filter with
  * @buf - the string that holds the function filter text.
  * @len - the length of the string.
  * @reset - non zero to reset all filters before applying this filter.
@@ -2720,13 +2868,49 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
  * Filters denote which functions should be enabled when tracing is enabled.
  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
  */
-void ftrace_set_filter(unsigned char *buf, int len, int reset)
+void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
+                      int len, int reset)
+{
+       ftrace_set_regex(ops, buf, len, reset, 1);
+}
+EXPORT_SYMBOL_GPL(ftrace_set_filter);
+
+/**
+ * ftrace_set_notrace - set a function to not trace in ftrace
+ * @ops - the ops to set the notrace filter with
+ * @buf - the string that holds the function notrace text.
+ * @len - the length of the string.
+ * @reset - non zero to reset all filters before applying this filter.
+ *
+ * Notrace Filters denote which functions should not be enabled when tracing
+ * is enabled. If @buf is NULL and reset is set, all functions will be enabled
+ * for tracing.
+ */
+void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
+                       int len, int reset)
+{
+       ftrace_set_regex(ops, buf, len, reset, 0);
+}
+EXPORT_SYMBOL_GPL(ftrace_set_notrace);
+/**
+ * ftrace_set_filter - set a function to filter on in ftrace
+ * @ops - the ops to set the filter with
+ * @buf - the string that holds the function filter text.
+ * @len - the length of the string.
+ * @reset - non zero to reset all filters before applying this filter.
+ *
+ * Filters denote which functions should be enabled when tracing is enabled.
+ * If @buf is NULL and reset is set, all functions will be enabled for tracing.
+ */
+void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
 {
        ftrace_set_regex(&global_ops, buf, len, reset, 1);
 }
+EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
 
 /**
  * ftrace_set_notrace - set a function to not trace in ftrace
+ * @ops - the ops to set the notrace filter with
  * @buf - the string that holds the function notrace text.
  * @len - the length of the string.
  * @reset - non zero to reset all filters before applying this filter.
@@ -2735,10 +2919,11 @@ void ftrace_set_filter(unsigned char *buf, int len, int reset)
  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
  * for tracing.
  */
-void ftrace_set_notrace(unsigned char *buf, int len, int reset)
+void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
 {
        ftrace_set_regex(&global_ops, buf, len, reset, 0);
 }
+EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
 
 /*
  * command line interface to allow users to set filters on boot up.
@@ -3267,6 +3452,10 @@ void __init ftrace_init(void)
 
 #else
 
+static struct ftrace_ops global_ops = {
+       .func                   = ftrace_stub,
+};
+
 static int __init ftrace_nodyn_init(void)
 {
        ftrace_enabled = 1;
@@ -3277,12 +3466,38 @@ device_initcall(ftrace_nodyn_init);
 static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
 static inline void ftrace_startup_enable(int command) { }
 /* Keep as macros so we do not need to define the commands */
-# define ftrace_startup(command)       do { } while (0)
-# define ftrace_shutdown(command)      do { } while (0)
+# define ftrace_startup(ops, command)  do { } while (0)
+# define ftrace_shutdown(ops, command) do { } while (0)
 # define ftrace_startup_sysctl()       do { } while (0)
 # define ftrace_shutdown_sysctl()      do { } while (0)
+
+static inline int
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+{
+       return 1;
+}
+
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+static void
+ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip)
+{
+       struct ftrace_ops *op;
+
+       /*
+        * Some of the ops may be dynamically allocated,
+        * they must be freed after a synchronize_sched().
+        */
+       preempt_disable_notrace();
+       op = rcu_dereference_raw(ftrace_ops_list);
+       while (op != &ftrace_list_end) {
+               if (ftrace_ops_test(op, ip))
+                       op->func(ip, parent_ip);
+               op = rcu_dereference_raw(op->next);
+       };
+       preempt_enable_notrace();
+}
+
 static void clear_ftrace_swapper(void)
 {
        struct task_struct *p;
@@ -3583,12 +3798,15 @@ int register_ftrace_function(struct ftrace_ops *ops)
                goto out_unlock;
 
        ret = __register_ftrace_function(ops);
-       ftrace_startup(0);
+       if (!ret)
+               ftrace_startup(ops, 0);
+
 
  out_unlock:
        mutex_unlock(&ftrace_lock);
        return ret;
 }
+EXPORT_SYMBOL_GPL(register_ftrace_function);
 
 /**
  * unregister_ftrace_function - unregister a function for profiling.
@@ -3602,11 +3820,13 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
 
        mutex_lock(&ftrace_lock);
        ret = __unregister_ftrace_function(ops);
-       ftrace_shutdown(0);
+       if (!ret)
+               ftrace_shutdown(ops, 0);
        mutex_unlock(&ftrace_lock);
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(unregister_ftrace_function);
 
 int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
@@ -3632,11 +3852,11 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
                ftrace_startup_sysctl();
 
                /* we are starting ftrace again */
-               if (ftrace_list != &ftrace_list_end) {
-                       if (ftrace_list->next == &ftrace_list_end)
-                               ftrace_trace_function = ftrace_list->func;
+               if (ftrace_ops_list != &ftrace_list_end) {
+                       if (ftrace_ops_list->next == &ftrace_list_end)
+                               ftrace_trace_function = ftrace_ops_list->func;
                        else
-                               ftrace_trace_function = ftrace_list_func;
+                               ftrace_trace_function = ftrace_ops_list_func;
                }
 
        } else {
@@ -3825,7 +4045,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
        ftrace_graph_return = retfunc;
        ftrace_graph_entry = entryfunc;
 
-       ftrace_startup(FTRACE_START_FUNC_RET);
+       ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
 
 out:
        mutex_unlock(&ftrace_lock);
@@ -3842,7 +4062,7 @@ void unregister_ftrace_graph(void)
        ftrace_graph_active--;
        ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
        ftrace_graph_entry = ftrace_graph_entry_stub;
-       ftrace_shutdown(FTRACE_STOP_FUNC_RET);
+       ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
        unregister_pm_notifier(&ftrace_suspend_notifier);
        unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);