Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f48fc4d3 authored by Jens Axboe's avatar Jens Axboe
Browse files

block: get rid of the manual directory counting in blktrace



It can result in a stuck blktrace system, if --kill is used.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 32231638
Loading
Loading
Loading
Loading
+21 −51
Original line number Diff line number Diff line
@@ -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 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
	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);