|
@@ -5192,6 +5192,42 @@ static int new_instance_create(const char *name)
|
|
|
|
|
|
}
|
|
|
|
|
|
+static int instance_delete(const char *name)
|
|
|
+{
|
|
|
+ struct trace_array *tr;
|
|
|
+ int found = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock(&trace_types_lock);
|
|
|
+
|
|
|
+ ret = -ENODEV;
|
|
|
+ list_for_each_entry(tr, &ftrace_trace_arrays, list) {
|
|
|
+ if (tr->name && strcmp(tr->name, name) == 0) {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!found)
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
+ list_del(&tr->list);
|
|
|
+
|
|
|
+ event_trace_del_tracer(tr);
|
|
|
+ debugfs_remove_recursive(tr->dir);
|
|
|
+ free_percpu(tr->data);
|
|
|
+ ring_buffer_free(tr->buffer);
|
|
|
+
|
|
|
+ kfree(tr->name);
|
|
|
+ kfree(tr);
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+
|
|
|
+ out_unlock:
|
|
|
+ mutex_unlock(&trace_types_lock);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t mode)
|
|
|
{
|
|
|
struct dentry *parent;
|
|
@@ -5219,9 +5255,41 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int instance_rmdir(struct inode *inode, struct dentry *dentry)
|
|
|
+{
|
|
|
+ struct dentry *parent;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* Paranoid: Make sure the parent is the "instances" directory */
|
|
|
+ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
|
|
|
+ if (WARN_ON_ONCE(parent != trace_instance_dir))
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ /* The caller did a dget() on dentry */
|
|
|
+ mutex_unlock(&dentry->d_inode->i_mutex);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The inode mutex is locked, but debugfs_create_dir() will also
|
|
|
+ * take the mutex. As the instances directory can not be destroyed
|
|
|
+ * or changed in any other way, it is safe to unlock it, and
|
|
|
+ * let the dentry try. If two users try to make the same dir at
|
|
|
+ * the same time, then the instance_delete() will determine the
|
|
|
+ * winner.
|
|
|
+ */
|
|
|
+ mutex_unlock(&inode->i_mutex);
|
|
|
+
|
|
|
+ ret = instance_delete(dentry->d_iname);
|
|
|
+
|
|
|
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
|
|
|
+ mutex_lock(&dentry->d_inode->i_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static const struct inode_operations instance_dir_inode_operations = {
|
|
|
.lookup = simple_lookup,
|
|
|
.mkdir = instance_mkdir,
|
|
|
+ .rmdir = instance_rmdir,
|
|
|
};
|
|
|
|
|
|
static __init void create_trace_instances(struct dentry *d_tracer)
|