[PATCH v5] erofs: introduce error injection infrastructure
Chao Yu
chao at kernel.org
Sun Jul 1 13:56:27 AEST 2018
On 2018/7/1 2:39, Gao Xiang via Linux-erofs wrote:
> From: Chao Yu <yuchao0 at 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>
> ---
> v5 Gao Xiang <gaoxiang25 at huawei.com>:
> - fix implicit declaration of "kmalloc" by moving
> <linux/slab.h> to internal.h
> Reported-by: kbuild test robot <lkp at intel.com>
> https://lists.01.org/pipermail/kbuild-all/2018-June/049644.html
>
> v4 Gao Xiang <gaoxiang25 at huawei.com>:
> - avoid the global variable 'fault_name' to pollute symbol space.
> Reported-by: kbuild test robot <lkp at intel.com>
> https://lists.01.org/pipermail/kbuild-all/2018-June/049660.html
Thanks for fixing these issues.
Thanks,
> v3:
> - code rebase.
> v2:
> - add missing Kconfig entry.
> - fix double prefix 'erofs:' in erofs_show_injection_info macro.
>
> fs/erofs/Kconfig | 6 +++++
> fs/erofs/inode.c | 4 ++--
> fs/erofs/internal.h | 58 +++++++++++++++++++++++++++++++++++++++++++++
> fs/erofs/super.c | 41 ++++++++++++++++++++++++++++++--
> fs/erofs/xattr.c | 1 -
> 5 files changed, 105 insertions(+), 5 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..844b999649f0 100644
> --- a/fs/erofs/inode.c
> +++ b/fs/erofs/inode.c
> @@ -11,7 +11,6 @@
> * distribution for more details.
> */
> #include "internal.h"
> -#include <linux/slab.h>
> #include "xattr.h"
>
> /* no locking */
> @@ -100,6 +99,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 +110,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..2567fb83b5f6 100644
> --- a/fs/erofs/internal.h
> +++ b/fs/erofs/internal.h
> @@ -23,6 +23,7 @@
> #ifdef CONFIG_EROFS_FS_PAGE_BUNDLE
> #include <linux/swap.h>
> #endif
> +#include <linux/slab.h>
> #include <linux/vmalloc.h>
> #include "erofs_fs.h"
>
> @@ -45,6 +46,22 @@
> #define DBG_BUGON(...) ((void)0)
> #endif
>
> +#ifdef CONFIG_EROFS_FAULT_INJECTION
> +enum {
> + FAULT_KMALLOC,
> + FAULT_MAX,
> +};
> +
> +extern char *erofs_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 +98,55 @@ 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", erofs_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..d6046d4d787b 100644
> --- a/fs/erofs/super.c
> +++ b/fs/erofs/super.c
> @@ -12,7 +12,6 @@
> */
> #include <linux/module.h>
> #include <linux/buffer_head.h>
> -#include <linux/slab.h>
> #include <linux/statfs.h>
> #include <linux/seq_file.h>
> #include <linux/parser.h>
> @@ -135,6 +134,26 @@ static int superblock_read(struct super_block *sb)
> return ret;
> }
>
> +#ifdef CONFIG_EROFS_FAULT_INJECTION
> +char *erofs_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 +167,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 +214,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 +483,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;
> }
> diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
> index fb8f3f1b3aab..aa0231768643 100644
> --- a/fs/erofs/xattr.c
> +++ b/fs/erofs/xattr.c
> @@ -10,7 +10,6 @@
> * License. See the file COPYING in the main directory of the Linux
> * distribution for more details.
> */
> -#include <linux/slab.h>
> #include <linux/security.h>
> #include "xattr.h"
> #include <linux/version.h>
>
More information about the Linux-erofs
mailing list