]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/trace/trace_events_trigger.c
tracing: Fix memory leak in set_trigger_filter()
[linux.git] / kernel / trace / trace_events_trigger.c
index 5dea177cef53120129c7d4a4d76eacb67ad66db0..cd12ecb66eb9236e3ca741517ea55105d744ab6e 100644 (file)
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_events_trigger - trace event triggers
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
  * Copyright (C) 2013 Tom Zanussi <tom.zanussi@linux.intel.com>
  */
 
@@ -34,7 +21,9 @@ void trigger_data_free(struct event_trigger_data *data)
        if (data->cmd_ops->set_filter)
                data->cmd_ops->set_filter(NULL, data, NULL);
 
-       synchronize_sched(); /* make sure current triggers exit before free */
+       /* make sure current triggers exit before free */
+       tracepoint_synchronize_unregister();
+
        kfree(data);
 }
 
@@ -579,9 +568,9 @@ static int register_trigger(char *glob, struct event_trigger_ops *ops,
  * Usually used directly as the @unreg method in event command
  * implementations.
  */
-void unregister_trigger(char *glob, struct event_trigger_ops *ops,
-                       struct event_trigger_data *test,
-                       struct trace_event_file *file)
+static void unregister_trigger(char *glob, struct event_trigger_ops *ops,
+                              struct event_trigger_data *test,
+                              struct trace_event_file *file)
 {
        struct event_trigger_data *data;
        bool unregistered = false;
@@ -743,8 +732,10 @@ int set_trigger_filter(char *filter_str,
 
        /* The filter is for the 'trigger' event, not the triggered event */
        ret = create_event_filter(file->event_call, filter_str, false, &filter);
-       if (ret)
-               goto out;
+       /*
+        * If create_event_filter() fails, filter still needs to be freed.
+        * Which the calling code will do with data->filter.
+        */
  assign:
        tmp = rcu_access_pointer(data->filter);
 
@@ -752,7 +743,7 @@ int set_trigger_filter(char *filter_str,
 
        if (tmp) {
                /* Make sure the call is done with the filter */
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
                free_event_filter(tmp);
        }