block: get rid of the manual directory counting in blktrace
authorJens Axboe <jens.axboe@oracle.com>
Mon, 5 Jan 2009 09:17:25 +0000 (10:17 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 30 Jan 2009 11:34:36 +0000 (12:34 +0100)
It can result in a stuck blktrace system, if --kill is used.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
block/blktrace.c

index b0a2cae886dbdc4dde9a2efa99345ea2462a54b0..39cc3bfe56e41055793a804e1461dad39045b264 100644 (file)
@@ -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);