aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-24 23:11:22 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-26 07:07:00 -0400
commit701970b3a83cc639c1ec8fc6f40a7871cb99426f (patch)
treec17cee9da25eaecee7a7e615eaa932becec663a4 /kernel/trace
parent060fa5c83e67901ba47ab484cfcdb32737d630ba (diff)
tracing/events: make modules have their own file_operations structure
For proper module reference counting, the file_operations that modules use must have the "owner" field set to the module. Unfortunately, the trace events use share file_operations. The same file_operations are used by all both kernel core and all modules. This patch makes the modules allocate their own file_operations and copies the functions from the core kernel. This allows those file operations to be owned by the module. Care is taken to free this code on module unload. Thanks to Greg KH for reminding me that file_operations must be owned by the module to have reference counting take place. [ Impact: fix modular tracepoints / potential crash ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_events.c95
1 files changed, 88 insertions, 7 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index b92081588088..be4d3a437c17 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -770,7 +770,11 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
770} 770}
771 771
772static int 772static int
773event_create_dir(struct ftrace_event_call *call, struct dentry *d_events) 773event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
774 const struct file_operations *id,
775 const struct file_operations *enable,
776 const struct file_operations *filter,
777 const struct file_operations *format)
774{ 778{
775 struct dentry *entry; 779 struct dentry *entry;
776 int ret; 780 int ret;
@@ -800,11 +804,11 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
800 804
801 if (call->regfunc) 805 if (call->regfunc)
802 entry = trace_create_file("enable", 0644, call->dir, call, 806 entry = trace_create_file("enable", 0644, call->dir, call,
803 &ftrace_enable_fops); 807 enable);
804 808
805 if (call->id) 809 if (call->id)
806 entry = trace_create_file("id", 0444, call->dir, call, 810 entry = trace_create_file("id", 0444, call->dir, call,
807 &ftrace_event_id_fops); 811 id);
808 812
809 if (call->define_fields) { 813 if (call->define_fields) {
810 ret = call->define_fields(); 814 ret = call->define_fields();
@@ -814,7 +818,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
814 return ret; 818 return ret;
815 } 819 }
816 entry = trace_create_file("filter", 0644, call->dir, call, 820 entry = trace_create_file("filter", 0644, call->dir, call,
817 &ftrace_event_filter_fops); 821 filter);
818 } 822 }
819 823
820 /* A trace may not want to export its format */ 824 /* A trace may not want to export its format */
@@ -822,7 +826,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
822 return 0; 826 return 0;
823 827
824 entry = trace_create_file("format", 0444, call->dir, call, 828 entry = trace_create_file("format", 0444, call->dir, call,
825 &ftrace_event_format_fops); 829 format);
826 830
827 return 0; 831 return 0;
828} 832}
@@ -833,8 +837,60 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
833 event++) 837 event++)
834 838
835#ifdef CONFIG_MODULES 839#ifdef CONFIG_MODULES
840
841static LIST_HEAD(ftrace_module_file_list);
842
843/*
844 * Modules must own their file_operations to keep up with
845 * reference counting.
846 */
847struct ftrace_module_file_ops {
848 struct list_head list;
849 struct module *mod;
850 struct file_operations id;
851 struct file_operations enable;
852 struct file_operations format;
853 struct file_operations filter;
854};
855
856static struct ftrace_module_file_ops *
857trace_create_file_ops(struct module *mod)
858{
859 struct ftrace_module_file_ops *file_ops;
860
861 /*
862 * This is a bit of a PITA. To allow for correct reference
863 * counting, modules must "own" their file_operations.
864 * To do this, we allocate the file operations that will be
865 * used in the event directory.
866 */
867
868 file_ops = kmalloc(sizeof(*file_ops), GFP_KERNEL);
869 if (!file_ops)
870 return NULL;
871
872 file_ops->mod = mod;
873
874 file_ops->id = ftrace_event_id_fops;
875 file_ops->id.owner = mod;
876
877 file_ops->enable = ftrace_enable_fops;
878 file_ops->enable.owner = mod;
879
880 file_ops->filter = ftrace_event_filter_fops;
881 file_ops->filter.owner = mod;
882
883 file_ops->format = ftrace_event_format_fops;
884 file_ops->format.owner = mod;
885
886 list_add(&file_ops->list, &ftrace_module_file_list);
887
888 return file_ops;
889}
890
836static void trace_module_add_events(struct module *mod) 891static void trace_module_add_events(struct module *mod)
837{ 892{
893 struct ftrace_module_file_ops *file_ops = NULL;
838 struct ftrace_event_call *call, *start, *end; 894 struct ftrace_event_call *call, *start, *end;
839 struct dentry *d_events; 895 struct dentry *d_events;
840 896
@@ -852,14 +908,27 @@ static void trace_module_add_events(struct module *mod)
852 /* The linker may leave blanks */ 908 /* The linker may leave blanks */
853 if (!call->name) 909 if (!call->name)
854 continue; 910 continue;
911
912 /*
913 * This module has events, create file ops for this module
914 * if not already done.
915 */
916 if (!file_ops) {
917 file_ops = trace_create_file_ops(mod);
918 if (!file_ops)
919 return;
920 }
855 call->mod = mod; 921 call->mod = mod;
856 list_add(&call->list, &ftrace_events); 922 list_add(&call->list, &ftrace_events);
857 event_create_dir(call, d_events); 923 event_create_dir(call, d_events,
924 &file_ops->id, &file_ops->enable,
925 &file_ops->filter, &file_ops->format);
858 } 926 }
859} 927}
860 928
861static void trace_module_remove_events(struct module *mod) 929static void trace_module_remove_events(struct module *mod)
862{ 930{
931 struct ftrace_module_file_ops *file_ops;
863 struct ftrace_event_call *call, *p; 932 struct ftrace_event_call *call, *p;
864 933
865 list_for_each_entry_safe(call, p, &ftrace_events, list) { 934 list_for_each_entry_safe(call, p, &ftrace_events, list) {
@@ -874,6 +943,16 @@ static void trace_module_remove_events(struct module *mod)
874 list_del(&call->list); 943 list_del(&call->list);
875 } 944 }
876 } 945 }
946
947 /* Now free the file_operations */
948 list_for_each_entry(file_ops, &ftrace_module_file_list, list) {
949 if (file_ops->mod == mod)
950 break;
951 }
952 if (&file_ops->list != &ftrace_module_file_list) {
953 list_del(&file_ops->list);
954 kfree(file_ops);
955 }
877} 956}
878 957
879static int trace_module_notify(struct notifier_block *self, 958static int trace_module_notify(struct notifier_block *self,
@@ -954,7 +1033,9 @@ static __init int event_trace_init(void)
954 if (!call->name) 1033 if (!call->name)
955 continue; 1034 continue;
956 list_add(&call->list, &ftrace_events); 1035 list_add(&call->list, &ftrace_events);
957 event_create_dir(call, d_events); 1036 event_create_dir(call, d_events, &ftrace_event_id_fops,
1037 &ftrace_enable_fops, &ftrace_event_filter_fops,
1038 &ftrace_event_format_fops);
958 } 1039 }
959 1040
960 ret = register_module_notifier(&trace_module_nb); 1041 ret = register_module_notifier(&trace_module_nb);