aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 13:22:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 13:22:29 -0400
commit3f3c73de77b5598e9f87812ac4da9445090c3b4a (patch)
tree1b6ea5c10c273025c3d38dddda1975dc3d9a5070 /kernel/trace/trace.c
parent9497d7380b9c450830190c75aa43b25c278bb1f9 (diff)
parenteae473581cf93dad94ca833aa961c033c6a43924 (diff)
Merge tag 'trace-4.1-tracefs' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracefs from Steven Rostedt: "This adds the new tracefs file system. This has been in linux-next for more than one release, as I had it ready for the 4.0 merge window, but a last minute thing that needed to go into Linux first had to be done. That was that perf hard coded the file system number when reading /sys/kernel/debugfs/tracing directory making sure that the path had the debugfs mount # before it would parse the tracing file. This broke other use cases of perf, and the check is removed. Now when mounting /sys/kernel/debug, tracefs is automatically mounted in /sys/kernel/debug/tracing such that old tools will still see that path as expected. But now system admins can mount tracefs directly and not need to mount debugfs, which can expose security issues. A new directory is created when tracefs is configured such that system admins can now mount it separately (/sys/kernel/tracing)" * tag 'trace-4.1-tracefs' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing: Have mkdir and rmdir be part of tracefs tracefs: Add directory /sys/kernel/tracing tracing: Automatically mount tracefs on debugfs/tracing tracing: Convert the tracing facility over to use tracefs tracefs: Add new tracefs file system tracing: Create cmdline tracer options on tracing fs init tracing: Only create tracer options files if directory exists debugfs: Provide a file creation function that also takes an initial size
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c187
1 files changed, 88 insertions, 99 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 62c6506d663f..bcfa2add6dda 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -20,6 +20,7 @@
20#include <linux/notifier.h> 20#include <linux/notifier.h>
21#include <linux/irqflags.h> 21#include <linux/irqflags.h>
22#include <linux/debugfs.h> 22#include <linux/debugfs.h>
23#include <linux/tracefs.h>
23#include <linux/pagemap.h> 24#include <linux/pagemap.h>
24#include <linux/hardirq.h> 25#include <linux/hardirq.h>
25#include <linux/linkage.h> 26#include <linux/linkage.h>
@@ -31,6 +32,7 @@
31#include <linux/splice.h> 32#include <linux/splice.h>
32#include <linux/kdebug.h> 33#include <linux/kdebug.h>
33#include <linux/string.h> 34#include <linux/string.h>
35#include <linux/mount.h>
34#include <linux/rwsem.h> 36#include <linux/rwsem.h>
35#include <linux/slab.h> 37#include <linux/slab.h>
36#include <linux/ctype.h> 38#include <linux/ctype.h>
@@ -4105,9 +4107,24 @@ static void tracing_set_nop(struct trace_array *tr)
4105 tr->current_trace = &nop_trace; 4107 tr->current_trace = &nop_trace;
4106} 4108}
4107 4109
4108static int tracing_set_tracer(struct trace_array *tr, const char *buf) 4110static void update_tracer_options(struct trace_array *tr, struct tracer *t)
4109{ 4111{
4110 static struct trace_option_dentry *topts; 4112 static struct trace_option_dentry *topts;
4113
4114 /* Only enable if the directory has been created already. */
4115 if (!tr->dir)
4116 return;
4117
4118 /* Currently, only the top instance has options */
4119 if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL))
4120 return;
4121
4122 destroy_trace_option_files(topts);
4123 topts = create_trace_option_files(tr, t);
4124}
4125
4126static int tracing_set_tracer(struct trace_array *tr, const char *buf)
4127{
4111 struct tracer *t; 4128 struct tracer *t;
4112#ifdef CONFIG_TRACER_MAX_TRACE 4129#ifdef CONFIG_TRACER_MAX_TRACE
4113 bool had_max_tr; 4130 bool had_max_tr;
@@ -4172,11 +4189,7 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf)
4172 free_snapshot(tr); 4189 free_snapshot(tr);
4173 } 4190 }
4174#endif 4191#endif
4175 /* Currently, only the top instance has options */ 4192 update_tracer_options(tr, t);
4176 if (tr->flags & TRACE_ARRAY_FL_GLOBAL) {
4177 destroy_trace_option_files(topts);
4178 topts = create_trace_option_files(tr, t);
4179 }
4180 4193
4181#ifdef CONFIG_TRACER_MAX_TRACE 4194#ifdef CONFIG_TRACER_MAX_TRACE
4182 if (t->use_max_tr && !had_max_tr) { 4195 if (t->use_max_tr && !had_max_tr) {
@@ -5817,6 +5830,14 @@ static inline __init int register_snapshot_cmd(void) { return 0; }
5817 5830
5818static struct dentry *tracing_get_dentry(struct trace_array *tr) 5831static struct dentry *tracing_get_dentry(struct trace_array *tr)
5819{ 5832{
5833 if (WARN_ON(!tr->dir))
5834 return ERR_PTR(-ENODEV);
5835
5836 /* Top directory uses NULL as the parent */
5837 if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
5838 return NULL;
5839
5840 /* All sub buffers have a descriptor */
5820 return tr->dir; 5841 return tr->dir;
5821} 5842}
5822 5843
@@ -5831,10 +5852,10 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
5831 if (IS_ERR(d_tracer)) 5852 if (IS_ERR(d_tracer))
5832 return NULL; 5853 return NULL;
5833 5854
5834 tr->percpu_dir = debugfs_create_dir("per_cpu", d_tracer); 5855 tr->percpu_dir = tracefs_create_dir("per_cpu", d_tracer);
5835 5856
5836 WARN_ONCE(!tr->percpu_dir, 5857 WARN_ONCE(!tr->percpu_dir,
5837 "Could not create debugfs directory 'per_cpu/%d'\n", cpu); 5858 "Could not create tracefs directory 'per_cpu/%d'\n", cpu);
5838 5859
5839 return tr->percpu_dir; 5860 return tr->percpu_dir;
5840} 5861}
@@ -5851,7 +5872,7 @@ trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
5851} 5872}
5852 5873
5853static void 5874static void
5854tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) 5875tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
5855{ 5876{
5856 struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu); 5877 struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
5857 struct dentry *d_cpu; 5878 struct dentry *d_cpu;
@@ -5861,9 +5882,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
5861 return; 5882 return;
5862 5883
5863 snprintf(cpu_dir, 30, "cpu%ld", cpu); 5884 snprintf(cpu_dir, 30, "cpu%ld", cpu);
5864 d_cpu = debugfs_create_dir(cpu_dir, d_percpu); 5885 d_cpu = tracefs_create_dir(cpu_dir, d_percpu);
5865 if (!d_cpu) { 5886 if (!d_cpu) {
5866 pr_warning("Could not create debugfs '%s' entry\n", cpu_dir); 5887 pr_warning("Could not create tracefs '%s' entry\n", cpu_dir);
5867 return; 5888 return;
5868 } 5889 }
5869 5890
@@ -6015,9 +6036,9 @@ struct dentry *trace_create_file(const char *name,
6015{ 6036{
6016 struct dentry *ret; 6037 struct dentry *ret;
6017 6038
6018 ret = debugfs_create_file(name, mode, parent, data, fops); 6039 ret = tracefs_create_file(name, mode, parent, data, fops);
6019 if (!ret) 6040 if (!ret)
6020 pr_warning("Could not create debugfs '%s' entry\n", name); 6041 pr_warning("Could not create tracefs '%s' entry\n", name);
6021 6042
6022 return ret; 6043 return ret;
6023} 6044}
@@ -6034,9 +6055,9 @@ static struct dentry *trace_options_init_dentry(struct trace_array *tr)
6034 if (IS_ERR(d_tracer)) 6055 if (IS_ERR(d_tracer))
6035 return NULL; 6056 return NULL;
6036 6057
6037 tr->options = debugfs_create_dir("options", d_tracer); 6058 tr->options = tracefs_create_dir("options", d_tracer);
6038 if (!tr->options) { 6059 if (!tr->options) {
6039 pr_warning("Could not create debugfs directory 'options'\n"); 6060 pr_warning("Could not create tracefs directory 'options'\n");
6040 return NULL; 6061 return NULL;
6041 } 6062 }
6042 6063
@@ -6105,7 +6126,7 @@ destroy_trace_option_files(struct trace_option_dentry *topts)
6105 return; 6126 return;
6106 6127
6107 for (cnt = 0; topts[cnt].opt; cnt++) 6128 for (cnt = 0; topts[cnt].opt; cnt++)
6108 debugfs_remove(topts[cnt].entry); 6129 tracefs_remove(topts[cnt].entry);
6109 6130
6110 kfree(topts); 6131 kfree(topts);
6111} 6132}
@@ -6194,7 +6215,7 @@ static const struct file_operations rb_simple_fops = {
6194struct dentry *trace_instance_dir; 6215struct dentry *trace_instance_dir;
6195 6216
6196static void 6217static void
6197init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer); 6218init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer);
6198 6219
6199static int 6220static int
6200allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size) 6221allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size)
@@ -6271,7 +6292,7 @@ static void free_trace_buffers(struct trace_array *tr)
6271#endif 6292#endif
6272} 6293}
6273 6294
6274static int new_instance_create(const char *name) 6295static int instance_mkdir(const char *name)
6275{ 6296{
6276 struct trace_array *tr; 6297 struct trace_array *tr;
6277 int ret; 6298 int ret;
@@ -6310,17 +6331,17 @@ static int new_instance_create(const char *name)
6310 if (allocate_trace_buffers(tr, trace_buf_size) < 0) 6331 if (allocate_trace_buffers(tr, trace_buf_size) < 0)
6311 goto out_free_tr; 6332 goto out_free_tr;
6312 6333
6313 tr->dir = debugfs_create_dir(name, trace_instance_dir); 6334 tr->dir = tracefs_create_dir(name, trace_instance_dir);
6314 if (!tr->dir) 6335 if (!tr->dir)
6315 goto out_free_tr; 6336 goto out_free_tr;
6316 6337
6317 ret = event_trace_add_tracer(tr->dir, tr); 6338 ret = event_trace_add_tracer(tr->dir, tr);
6318 if (ret) { 6339 if (ret) {
6319 debugfs_remove_recursive(tr->dir); 6340 tracefs_remove_recursive(tr->dir);
6320 goto out_free_tr; 6341 goto out_free_tr;
6321 } 6342 }
6322 6343
6323 init_tracer_debugfs(tr, tr->dir); 6344 init_tracer_tracefs(tr, tr->dir);
6324 6345
6325 list_add(&tr->list, &ftrace_trace_arrays); 6346 list_add(&tr->list, &ftrace_trace_arrays);
6326 6347
@@ -6341,7 +6362,7 @@ static int new_instance_create(const char *name)
6341 6362
6342} 6363}
6343 6364
6344static int instance_delete(const char *name) 6365static int instance_rmdir(const char *name)
6345{ 6366{
6346 struct trace_array *tr; 6367 struct trace_array *tr;
6347 int found = 0; 6368 int found = 0;
@@ -6382,82 +6403,17 @@ static int instance_delete(const char *name)
6382 return ret; 6403 return ret;
6383} 6404}
6384 6405
6385static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t mode)
6386{
6387 struct dentry *parent;
6388 int ret;
6389
6390 /* Paranoid: Make sure the parent is the "instances" directory */
6391 parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
6392 if (WARN_ON_ONCE(parent != trace_instance_dir))
6393 return -ENOENT;
6394
6395 /*
6396 * The inode mutex is locked, but debugfs_create_dir() will also
6397 * take the mutex. As the instances directory can not be destroyed
6398 * or changed in any other way, it is safe to unlock it, and
6399 * let the dentry try. If two users try to make the same dir at
6400 * the same time, then the new_instance_create() will determine the
6401 * winner.
6402 */
6403 mutex_unlock(&inode->i_mutex);
6404
6405 ret = new_instance_create(dentry->d_iname);
6406
6407 mutex_lock(&inode->i_mutex);
6408
6409 return ret;
6410}
6411
6412static int instance_rmdir(struct inode *inode, struct dentry *dentry)
6413{
6414 struct dentry *parent;
6415 int ret;
6416
6417 /* Paranoid: Make sure the parent is the "instances" directory */
6418 parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
6419 if (WARN_ON_ONCE(parent != trace_instance_dir))
6420 return -ENOENT;
6421
6422 /* The caller did a dget() on dentry */
6423 mutex_unlock(&dentry->d_inode->i_mutex);
6424
6425 /*
6426 * The inode mutex is locked, but debugfs_create_dir() will also
6427 * take the mutex. As the instances directory can not be destroyed
6428 * or changed in any other way, it is safe to unlock it, and
6429 * let the dentry try. If two users try to make the same dir at
6430 * the same time, then the instance_delete() will determine the
6431 * winner.
6432 */
6433 mutex_unlock(&inode->i_mutex);
6434
6435 ret = instance_delete(dentry->d_iname);
6436
6437 mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
6438 mutex_lock(&dentry->d_inode->i_mutex);
6439
6440 return ret;
6441}
6442
6443static const struct inode_operations instance_dir_inode_operations = {
6444 .lookup = simple_lookup,
6445 .mkdir = instance_mkdir,
6446 .rmdir = instance_rmdir,
6447};
6448
6449static __init void create_trace_instances(struct dentry *d_tracer) 6406static __init void create_trace_instances(struct dentry *d_tracer)
6450{ 6407{
6451 trace_instance_dir = debugfs_create_dir("instances", d_tracer); 6408 trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer,
6409 instance_mkdir,
6410 instance_rmdir);
6452 if (WARN_ON(!trace_instance_dir)) 6411 if (WARN_ON(!trace_instance_dir))
6453 return; 6412 return;
6454
6455 /* Hijack the dir inode operations, to allow mkdir */
6456 trace_instance_dir->d_inode->i_op = &instance_dir_inode_operations;
6457} 6413}
6458 6414
6459static void 6415static void
6460init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) 6416init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
6461{ 6417{
6462 int cpu; 6418 int cpu;
6463 6419
@@ -6511,10 +6467,32 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
6511#endif 6467#endif
6512 6468
6513 for_each_tracing_cpu(cpu) 6469 for_each_tracing_cpu(cpu)
6514 tracing_init_debugfs_percpu(tr, cpu); 6470 tracing_init_tracefs_percpu(tr, cpu);
6515 6471
6516} 6472}
6517 6473
6474static struct vfsmount *trace_automount(void *ingore)
6475{
6476 struct vfsmount *mnt;
6477 struct file_system_type *type;
6478
6479 /*
6480 * To maintain backward compatibility for tools that mount
6481 * debugfs to get to the tracing facility, tracefs is automatically
6482 * mounted to the debugfs/tracing directory.
6483 */
6484 type = get_fs_type("tracefs");
6485 if (!type)
6486 return NULL;
6487 mnt = vfs_kern_mount(type, 0, "tracefs", NULL);
6488 put_filesystem(type);
6489 if (IS_ERR(mnt))
6490 return NULL;
6491 mntget(mnt);
6492
6493 return mnt;
6494}
6495
6518/** 6496/**
6519 * tracing_init_dentry - initialize top level trace array 6497 * tracing_init_dentry - initialize top level trace array
6520 * 6498 *
@@ -6526,23 +6504,30 @@ struct dentry *tracing_init_dentry(void)
6526{ 6504{
6527 struct trace_array *tr = &global_trace; 6505 struct trace_array *tr = &global_trace;
6528 6506
6507 /* The top level trace array uses NULL as parent */
6529 if (tr->dir) 6508 if (tr->dir)
6530 return tr->dir; 6509 return NULL;
6531 6510
6532 if (WARN_ON(!debugfs_initialized())) 6511 if (WARN_ON(!debugfs_initialized()))
6533 return ERR_PTR(-ENODEV); 6512 return ERR_PTR(-ENODEV);
6534 6513
6535 tr->dir = debugfs_create_dir("tracing", NULL); 6514 /*
6536 6515 * As there may still be users that expect the tracing
6516 * files to exist in debugfs/tracing, we must automount
6517 * the tracefs file system there, so older tools still
6518 * work with the newer kerenl.
6519 */
6520 tr->dir = debugfs_create_automount("tracing", NULL,
6521 trace_automount, NULL);
6537 if (!tr->dir) { 6522 if (!tr->dir) {
6538 pr_warn_once("Could not create debugfs directory 'tracing'\n"); 6523 pr_warn_once("Could not create debugfs directory 'tracing'\n");
6539 return ERR_PTR(-ENOMEM); 6524 return ERR_PTR(-ENOMEM);
6540 } 6525 }
6541 6526
6542 return tr->dir; 6527 return NULL;
6543} 6528}
6544 6529
6545static __init int tracer_init_debugfs(void) 6530static __init int tracer_init_tracefs(void)
6546{ 6531{
6547 struct dentry *d_tracer; 6532 struct dentry *d_tracer;
6548 6533
@@ -6552,7 +6537,7 @@ static __init int tracer_init_debugfs(void)
6552 if (IS_ERR(d_tracer)) 6537 if (IS_ERR(d_tracer))
6553 return 0; 6538 return 0;
6554 6539
6555 init_tracer_debugfs(&global_trace, d_tracer); 6540 init_tracer_tracefs(&global_trace, d_tracer);
6556 6541
6557 trace_create_file("tracing_thresh", 0644, d_tracer, 6542 trace_create_file("tracing_thresh", 0644, d_tracer,
6558 &global_trace, &tracing_thresh_fops); 6543 &global_trace, &tracing_thresh_fops);
@@ -6575,6 +6560,10 @@ static __init int tracer_init_debugfs(void)
6575 6560
6576 create_trace_options_dir(&global_trace); 6561 create_trace_options_dir(&global_trace);
6577 6562
6563 /* If the tracer was started via cmdline, create options for it here */
6564 if (global_trace.current_trace != &nop_trace)
6565 update_tracer_options(&global_trace, global_trace.current_trace);
6566
6578 return 0; 6567 return 0;
6579} 6568}
6580 6569
@@ -6910,5 +6899,5 @@ __init static int clear_boot_tracer(void)
6910 return 0; 6899 return 0;
6911} 6900}
6912 6901
6913fs_initcall(tracer_init_debugfs); 6902fs_initcall(tracer_init_tracefs);
6914late_initcall(clear_boot_tracer); 6903late_initcall(clear_boot_tracer);