All of lore.kernel.org
 help / color / mirror / Atom feed
From: yuchao0@huawei.com (Chao Yu)
Subject: [PATCH 10/11] erofs: introduce error injection infrastructure
Date: Fri, 22 Jun 2018 10:01:30 +0800	[thread overview]
Message-ID: <20180622020131.65525-10-yuchao0@huawei.com> (raw)
In-Reply-To: <20180622020131.65525-1-yuchao0@huawei.com>

This patch introduces error injection infrastructure, with it, we can
inject error in any kernel exported common functions which erofs used,
so that it can force erofs running into error paths, it turns out that
tests can cover real rare paths more easily to find bugs.

Reviewed-by: Gao Xiang <gaoxiang25 at huawei.com>
Signed-off-by: Chao Yu <yuchao0 at huawei.com>
---
 fs/erofs/Kconfig    |  6 +++++
 fs/erofs/inode.c    |  3 ++-
 fs/erofs/internal.h | 56 +++++++++++++++++++++++++++++++++++++++++++++
 fs/erofs/super.c    | 40 +++++++++++++++++++++++++++++++-
 4 files changed, 103 insertions(+), 2 deletions(-)

diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index 752f0e08d0b8..e9bab0f5600c 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -86,3 +86,9 @@ config EROFS_FS_ZIP
 
 	  If you don't want to use compression, say N.
 
+config EROFS_FAULT_INJECTION
+	bool "EROFS fault injection facility"
+	depends on EROFS_FS
+	help
+	  Test EROFS to inject faults such as ENOMEM, EIO, and so on.
+	  If unsure, say N.
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index 3dbce0cf41ff..78e94ddb3080 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -100,6 +100,7 @@ static int read_inode(struct inode *inode, void *data)
 int fill_inline_data(struct inode *inode, void *data, unsigned m_pofs)
 {
 	struct erofs_vnode *vi = EROFS_V(inode);
+	struct erofs_sb_info *sbi = EROFS_I_SB(inode);
 	int mode = vi->data_mapping_mode;
 
 	BUG_ON(mode >= EROFS_INODE_LAYOUT_MAX);
@@ -110,7 +111,7 @@ int fill_inline_data(struct inode *inode, void *data, unsigned m_pofs)
 
 	/* fast symlink (following ext4) */
 	if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) {
-		char *lnk = kmalloc(inode->i_size + 1, GFP_KERNEL);
+		char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL);
 
 		if (unlikely(lnk == NULL))
 			return -ENOMEM;
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 43620c07044d..eb482b54d4b2 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -45,6 +45,22 @@
 #define DBG_BUGON(...)  ((void)0)
 #endif
 
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+enum {
+	FAULT_KMALLOC,
+	FAULT_MAX,
+};
+
+extern char *fault_name[FAULT_MAX];
+#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type)))
+
+struct erofs_fault_info {
+	atomic_t inject_ops;
+	unsigned int inject_rate;
+	unsigned int inject_type;
+};
+#endif
+
 /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */
 #define EROFS_SUPER_MAGIC   EROFS_SUPER_MAGIC_V1
 
@@ -81,14 +97,54 @@ struct erofs_sb_info {
 	char *dev_name;
 
 	unsigned int mount_opt;
+
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+	struct erofs_fault_info fault_info;	/* For fault injection */
+#endif
 };
 
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+#define erofs_show_injection_info(type)					\
+	infoln("inject %s in %s of %pS", fault_name[type], __func__,	\
+					__builtin_return_address(0))
+static inline bool time_to_inject(struct erofs_sb_info *sbi, int type)
+{
+	struct erofs_fault_info *ffi = &sbi->fault_info;
+
+	if (!ffi->inject_rate)
+		return false;
+
+	if (!IS_FAULT_SET(ffi, type))
+		return false;
+
+	atomic_inc(&ffi->inject_ops);
+	if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) {
+		atomic_set(&ffi->inject_ops, 0);
+		return true;
+	}
+	return false;
+}
+#endif
+
+static inline void *erofs_kmalloc(struct erofs_sb_info *sbi,
+					size_t size, gfp_t flags)
+{
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+	if (time_to_inject(sbi, FAULT_KMALLOC)) {
+		erofs_show_injection_info(FAULT_KMALLOC);
+		return NULL;
+	}
+#endif
+	return kmalloc(size, flags);
+}
+
 #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info)
 #define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info)
 
 /* Mount flags set via mount options or defaults */
 #define EROFS_MOUNT_XATTR_USER		0x00000010
 #define EROFS_MOUNT_POSIX_ACL		0x00000020
+#define EROFS_MOUNT_FAULT_INJECTION	0x00000040
 
 #define clear_opt(sbi, option)	((sbi)->mount_opt &= ~EROFS_MOUNT_##option)
 #define set_opt(sbi, option)	((sbi)->mount_opt |= EROFS_MOUNT_##option)
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 390a5217bbcc..b5af35ec2797 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -135,6 +135,26 @@ static int superblock_read(struct super_block *sb)
 	return ret;
 }
 
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+char *fault_name[FAULT_MAX] = {
+	[FAULT_KMALLOC]		= "kmalloc",
+};
+
+static void erofs_build_fault_attr(struct erofs_sb_info *sbi,
+						unsigned int rate)
+{
+	struct erofs_fault_info *ffi = &sbi->fault_info;
+
+	if (rate) {
+		atomic_set(&ffi->inject_ops, 0);
+		ffi->inject_rate = rate;
+		ffi->inject_type = (1 << FAULT_MAX) - 1;
+	} else {
+		memset(ffi, 0, sizeof(struct erofs_fault_info));
+	}
+}
+#endif
+
 static void default_options(struct erofs_sb_info *sbi)
 {
 #ifdef CONFIG_EROFS_FS_XATTR
@@ -148,18 +168,21 @@ static void default_options(struct erofs_sb_info *sbi)
 
 enum {
 	Opt_user_xattr,
-	Opt_acl
+	Opt_acl,
+	Opt_fault_injection
 };
 
 static match_table_t erofs_tokens = {
 	{Opt_user_xattr, "user_xattr"},
 	{Opt_acl, "acl"},
+	{Opt_fault_injection, "fault_injection=%u"},
 };
 
 static int parse_options(struct super_block *sb, char *options)
 {
 	substring_t args[MAX_OPT_ARGS];
 	char *p;
+	int arg = 0;
 
 	if (!options)
 		return 0;
@@ -192,6 +215,16 @@ static int parse_options(struct super_block *sb, char *options)
 			infoln("acl options not supported");
 			break;
 #endif
+		case Opt_fault_injection:
+			if (args->from && match_int(args, &arg))
+				return -EINVAL;
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+			erofs_build_fault_attr(EROFS_SB(sb), arg);
+			set_opt(EROFS_SB(sb), FAULT_INJECTION);
+#else
+			infoln("FAULT_INJECTION was not selected");
+#endif
+			break;
 		default:
 			infoln("Unrecognized mount option \"%s\" "
 					"or missing value", p);
@@ -451,6 +484,11 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
 		seq_puts(seq, ",acl");
 	else
 		seq_puts(seq, ",noacl");
+#endif
+#ifdef CONFIG_EROFS_FAULT_INJECTION
+	if (test_opt(sbi, FAULT_INJECTION))
+		seq_printf(seq, ",fault_injection=%u",
+				sbi->fault_info.inject_rate);
 #endif
 	return 0;
 }
-- 
2.18.0.rc1

  parent reply	other threads:[~2018-06-22  2:01 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-22  2:01 [PATCH 01/11] erofs: fix compile error Chao Yu
2018-06-22  2:01 ` [PATCH 02/11] erofs: fix to avoid potential overflow Chao Yu
2018-06-22  2:01 ` [PATCH 03/11] erofs: fix missing endian conversion Chao Yu
2018-06-22  2:01 ` [PATCH 04/11] erofs: fix to do endian conversion correctly Chao Yu
2018-06-22  2:01 ` [PATCH 05/11] erofs: fix to handle return value of erofs_init_page_bundle() correctly Chao Yu
2018-06-22  2:01 ` [PATCH 06/11] erofs: fix to return correct value of alloc_inode Chao Yu
2018-06-22  2:01 ` [PATCH 07/11] erofs: remove unused EROFS_XATTR_INDEX_ADVISE Chao Yu
2018-06-22  2:01 ` [PATCH 08/11] erofs: support special inode Chao Yu
2018-07-03  5:31   ` Gao Xiang
2018-07-03 13:48     ` Chao Yu
2018-08-01  8:17       ` Gao Xiang
2018-08-01  8:40         ` 答复: " liguifu (C)
2018-06-22  2:01 ` [PATCH 09/11] erofs: introduce parse_options() Chao Yu
2018-06-22  2:01 ` Chao Yu [this message]
2018-06-30 15:44   ` [PATCH v4] erofs: introduce error injection infrastructure Gao Xiang
2018-06-30 18:39   ` [PATCH v5] " Gao Xiang
2018-07-01  3:56     ` Chao Yu
2018-07-01  4:04       ` Gao Xiang
2018-06-22  2:01 ` [PATCH 11/11] erofs: support tracepoint Chao Yu
2018-07-03  9:44   ` Gao Xiang
2018-07-03 13:52     ` Chao Yu
2018-07-03 14:22       ` Gao Xiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180622020131.65525-10-yuchao0@huawei.com \
    --to=yuchao0@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.