|
@@ -187,59 +187,12 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
|
|
|
|
|
|
static struct dentry *blk_tree_root;
|
|
|
static DEFINE_MUTEX(blk_tree_mutex);
|
|
|
-static unsigned int root_users;
|
|
|
-
|
|
|
-static inline void blk_remove_root(void)
|
|
|
-{
|
|
|
- if (blk_tree_root) {
|
|
|
- debugfs_remove(blk_tree_root);
|
|
|
- blk_tree_root = NULL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void blk_remove_tree(struct dentry *dir)
|
|
|
-{
|
|
|
- mutex_lock(&blk_tree_mutex);
|
|
|
- debugfs_remove(dir);
|
|
|
- if (--root_users == 0)
|
|
|
- blk_remove_root();
|
|
|
- mutex_unlock(&blk_tree_mutex);
|
|
|
-}
|
|
|
-
|
|
|
-static struct dentry *blk_create_tree(const char *blk_name)
|
|
|
-{
|
|
|
- struct dentry *dir = NULL;
|
|
|
- int created = 0;
|
|
|
-
|
|
|
- mutex_lock(&blk_tree_mutex);
|
|
|
-
|
|
|
- if (!blk_tree_root) {
|
|
|
- blk_tree_root = debugfs_create_dir("block", NULL);
|
|
|
- if (!blk_tree_root)
|
|
|
- goto err;
|
|
|
- created = 1;
|
|
|
- }
|
|
|
-
|
|
|
- dir = debugfs_create_dir(blk_name, blk_tree_root);
|
|
|
- if (dir)
|
|
|
- root_users++;
|
|
|
- else {
|
|
|
- /* Delete root only if we created it */
|
|
|
- if (created)
|
|
|
- blk_remove_root();
|
|
|
- }
|
|
|
-
|
|
|
-err:
|
|
|
- mutex_unlock(&blk_tree_mutex);
|
|
|
- return dir;
|
|
|
-}
|
|
|
|
|
|
static void blk_trace_cleanup(struct blk_trace *bt)
|
|
|
{
|
|
|
- relay_close(bt->rchan);
|
|
|
debugfs_remove(bt->msg_file);
|
|
|
debugfs_remove(bt->dropped_file);
|
|
|
- blk_remove_tree(bt->dir);
|
|
|
+ relay_close(bt->rchan);
|
|
|
free_percpu(bt->sequence);
|
|
|
free_percpu(bt->msg_data);
|
|
|
kfree(bt);
|
|
@@ -346,7 +299,18 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
|
|
|
|
|
|
static int blk_remove_buf_file_callback(struct dentry *dentry)
|
|
|
{
|
|
|
+ struct dentry *parent = dentry->d_parent;
|
|
|
debugfs_remove(dentry);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * this will fail for all but the last file, but that is ok. what we
|
|
|
+ * care about is the top level buts->name directory going away, when
|
|
|
+ * the last trace file is gone. Then we don't have to rmdir() that
|
|
|
+ * manually on trace stop, so it nicely solves the issue with
|
|
|
+ * force killing of running traces.
|
|
|
+ */
|
|
|
+
|
|
|
+ debugfs_remove(parent);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -404,7 +368,15 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
|
|
|
goto err;
|
|
|
|
|
|
ret = -ENOENT;
|
|
|
- dir = blk_create_tree(buts->name);
|
|
|
+
|
|
|
+ if (!blk_tree_root) {
|
|
|
+ blk_tree_root = debugfs_create_dir("block", NULL);
|
|
|
+ if (!blk_tree_root)
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ dir = debugfs_create_dir(buts->name, blk_tree_root);
|
|
|
+
|
|
|
if (!dir)
|
|
|
goto err;
|
|
|
|
|
@@ -458,8 +430,6 @@ probe_err:
|
|
|
atomic_dec(&blk_probes_ref);
|
|
|
mutex_unlock(&blk_probe_mutex);
|
|
|
err:
|
|
|
- if (dir)
|
|
|
- blk_remove_tree(dir);
|
|
|
if (bt) {
|
|
|
if (bt->msg_file)
|
|
|
debugfs_remove(bt->msg_file);
|