diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r-- | kernel/trace/trace_events.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 32b9895af239..6dfd48b5d1c0 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -413,6 +413,35 @@ static void put_system(struct ftrace_subsystem_dir *dir) | |||
413 | } | 413 | } |
414 | 414 | ||
415 | /* | 415 | /* |
416 | * Open and update trace_array ref count. | ||
417 | * Must have the current trace_array passed to it. | ||
418 | */ | ||
419 | static int tracing_open_generic_file(struct inode *inode, struct file *filp) | ||
420 | { | ||
421 | struct ftrace_event_file *file = inode->i_private; | ||
422 | struct trace_array *tr = file->tr; | ||
423 | int ret; | ||
424 | |||
425 | if (trace_array_get(tr) < 0) | ||
426 | return -ENODEV; | ||
427 | |||
428 | ret = tracing_open_generic(inode, filp); | ||
429 | if (ret < 0) | ||
430 | trace_array_put(tr); | ||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | static int tracing_release_generic_file(struct inode *inode, struct file *filp) | ||
435 | { | ||
436 | struct ftrace_event_file *file = inode->i_private; | ||
437 | struct trace_array *tr = file->tr; | ||
438 | |||
439 | trace_array_put(tr); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /* | ||
416 | * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. | 445 | * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. |
417 | */ | 446 | */ |
418 | static int | 447 | static int |
@@ -1046,9 +1075,17 @@ static int subsystem_open(struct inode *inode, struct file *filp) | |||
1046 | /* Some versions of gcc think dir can be uninitialized here */ | 1075 | /* Some versions of gcc think dir can be uninitialized here */ |
1047 | WARN_ON(!dir); | 1076 | WARN_ON(!dir); |
1048 | 1077 | ||
1078 | /* Still need to increment the ref count of the system */ | ||
1079 | if (trace_array_get(tr) < 0) { | ||
1080 | put_system(dir); | ||
1081 | return -ENODEV; | ||
1082 | } | ||
1083 | |||
1049 | ret = tracing_open_generic(inode, filp); | 1084 | ret = tracing_open_generic(inode, filp); |
1050 | if (ret < 0) | 1085 | if (ret < 0) { |
1086 | trace_array_put(tr); | ||
1051 | put_system(dir); | 1087 | put_system(dir); |
1088 | } | ||
1052 | 1089 | ||
1053 | return ret; | 1090 | return ret; |
1054 | } | 1091 | } |
@@ -1059,16 +1096,23 @@ static int system_tr_open(struct inode *inode, struct file *filp) | |||
1059 | struct trace_array *tr = inode->i_private; | 1096 | struct trace_array *tr = inode->i_private; |
1060 | int ret; | 1097 | int ret; |
1061 | 1098 | ||
1099 | if (trace_array_get(tr) < 0) | ||
1100 | return -ENODEV; | ||
1101 | |||
1062 | /* Make a temporary dir that has no system but points to tr */ | 1102 | /* Make a temporary dir that has no system but points to tr */ |
1063 | dir = kzalloc(sizeof(*dir), GFP_KERNEL); | 1103 | dir = kzalloc(sizeof(*dir), GFP_KERNEL); |
1064 | if (!dir) | 1104 | if (!dir) { |
1105 | trace_array_put(tr); | ||
1065 | return -ENOMEM; | 1106 | return -ENOMEM; |
1107 | } | ||
1066 | 1108 | ||
1067 | dir->tr = tr; | 1109 | dir->tr = tr; |
1068 | 1110 | ||
1069 | ret = tracing_open_generic(inode, filp); | 1111 | ret = tracing_open_generic(inode, filp); |
1070 | if (ret < 0) | 1112 | if (ret < 0) { |
1113 | trace_array_put(tr); | ||
1071 | kfree(dir); | 1114 | kfree(dir); |
1115 | } | ||
1072 | 1116 | ||
1073 | filp->private_data = dir; | 1117 | filp->private_data = dir; |
1074 | 1118 | ||
@@ -1079,6 +1123,8 @@ static int subsystem_release(struct inode *inode, struct file *file) | |||
1079 | { | 1123 | { |
1080 | struct ftrace_subsystem_dir *dir = file->private_data; | 1124 | struct ftrace_subsystem_dir *dir = file->private_data; |
1081 | 1125 | ||
1126 | trace_array_put(dir->tr); | ||
1127 | |||
1082 | /* | 1128 | /* |
1083 | * If dir->subsystem is NULL, then this is a temporary | 1129 | * If dir->subsystem is NULL, then this is a temporary |
1084 | * descriptor that was made for a trace_array to enable | 1130 | * descriptor that was made for a trace_array to enable |
@@ -1206,9 +1252,10 @@ static const struct file_operations ftrace_set_event_fops = { | |||
1206 | }; | 1252 | }; |
1207 | 1253 | ||
1208 | static const struct file_operations ftrace_enable_fops = { | 1254 | static const struct file_operations ftrace_enable_fops = { |
1209 | .open = tracing_open_generic, | 1255 | .open = tracing_open_generic_file, |
1210 | .read = event_enable_read, | 1256 | .read = event_enable_read, |
1211 | .write = event_enable_write, | 1257 | .write = event_enable_write, |
1258 | .release = tracing_release_generic_file, | ||
1212 | .llseek = default_llseek, | 1259 | .llseek = default_llseek, |
1213 | }; | 1260 | }; |
1214 | 1261 | ||