diff --git a/block/blk-debugfs.c b/block/blk-debugfs.c
index 19091e1effc0..a0f4077d6959 100644
--- a/block/blk-debugfs.c
+++ b/block/blk-debugfs.c
@@ -13,3 +13,32 @@ void blk_debugfs_register(void)
 {
 	blk_debugfs_root = debugfs_create_dir("block", NULL);
 }
+
+static struct dentry *blk_debugfs_dir_register(const char *name)
+{
+	return debugfs_create_dir(name, blk_debugfs_root);
+}
+
+void blk_queue_debugfs_register(struct request_queue *q, const char *name)
+{
+	q->debugfs_dir = blk_debugfs_dir_register(name);
+}
+EXPORT_SYMBOL_GPL(blk_queue_debugfs_register);
+
+void blk_queue_debugfs_unregister(struct request_queue *q)
+{
+	debugfs_remove_recursive(q->debugfs_dir);
+	q->debugfs_dir = NULL;
+}
+EXPORT_SYMBOL_GPL(blk_queue_debugfs_unregister);
+
+void blk_part_debugfs_register(struct hd_struct *p, const char *name)
+{
+	p->debugfs_dir = blk_debugfs_dir_register(name);
+}
+
+void blk_part_debugfs_unregister(struct hd_struct *p)
+{
+	debugfs_remove_recursive(p->debugfs_dir);
+	p->debugfs_dir = NULL;
+}
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 96b7a35c898a..08edc3a54114 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -822,9 +822,6 @@ void blk_mq_debugfs_register(struct request_queue *q)
 	struct blk_mq_hw_ctx *hctx;
 	int i;
 
-	q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent),
-					    blk_debugfs_root);
-
 	debugfs_create_files(q->debugfs_dir, q, blk_mq_debugfs_queue_attrs);
 
 	/*
@@ -855,9 +852,7 @@ void blk_mq_debugfs_register(struct request_queue *q)
 
 void blk_mq_debugfs_unregister(struct request_queue *q)
 {
-	debugfs_remove_recursive(q->debugfs_dir);
 	q->sched_debugfs_dir = NULL;
-	q->debugfs_dir = NULL;
 }
 
 static void blk_mq_debugfs_register_ctx(struct blk_mq_hw_ctx *hctx,
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index eda8c4985511..f758a7e06671 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -905,6 +905,7 @@ static void blk_release_queue(struct kobject *kobj)
 
 	blk_trace_shutdown(q);
 
+	blk_queue_debugfs_unregister(q);
 	if (queue_is_mq(q))
 		blk_mq_debugfs_unregister(q);
 
@@ -976,6 +977,8 @@ int blk_register_queue(struct gendisk *disk)
 		goto unlock;
 	}
 
+	blk_queue_debugfs_register(q, kobject_name(q->kobj.parent));
+
 	if (queue_is_mq(q)) {
 		__blk_mq_register_dev(dev, q);
 		blk_mq_debugfs_register(q);
@@ -986,6 +989,7 @@ int blk_register_queue(struct gendisk *disk)
 		ret = elv_register_queue(q, false);
 		if (ret) {
 			mutex_unlock(&q->sysfs_lock);
+			blk_queue_debugfs_unregister(q);
 			mutex_unlock(&q->sysfs_dir_lock);
 			kobject_del(&q->kobj);
 			blk_trace_remove_sysfs(dev);
diff --git a/block/blk.h b/block/blk.h
index ec16e8a6049e..46d867a7f5bc 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -458,10 +458,21 @@ int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 		bool *same_page);
 #ifdef CONFIG_DEBUG_FS
 void blk_debugfs_register(void);
+void blk_part_debugfs_register(struct hd_struct *p, const char *name);
+void blk_part_debugfs_unregister(struct hd_struct *p);
 #else
 static inline void blk_debugfs_register(void)
 {
 }
+
+static inline void blk_part_debugfs_register(struct hd_struct *p,
+					     const char *name)
+{
+}
+
+static inline void blk_part_debugfs_unregister(struct hd_struct *p)
+{
+}
 #endif /* CONFIG_DEBUG_FS */
 
 #endif /* BLK_INTERNAL_H */
diff --git a/block/partitions/core.c b/block/partitions/core.c
index c085bf85509b..ae395b3ec9cc 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -312,6 +312,7 @@ void delete_partition(struct gendisk *disk, struct hd_struct *part)
 	rcu_assign_pointer(ptbl->part[part->partno], NULL);
 	rcu_assign_pointer(ptbl->last_lookup, NULL);
 	kobject_put(part->holder_dir);
+	blk_part_debugfs_unregister(part);
 	device_del(part_to_dev(part));
 
 	/*
@@ -433,6 +434,8 @@ static struct hd_struct *add_partition(struct gendisk *disk, int partno,
 	if (!p->holder_dir)
 		goto out_del;
 
+	blk_part_debugfs_register(p, dev_name(pdev));
+
 	dev_set_uevent_suppress(pdev, 0);
 	if (flags & ADDPART_FLAG_WHOLEDISK) {
 		err = device_create_file(pdev, &dev_attr_whole_disk);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 20472aaaf630..f21787611918 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1548,6 +1548,7 @@ sg_add_device(struct device *cl_dev, struct class_interface *cl_intf)
 		goto out;
 	}
 
+	blk_queue_debugfs_register(sdp->device->request_queue, disk->disk_name);
 	error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1);
 	if (error)
 		goto cdev_add_err;
@@ -1644,6 +1645,7 @@ sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf)
 
 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
 	device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
+	blk_queue_debugfs_unregister(sdp->device->request_queue);
 	cdev_del(sdp->cdev);
 	sdp->cdev = NULL;
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3122a93c7277..e7edd31bdf9a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -561,8 +561,11 @@ struct request_queue {
 	struct list_head	tag_set_list;
 	struct bio_set		bio_split;
 
-#ifdef CONFIG_BLK_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
+	/* Used by block/blk-*debugfs.c and kernel/trace/blktrace.c */
 	struct dentry		*debugfs_dir;
+#endif
+#ifdef CONFIG_BLK_DEBUG_FS
 	struct dentry		*sched_debugfs_dir;
 	struct dentry		*rqos_debugfs_dir;
 #endif
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 3b6ff5902edc..eb6db276e293 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -22,7 +22,6 @@ struct blk_trace {
 	u64 end_lba;
 	u32 pid;
 	u32 dev;
-	struct dentry *dir;
 	struct dentry *dropped_file;
 	struct dentry *msg_file;
 	struct list_head running_list;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 058d895544c7..899760cf8c37 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -86,6 +86,10 @@ struct hd_struct {
 #endif
 	struct percpu_ref ref;
 	struct rcu_work rcu_work;
+#ifdef CONFIG_DEBUG_FS
+	/* Currently only used by kernel/trace/blktrace.c */
+	struct dentry *debugfs_dir;
+#endif
 };
 
 /**
@@ -382,4 +386,18 @@ static inline dev_t blk_lookup_devt(const char *name, int partno)
 }
 #endif /* CONFIG_BLOCK */
 
+#ifdef CONFIG_DEBUG_FS
+void blk_queue_debugfs_register(struct request_queue *q, const char *name);
+void blk_queue_debugfs_unregister(struct request_queue *q);
+#else
+static inline void blk_queue_debugfs_register(struct request_queue *q,
+					      const char *name)
+{
+}
+
+static inline void blk_queue_debugfs_unregister(struct request_queue *q)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
 #endif /* _LINUX_GENHD_H */
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 2c6e6c386ace..5c52976bd762 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
  *
  */
+
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/blktrace_api.h>
@@ -311,7 +312,6 @@ static void blk_trace_free(struct blk_trace *bt)
 	debugfs_remove(bt->msg_file);
 	debugfs_remove(bt->dropped_file);
 	relay_close(bt->rchan);
-	debugfs_remove(bt->dir);
 	free_percpu(bt->sequence);
 	free_percpu(bt->msg_data);
 	kfree(bt);
@@ -468,16 +468,25 @@ static void blk_trace_setup_lba(struct blk_trace *bt,
 	}
 }
 
-static struct dentry *blk_trace_debugfs_dir(struct blk_user_trace_setup *buts,
-					    struct blk_trace *bt)
+static struct dentry *blk_trace_debugfs_dir(struct block_device *bdev,
+					    struct request_queue *q)
 {
-	struct dentry *dir = NULL;
+	struct hd_struct *p = NULL;
 
-	dir = debugfs_lookup(buts->name, blk_debugfs_root);
-	if (!dir)
-		bt->dir = dir = debugfs_create_dir(buts->name, blk_debugfs_root);
+	/*
+	 * Some drivers like scsi-generic use a NULL block device. For
+	 * other drivers when bdev != bdev->bd_contain we are doing a blktrace
+	 * on a parition, otherwise we know we are working on the whole
+	 * disk, and for that the request_queue already has its own debugfs_dir.
+	 * which we have been using for other things other than blktrace.
+	 */
+	if (bdev && bdev != bdev->bd_contains)
+		p = bdev->bd_part;
 
-	return dir;
+	if (p)
+		return p->debugfs_dir;
+
+	return q->debugfs_dir;
 }
 
 /*
@@ -491,6 +500,7 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
 	struct dentry *dir = NULL;
 	int ret;
 
+
 	if (!buts->buf_size || !buts->buf_nr)
 		return -EINVAL;
 
@@ -521,7 +531,9 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
 
 	ret = -ENOENT;
 
-	dir = blk_trace_debugfs_dir(buts, bt);
+	dir = blk_trace_debugfs_dir(bdev, q);
+	if (WARN_ON(!dir))
+		goto err;
 
 	bt->dev = dev;
 	atomic_set(&bt->dropped, 0);
@@ -561,8 +573,6 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
 
 	ret = 0;
 err:
-	if (dir && !bt->dir)
-		dput(dir);
 	if (ret)
 		blk_trace_free(bt);
 	return ret;
