From ca41f3f2ebeb2555ce18393f6ef98629b63a80db Mon Sep 17 00:00:00 2001
From: Robert Baldyga <robert.baldyga@intel.com>
Date: Wed, 1 Jun 2016 11:00:47 +0200
Subject: [DEBUG] drivers: md: dm: add error injection

This patch adds error injection mechanism using debugfs.
It allows to fail few BIO's for debug purposes.

Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
---
 drivers/md/dm.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 1b2f962..15a70a2 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -25,6 +25,7 @@
 #include <linux/elevator.h> /* for rq_end_sector() */
 #include <linux/blk-mq.h>
 #include <linux/pr.h>
+#include <linux/debugfs.h>
 
 #include <trace/events/block.h>
 
@@ -415,8 +416,47 @@ static void local_exit(void)
 	DMINFO("cleaned up");
 }
 
+static struct dentry *dbgfs_root;
+static u32 dbg_error_counter = 0;
+static u32 dbg_error_max = 1;
+static u32 dbg_error = 0;
+
+static int __init dm_debugfs_init(void)
+{
+	struct dentry *ret_d;
+
+	dbgfs_root = debugfs_create_dir("dm_debug", NULL);
+	if (!dbgfs_root)
+		return -ENOENT;
+
+	ret_d = debugfs_create_u32("error_counter", 0644, dbgfs_root, &dbg_error_counter);
+	if (!ret_d)
+		goto fail;
+
+	ret_d = debugfs_create_u32("error_max", 0644, dbgfs_root, &dbg_error_max);
+	if (!ret_d)
+		goto fail;
+
+	ret_d = debugfs_create_u32("error", 0644, dbgfs_root, &dbg_error);
+	if (!ret_d)
+		goto fail;
+
+	return 0;
+
+fail:
+	debugfs_remove_recursive(dbgfs_root);
+	dbgfs_root = NULL;
+	return -ENOENT;
+}
+
+static void dm_debugfs_exit(void)
+{
+	debugfs_remove_recursive(dbgfs_root);
+}
+
 static int (*_inits[])(void) __initdata = {
 	local_init,
+	dm_debugfs_init,
 	dm_target_init,
 	dm_linear_init,
 	dm_stripe_init,
@@ -428,6 +468,7 @@ static int (*_inits[])(void) __initdata = {
 
 static void (*_exits[])(void) = {
 	local_exit,
+	dm_debugfs_exit,
 	dm_target_exit,
 	dm_linear_exit,
 	dm_stripe_exit,
@@ -1781,6 +1822,14 @@ static void __split_and_process_bio(struct mapped_device *md,
 		return;
 	}
 
+	if (bio_data_dir(bio) == WRITE) {
+		if (dbg_error && !strncmp(current->comm, "kworker", 7) &&
+				(++dbg_error_counter < dbg_error_max)) {
+			bio_io_error(bio);
+			return;
+		}
+	}
+
 	ci.map = map;
 	ci.md = md;
 	ci.io = alloc_io(md);
-- 
1.9.1

