aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2015-01-21 10:01:39 -0500
committerSteven Rostedt <rostedt@goodmis.org>2015-02-03 12:48:43 -0500
commiteae473581cf93dad94ca833aa961c033c6a43924 (patch)
treeea0a8bbf8a30940b497dad43a858be8d1b5efb26 /kernel/trace
parentcc31004a4aa784d89054ec07b87eae05cecf7121 (diff)
tracing: Have mkdir and rmdir be part of tracefs
The tracing "instances" directory can create sub tracing buffers with mkdir, and remove them with rmdir. As a mkdir will also create all the files and directories that control the sub buffer the inode mutexes need to be released before this is done, to avoid deadlocks. It is better to let the tracing system unlock the inode mutexes before calling the functions that create the files within the new directory (or deletes the files from the one being destroyed). Now that tracing has been converted over to tracefs, the tracefs file system can be modified to accommodate this feature. It still releases the locks, but the filesystem itself can take care of the ugly business and let the user just do what it needs. The tracing system now attaches a descriptor to the directory dentry that can have userspace create or remove sub directories. If this descriptor does not exist for a dentry, then that dentry can not be used to create other directories. This descriptor holds a mkdir and rmdir method that only takes a character string as an argument. The tracefs file system will first make a copy of the dentry name before releasing the locks. Then it will pass the copied name to the methods. It is up to the tracing system that supplied the methods to handle races with duplicate names and such as all the inode mutexes would be released when the functions are called. Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c75
1 files changed, 5 insertions, 70 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b4aa936509d2..3c8913bac204 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6292,7 +6292,7 @@ static void free_trace_buffers(struct trace_array *tr)
6292#endif 6292#endif
6293} 6293}
6294 6294
6295static int new_instance_create(const char *name) 6295static int instance_mkdir(const char *name)
6296{ 6296{
6297 struct trace_array *tr; 6297 struct trace_array *tr;
6298 int ret; 6298 int ret;
@@ -6362,7 +6362,7 @@ static int new_instance_create(const char *name)
6362 6362
6363} 6363}
6364 6364
6365static int instance_delete(const char *name) 6365static int instance_rmdir(const char *name)
6366{ 6366{
6367 struct trace_array *tr; 6367 struct trace_array *tr;
6368 int found = 0; 6368 int found = 0;
@@ -6403,78 +6403,13 @@ static int instance_delete(const char *name)
6403 return ret; 6403 return ret;
6404} 6404}
6405 6405
6406static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t mode)
6407{
6408 struct dentry *parent;
6409 int ret;
6410
6411 /* Paranoid: Make sure the parent is the "instances" directory */
6412 parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
6413 if (WARN_ON_ONCE(parent != trace_instance_dir))
6414 return -ENOENT;
6415
6416 /*
6417 * The inode mutex is locked, but tracefs_create_dir() will also
6418 * take the mutex. As the instances directory can not be destroyed
6419 * or changed in any other way, it is safe to unlock it, and
6420 * let the dentry try. If two users try to make the same dir at
6421 * the same time, then the new_instance_create() will determine the
6422 * winner.
6423 */
6424 mutex_unlock(&inode->i_mutex);
6425
6426 ret = new_instance_create(dentry->d_iname);
6427
6428 mutex_lock(&inode->i_mutex);
6429
6430 return ret;
6431}
6432
6433static int instance_rmdir(struct inode *inode, struct dentry *dentry)
6434{
6435 struct dentry *parent;
6436 int ret;
6437
6438 /* Paranoid: Make sure the parent is the "instances" directory */
6439 parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
6440 if (WARN_ON_ONCE(parent != trace_instance_dir))
6441 return -ENOENT;
6442
6443 /* The caller did a dget() on dentry */
6444 mutex_unlock(&dentry->d_inode->i_mutex);
6445
6446 /*
6447 * The inode mutex is locked, but tracefs_create_dir() will also
6448 * take the mutex. As the instances directory can not be destroyed
6449 * or changed in any other way, it is safe to unlock it, and
6450 * let the dentry try. If two users try to make the same dir at
6451 * the same time, then the instance_delete() will determine the
6452 * winner.
6453 */
6454 mutex_unlock(&inode->i_mutex);
6455
6456 ret = instance_delete(dentry->d_iname);
6457
6458 mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
6459 mutex_lock(&dentry->d_inode->i_mutex);
6460
6461 return ret;
6462}
6463
6464static const struct inode_operations instance_dir_inode_operations = {
6465 .lookup = simple_lookup,
6466 .mkdir = instance_mkdir,
6467 .rmdir = instance_rmdir,
6468};
6469
6470static __init void create_trace_instances(struct dentry *d_tracer) 6406static __init void create_trace_instances(struct dentry *d_tracer)
6471{ 6407{
6472 trace_instance_dir = tracefs_create_dir("instances", d_tracer); 6408 trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer,
6409 instance_mkdir,
6410 instance_rmdir);
6473 if (WARN_ON(!trace_instance_dir)) 6411 if (WARN_ON(!trace_instance_dir))
6474 return; 6412 return;
6475
6476 /* Hijack the dir inode operations, to allow mkdir */
6477 trace_instance_dir->d_inode->i_op = &instance_dir_inode_operations;
6478} 6413}
6479 6414
6480static void 6415static void