diff mbox series

[v2,11/12] ext4: add journal related fault injection

Message ID 20221110022558.7844-12-yi.zhang@huawei.com
State New
Headers show
Series ext4: enhance simulate fail facility | expand

Commit Message

Zhang Yi Nov. 10, 2022, 2:25 a.m. UTC
Add journal start, getting create/write access, and dirty metadata fault
injection. The journal start fault injections return -ENOMEM directly,
other 3 injections will abort the journal and return -EROFS.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
 fs/ext4/ext4.h      | 12 ++++++++++++
 fs/ext4/ext4_jbd2.c | 22 ++++++++++++++++------
 fs/ext4/ext4_jbd2.h |  5 +++++
 fs/ext4/sysfs.c     |  5 +++++
 4 files changed, 38 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 813127cfd3c0..96b805992ea5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1526,6 +1526,12 @@  enum ext4_fault_bits {
 	EXT4_FAULT_DIRBLOCK_EIO,	/* directory block */
 	EXT4_FAULT_XATTR_EIO,		/* xattr block */
 	EXT4_FAULT_SYMLINK_EIO,		/* symlink block */
+	/* journal error */
+	EXT4_FAULT_JOURNAL_START,	/* journal start inode */
+	EXT4_FAULT_JOURNAL_START_SB,	/* journal start sb */
+	EXT4_FAULT_JOURNAL_CREATE_ACCESS,	/* journal get create access */
+	EXT4_FAULT_JOURNAL_WRITE_ACCESS,	/* journal get write access */
+	EXT4_FAULT_JOURNAL_DIRTY_METADATA,	/* journal dirty meta data */
 	EXT4_FAULT_MAX
 };
 
@@ -1633,6 +1639,12 @@  EXT4_FAULT_INODE_LBLOCK_FN(DIRBLOCK_EIO, dirblock_io, -EIO)
 EXT4_FAULT_INODE_FN(XATTR_EIO, xattr_io, -EIO)
 EXT4_FAULT_INODE_FN(SYMLINK_EIO, symlink_io, -EIO)
 
+EXT4_FAULT_INODE_FN(JOURNAL_START, journal_start, -ENOMEM)
+EXT4_FAULT_FN(JOURNAL_START_SB, journal_start_sb, -ENOMEM)
+EXT4_FAULT_INODE_PBLOCK_FN(JOURNAL_CREATE_ACCESS, journal_create_access, -EROFS)
+EXT4_FAULT_INODE_PBLOCK_FN(JOURNAL_WRITE_ACCESS, journal_write_access, -EROFS)
+EXT4_FAULT_INODE_PBLOCK_FN(JOURNAL_DIRTY_METADATA, journal_dirty_metadata, -EROFS)
+
 /*
  * fourth extended-fs super-block data in memory
  */
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 8e1fb18f465e..e0972dea7463 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -95,6 +95,9 @@  handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
 
 	trace_ext4_journal_start(sb, blocks, rsv_blocks, revoke_creds,
 				 _RET_IP_);
+	err = ext4_fault_journal_start_sb(sb);
+	if (err)
+		return ERR_PTR(err);
 	err = ext4_journal_check_start(sb);
 	if (err < 0)
 		return ERR_PTR(err);
@@ -232,7 +235,9 @@  int __ext4_journal_get_write_access(const char *where, unsigned int line,
 		ext4_check_bdev_write_error(bh->b_bdev->bd_super);
 
 	if (ext4_handle_valid(handle)) {
-		err = jbd2_journal_get_write_access(handle, bh);
+		err = ext4_fault_journal_write_access(sb, 0, bh->b_blocknr);
+		if (!err)
+			err = jbd2_journal_get_write_access(handle, bh);
 		if (err) {
 			ext4_journal_abort_handle(where, line, __func__, bh,
 						  handle, err);
@@ -320,7 +325,9 @@  int __ext4_journal_get_create_access(const char *where, unsigned int line,
 	if (!ext4_handle_valid(handle))
 		return 0;
 
-	err = jbd2_journal_get_create_access(handle, bh);
+	err = ext4_fault_journal_create_access(sb, 0, bh->b_blocknr);
+	if (!err)
+		err = jbd2_journal_get_create_access(handle, bh);
 	if (err) {
 		ext4_journal_abort_handle(where, line, __func__, bh, handle,
 					  err);
@@ -338,7 +345,7 @@  int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
 				 handle_t *handle, struct inode *inode,
 				 struct buffer_head *bh)
 {
-	int err = 0;
+	int err = 0, fa_err = 0;
 
 	might_sleep();
 
@@ -346,9 +353,12 @@  int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
 	set_buffer_prio(bh);
 	set_buffer_uptodate(bh);
 	if (ext4_handle_valid(handle)) {
-		err = jbd2_journal_dirty_metadata(handle, bh);
-		/* Errors can only happen due to aborted journal or a nasty bug */
-		if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
+		if (bh->b_bdev->bd_super)
+			fa_err = ext4_fault_journal_dirty_metadata(bh->b_bdev->bd_super,
+						0, bh->b_blocknr);
+		if (!fa_err)
+			err = jbd2_journal_dirty_metadata(handle, bh);
+		if (!is_handle_aborted(handle) && (WARN_ON_ONCE(err) || fa_err)) {
 			ext4_journal_abort_handle(where, line, __func__, bh,
 						  handle, err);
 			if (inode == NULL) {
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index db2ae4a2b38d..b0a996f306bb 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -323,6 +323,11 @@  static inline handle_t *__ext4_journal_start(struct inode *inode,
 					     int blocks, int rsv_blocks,
 					     int revoke_creds)
 {
+	int err;
+
+	err = ext4_fault_journal_start(inode->i_sb, inode->i_ino);
+	if (err)
+		return ERR_PTR(err);
 	return __ext4_journal_start_sb(inode->i_sb, line, type, blocks,
 				       rsv_blocks, revoke_creds);
 }
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index dfccd9f04fbb..da725e128c89 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -585,6 +585,11 @@  char *ext4_fault_names[EXT4_FAULT_MAX] = {
 	"dir_block_eio",		/* EXT4_FAULT_DIRBLOCK_EIO */
 	"xattr_block_eio",		/* EXT4_FAULT_XATTR_EIO */
 	"symlink_block_eio",		/* EXT4_FAULT_SYMLINK_EIO */
+	"journal_start",		/* EXT4_FAULT_JOURNAL_START */
+	"journal_start_sb",		/* EXT4_FAULT_JOURNAL_START_SB */
+	"journal_get_create_access",	/* EXT4_FAULT_JOURNAL_CREATE_ACCESS */
+	"journal_get_write_access",	/* EXT4_FAULT_JOURNAL_WRITE_ACCESS */
+	"journal_dirty_metadata",	/* EXT4_FAULT_JOURNAL_DIRTY_METADATA */
 };
 
 static int ext4_fault_available_show(struct seq_file *m, void *v)