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

Commit 1ecc0c5c authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: support configuring fault injection per superblock



Previously, we only support global fault injection configuration, so that
when we configure type/rate of fault injection through sysfs, mount
option, it will influence all f2fs partition which is being used.

It is not make sence, since it will be not convenient if developer want
to test separated partitions with different fault injection rate/type
simultaneously, also it's not possible to enable fault injection in one
partition and disable fault injection in other one.

>From now on, we move global configuration of fault injection in module
into per-superblock, hence injection testing can be more flexible.

Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent d32853de
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -109,14 +109,16 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
	return ERR_PTR(-EINVAL);
}

static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,
				const struct posix_acl *acl, size_t *size)
{
	struct f2fs_acl_header *f2fs_acl;
	struct f2fs_acl_entry *entry;
	int i;

	f2fs_acl = f2fs_kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
			sizeof(struct f2fs_acl_entry), GFP_NOFS);
	f2fs_acl = f2fs_kmalloc(sbi, sizeof(struct f2fs_acl_header) +
			acl->a_count * sizeof(struct f2fs_acl_entry),
			GFP_NOFS);
	if (!f2fs_acl)
		return ERR_PTR(-ENOMEM);

@@ -175,7 +177,7 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,

	retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage);
	if (retval > 0) {
		value = f2fs_kmalloc(retval, GFP_F2FS_ZERO);
		value = f2fs_kmalloc(F2FS_I_SB(inode), retval, GFP_F2FS_ZERO);
		if (!value)
			return ERR_PTR(-ENOMEM);
		retval = f2fs_getxattr(inode, name_index, "", value,
@@ -230,7 +232,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
	}

	if (acl) {
		value = f2fs_acl_to_disk(acl, &size);
		value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size);
		if (IS_ERR(value)) {
			clear_inode_flag(inode, FI_ACL_MODE);
			return (int)PTR_ERR(value);
+1 −1
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
	spin_lock(&im->ino_lock);

#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (time_to_inject(FAULT_ORPHAN)) {
	if (time_to_inject(sbi, FAULT_ORPHAN)) {
		spin_unlock(&im->ino_lock);
		return -ENOSPC;
	}
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ static void f2fs_read_end_io(struct bio *bio)
	int i;

#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (time_to_inject(FAULT_IO))
	if (time_to_inject(F2FS_P_SB(bio->bi_io_vec->bv_page), FAULT_IO))
		bio->bi_error = -EIO;
#endif

+1 −1
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,

start:
#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (time_to_inject(FAULT_DIR_DEPTH))
	if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH))
		return -ENOSPC;
#endif
	if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
+35 −39
Original line number Diff line number Diff line
@@ -56,42 +56,8 @@ struct f2fs_fault_info {
	unsigned int inject_type;
};

extern struct f2fs_fault_info f2fs_fault;
extern char *fault_name[FAULT_MAX];
#define IS_FAULT_SET(type) (f2fs_fault.inject_type & (1 << (type)))

static inline bool time_to_inject(int type)
{
	if (!f2fs_fault.inject_rate)
		return false;
	if (type == FAULT_KMALLOC && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_PAGE_ALLOC && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_ALLOC_NID && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_ORPHAN && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_BLOCK && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_DIR_DEPTH && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_EVICT_INODE && !IS_FAULT_SET(type))
		return false;
	else if (type == FAULT_IO && !IS_FAULT_SET(type))
		return false;

	atomic_inc(&f2fs_fault.inject_ops);
	if (atomic_read(&f2fs_fault.inject_ops) >= f2fs_fault.inject_rate) {
		atomic_set(&f2fs_fault.inject_ops, 0);
		printk("%sF2FS-fs : inject %s in %pF\n",
				KERN_INFO,
				fault_name[type],
				__builtin_return_address(0));
		return true;
	}
	return false;
}
#define IS_FAULT_SET(fi, type) (fi->inject_type & (1 << (type)))
#endif

/*
@@ -905,8 +871,37 @@ struct f2fs_sb_info {

	/* Reference to checksum algorithm driver via cryptoapi */
	struct crypto_shash *s_chksum_driver;

	/* For fault injection */
#ifdef CONFIG_F2FS_FAULT_INJECTION
	struct f2fs_fault_info fault_info;
#endif
};

#ifdef CONFIG_F2FS_FAULT_INJECTION
static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
{
	struct f2fs_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);
		printk("%sF2FS-fs : inject %s in %pF\n",
				KERN_INFO,
				fault_name[type],
				__builtin_return_address(0));
		return true;
	}
	return false;
}
#endif

/* For write statistics. Suppose sector size is 512 bytes,
 * and the return value is in kbytes. s is of struct f2fs_sb_info.
 */
@@ -1195,7 +1190,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
	blkcnt_t diff;

#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (time_to_inject(FAULT_BLOCK))
	if (time_to_inject(sbi, FAULT_BLOCK))
		return false;
#endif
	/*
@@ -1429,7 +1424,7 @@ static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
	if (page)
		return page;

	if (time_to_inject(FAULT_PAGE_ALLOC))
	if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC))
		return NULL;
#endif
	if (!for_write)
@@ -1880,10 +1875,11 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
	return S_ISREG(inode->i_mode);
}

static inline void *f2fs_kmalloc(size_t size, gfp_t flags)
static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
					size_t size, gfp_t flags)
{
#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (time_to_inject(FAULT_KMALLOC))
	if (time_to_inject(sbi, FAULT_KMALLOC))
		return NULL;
#endif
	return kmalloc(size, flags);
Loading