[PATCH] f2fs: support fault injection for f2fs_down_write_trylock()

From: Yangtao Li
Date: Sat Feb 18 2023 - 02:14:16 EST


This patch supports to inject fault into f2fs_down_write_trylock().

Usage:
a) echo 524288 > /sys/fs/f2fs/<dev>/inject_type or
b) mount -o fault_type=524288 <dev> <mountpoint>

Signed-off-by: Yangtao Li <frank.li@xxxxxxxx>
---
Documentation/ABI/testing/sysfs-fs-f2fs | 1 +
Documentation/filesystems/f2fs.rst | 1 +
fs/f2fs/checkpoint.c | 4 ++--
fs/f2fs/f2fs.h | 16 +++++++++++++++-
fs/f2fs/file.c | 8 ++++----
fs/f2fs/gc.c | 10 +++++-----
fs/f2fs/node.c | 2 +-
fs/f2fs/super.c | 1 +
8 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 94132745ecbe..a34507fbd01f 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -714,6 +714,7 @@ Description: Support configuring fault injection type, should be
FAULT_DQUOT_INIT 0x000010000
FAULT_LOCK_OP 0x000020000
FAULT_BLKADDR 0x000040000
+ FAULT_LOCK 0x000080000
=================== ===========

What: /sys/fs/f2fs/<disk>/discard_io_aware_gran
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 2055e72871fe..a81c896464ff 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -206,6 +206,7 @@ fault_type=%d Support configuring fault injection type, should be
FAULT_DQUOT_INIT 0x000010000
FAULT_LOCK_OP 0x000020000
FAULT_BLKADDR 0x000040000
+ FAULT_LOCK 0x000080000
=================== ===========
mode=%s Control block allocation mode which supports "adaptive"
and "lfs". In "lfs" mode, there should be no random
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 1369ec892a2c..93cee10d3244 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -372,7 +372,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
goto skip_write;

/* if locked failed, cp will flush dirty pages instead */
- if (!f2fs_down_write_trylock(&sbi->cp_global_sem))
+ if (!f2fs_down_write_trylock(sbi, &sbi->cp_global_sem))
goto skip_write;

trace_f2fs_writepages(mapping->host, wbc, META);
@@ -1182,7 +1182,7 @@ static bool __need_flush_quota(struct f2fs_sb_info *sbi)
if (!is_journalled_quota(sbi))
return false;

- if (!f2fs_down_write_trylock(&sbi->quota_sem))
+ if (!f2fs_down_write_trylock(sbi, &sbi->quota_sem))
return true;
if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) {
ret = false;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 21596e0266ba..462e478528e2 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -61,6 +61,7 @@ enum {
FAULT_DQUOT_INIT,
FAULT_LOCK_OP,
FAULT_BLKADDR,
+ FAULT_LOCK,
FAULT_MAX,
};

@@ -2207,8 +2208,21 @@ static inline void f2fs_down_write(struct f2fs_rwsem *sem)
down_write(&sem->internal_rwsem);
}

-static inline int f2fs_down_write_trylock(struct f2fs_rwsem *sem)
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+#define f2fs_down_write_trylock(sbi, sem) __f2fs_down_write_trylock(sbi, sem)
+
+static inline int __f2fs_down_write_trylock(struct f2fs_sb_info *sbi,
+ struct f2fs_rwsem *sem)
+{
+ if (time_to_inject(sbi, FAULT_LOCK))
+ return 0;
+#else
+#define f2fs_down_write_trylock(sbi, sem) __f2fs_down_write_trylock(sem)
+
+static inline int __f2fs_down_write_trylock(struct f2fs_rwsem *sem)
{
+#endif
+
return down_write_trylock(&sem->internal_rwsem);
}

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index ca1720fc1187..4fa9a5468e61 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2462,7 +2462,7 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
return ret;

if (!sync) {
- if (!f2fs_down_write_trylock(&sbi->gc_lock)) {
+ if (!f2fs_down_write_trylock(sbi, &sbi->gc_lock)) {
ret = -EBUSY;
goto out;
}
@@ -2506,7 +2506,7 @@ static int __f2fs_ioc_gc_range(struct file *filp, struct f2fs_gc_range *range)

do_more:
if (!range->sync) {
- if (!f2fs_down_write_trylock(&sbi->gc_lock)) {
+ if (!f2fs_down_write_trylock(sbi, &sbi->gc_lock)) {
ret = -EBUSY;
goto out;
}
@@ -2851,7 +2851,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
f2fs_down_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
if (src != dst) {
ret = -EBUSY;
- if (!f2fs_down_write_trylock(&F2FS_I(dst)->i_gc_rwsem[WRITE]))
+ if (!f2fs_down_write_trylock(sbi, &F2FS_I(dst)->i_gc_rwsem[WRITE]))
goto out_src;
}

@@ -2971,7 +2971,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
end_segno = min(start_segno + range.segments, dev_end_segno);

while (start_segno < end_segno) {
- if (!f2fs_down_write_trylock(&sbi->gc_lock)) {
+ if (!f2fs_down_write_trylock(sbi, &sbi->gc_lock)) {
ret = -EBUSY;
goto out;
}
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 0a9dfa459860..8f4c99741f03 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -104,7 +104,7 @@ static int gc_thread_func(void *data)
if (foreground) {
f2fs_down_write(&sbi->gc_lock);
goto do_gc;
- } else if (!f2fs_down_write_trylock(&sbi->gc_lock)) {
+ } else if (!f2fs_down_write_trylock(sbi, &sbi->gc_lock)) {
stat_other_skip_bggc_count(sbi);
goto next;
}
@@ -1546,7 +1546,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
return submitted;
}

- if (!f2fs_down_write_trylock(
+ if (!f2fs_down_write_trylock(sbi,
&F2FS_I(inode)->i_gc_rwsem[WRITE])) {
iput(inode);
sbi->skipped_gc_rwsem++;
@@ -1589,11 +1589,11 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
int err;

if (S_ISREG(inode->i_mode)) {
- if (!f2fs_down_write_trylock(&fi->i_gc_rwsem[READ])) {
+ if (!f2fs_down_write_trylock(sbi, &fi->i_gc_rwsem[READ])) {
sbi->skipped_gc_rwsem++;
continue;
}
- if (!f2fs_down_write_trylock(
+ if (!f2fs_down_write_trylock(sbi,
&fi->i_gc_rwsem[WRITE])) {
sbi->skipped_gc_rwsem++;
f2fs_up_write(&fi->i_gc_rwsem[READ]);
@@ -2113,7 +2113,7 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)
secs = div_u64(shrunk_blocks, BLKS_PER_SEC(sbi));

/* stop other GC */
- if (!f2fs_down_write_trylock(&sbi->gc_lock))
+ if (!f2fs_down_write_trylock(sbi, &sbi->gc_lock))
return -EAGAIN;

/* stop CP to protect MAIN_SEC in free_segment_range */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 19a1fee88a36..e35cbf0fc56b 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -517,7 +517,7 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
struct f2fs_nm_info *nm_i = NM_I(sbi);
int nr = nr_shrink;

- if (!f2fs_down_write_trylock(&nm_i->nat_tree_lock))
+ if (!f2fs_down_write_trylock(sbi, &nm_i->nat_tree_lock))
return 0;

spin_lock(&nm_i->nat_list_lock);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index aa55dc12aff2..33a315795deb 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -62,6 +62,7 @@ const char *f2fs_fault_name[FAULT_MAX] = {
[FAULT_DQUOT_INIT] = "dquot initialize",
[FAULT_LOCK_OP] = "lock_op",
[FAULT_BLKADDR] = "invalid blkaddr",
+ [FAULT_LOCK] = "lock",
};

void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
--
2.25.1