Commit 14a56ec6 authored by Gao Xiang's avatar Gao Xiang Committed by Greg Kroah-Hartman

staging: erofs: support IO read error injection

Used to simulate disk IO read error for testing fatal
error tolerance.

Here are the details,
1) use bio->bi_private to indicate super_block
   for non-compressed bios since some (mainly meta)
   pages can be of the corresponding bdev inode;
2) get super_block dynamically for compressed bios,
   therefore it could not inject bios full of staging
   pages, yet it doesn't affect the normal usage.
Signed-off-by: default avatarGao Xiang <gaoxiang25@huawei.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d61fbb6b
...@@ -60,6 +60,7 @@ fault_injection=%d Enable fault injection in all supported types with ...@@ -60,6 +60,7 @@ fault_injection=%d Enable fault injection in all supported types with
specified injection rate. Supported injection type: specified injection rate. Supported injection type:
Type_Name Type_Value Type_Name Type_Value
FAULT_KMALLOC 0x000000001 FAULT_KMALLOC 0x000000001
FAULT_READ_IO 0x000000002
(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled (no)user_xattr Setup Extended User Attributes. Note: xattr is enabled
by default if CONFIG_EROFS_FS_XATTR is selected. by default if CONFIG_EROFS_FS_XATTR is selected.
(no)acl Setup POSIX Access Control List. Note: acl is enabled (no)acl Setup POSIX Access Control List. Note: acl is enabled
......
...@@ -17,11 +17,17 @@ ...@@ -17,11 +17,17 @@
static inline void read_endio(struct bio *bio) static inline void read_endio(struct bio *bio)
{ {
struct super_block *const sb = bio->bi_private;
int i; int i;
struct bio_vec *bvec; struct bio_vec *bvec;
const blk_status_t err = bio->bi_status; blk_status_t err = bio->bi_status;
struct bvec_iter_all iter_all; struct bvec_iter_all iter_all;
if (time_to_inject(EROFS_SB(sb), FAULT_READ_IO)) {
erofs_show_injection_info(FAULT_READ_IO);
err = BLK_STS_IOERR;
}
bio_for_each_segment_all(bvec, bio, i, iter_all) { bio_for_each_segment_all(bvec, bio, i, iter_all) {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
...@@ -63,7 +69,7 @@ struct page *__erofs_get_meta_page(struct super_block *sb, ...@@ -63,7 +69,7 @@ struct page *__erofs_get_meta_page(struct super_block *sb,
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
struct bio *bio; struct bio *bio;
bio = erofs_grab_bio(sb, blkaddr, 1, read_endio, nofail); bio = erofs_grab_bio(sb, blkaddr, 1, sb, read_endio, nofail);
if (IS_ERR(bio)) { if (IS_ERR(bio)) {
DBG_BUGON(nofail); DBG_BUGON(nofail);
err = PTR_ERR(bio); err = PTR_ERR(bio);
...@@ -188,7 +194,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, ...@@ -188,7 +194,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio,
unsigned int nblocks, unsigned int nblocks,
bool ra) bool ra)
{ {
struct inode *inode = mapping->host; struct inode *const inode = mapping->host;
struct super_block *const sb = inode->i_sb;
erofs_off_t current_block = (erofs_off_t)page->index; erofs_off_t current_block = (erofs_off_t)page->index;
int err; int err;
...@@ -280,9 +287,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, ...@@ -280,9 +287,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio,
if (nblocks > BIO_MAX_PAGES) if (nblocks > BIO_MAX_PAGES)
nblocks = BIO_MAX_PAGES; nblocks = BIO_MAX_PAGES;
bio = erofs_grab_bio(inode->i_sb, bio = erofs_grab_bio(sb, blknr, nblocks, sb,
blknr, nblocks, read_endio, false); read_endio, false);
if (IS_ERR(bio)) { if (IS_ERR(bio)) {
err = PTR_ERR(bio); err = PTR_ERR(bio);
bio = NULL; bio = NULL;
......
...@@ -44,11 +44,12 @@ ...@@ -44,11 +44,12 @@
enum { enum {
FAULT_KMALLOC, FAULT_KMALLOC,
FAULT_READ_IO,
FAULT_MAX, FAULT_MAX,
}; };
#ifdef CONFIG_EROFS_FAULT_INJECTION #ifdef CONFIG_EROFS_FAULT_INJECTION
extern char *erofs_fault_name[FAULT_MAX]; extern const char *erofs_fault_name[FAULT_MAX];
#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) #define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type)))
struct erofs_fault_info { struct erofs_fault_info {
...@@ -467,7 +468,7 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, ...@@ -467,7 +468,7 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode,
/* data.c */ /* data.c */
static inline struct bio * static inline struct bio *
erofs_grab_bio(struct super_block *sb, erofs_grab_bio(struct super_block *sb,
erofs_blk_t blkaddr, unsigned int nr_pages, erofs_blk_t blkaddr, unsigned int nr_pages, void *bi_private,
bio_end_io_t endio, bool nofail) bio_end_io_t endio, bool nofail)
{ {
const gfp_t gfp = GFP_NOIO; const gfp_t gfp = GFP_NOIO;
...@@ -489,6 +490,7 @@ erofs_grab_bio(struct super_block *sb, ...@@ -489,6 +490,7 @@ erofs_grab_bio(struct super_block *sb,
bio->bi_end_io = endio; bio->bi_end_io = endio;
bio_set_dev(bio, sb->s_bdev); bio_set_dev(bio, sb->s_bdev);
bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK; bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK;
bio->bi_private = bi_private;
return bio; return bio;
} }
......
...@@ -142,8 +142,9 @@ static int superblock_read(struct super_block *sb) ...@@ -142,8 +142,9 @@ static int superblock_read(struct super_block *sb)
} }
#ifdef CONFIG_EROFS_FAULT_INJECTION #ifdef CONFIG_EROFS_FAULT_INJECTION
char *erofs_fault_name[FAULT_MAX] = { const char *erofs_fault_name[FAULT_MAX] = {
[FAULT_KMALLOC] = "kmalloc", [FAULT_KMALLOC] = "kmalloc",
[FAULT_READ_IO] = "read IO error",
}; };
static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, static void __erofs_build_fault_attr(struct erofs_sb_info *sbi,
......
...@@ -844,8 +844,8 @@ static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) ...@@ -844,8 +844,8 @@ static void z_erofs_vle_unzip_kickoff(void *ptr, int bios)
static inline void z_erofs_vle_read_endio(struct bio *bio) static inline void z_erofs_vle_read_endio(struct bio *bio)
{ {
const blk_status_t err = bio->bi_status;
struct erofs_sb_info *sbi = NULL; struct erofs_sb_info *sbi = NULL;
blk_status_t err = bio->bi_status;
unsigned int i; unsigned int i;
struct bio_vec *bvec; struct bio_vec *bvec;
struct bvec_iter_all iter_all; struct bvec_iter_all iter_all;
...@@ -857,9 +857,15 @@ static inline void z_erofs_vle_read_endio(struct bio *bio) ...@@ -857,9 +857,15 @@ static inline void z_erofs_vle_read_endio(struct bio *bio)
DBG_BUGON(PageUptodate(page)); DBG_BUGON(PageUptodate(page));
DBG_BUGON(!page->mapping); DBG_BUGON(!page->mapping);
if (unlikely(!sbi && !z_erofs_is_stagingpage(page))) if (unlikely(!sbi && !z_erofs_is_stagingpage(page))) {
sbi = EROFS_SB(page->mapping->host->i_sb); sbi = EROFS_SB(page->mapping->host->i_sb);
if (time_to_inject(sbi, FAULT_READ_IO)) {
erofs_show_injection_info(FAULT_READ_IO);
err = BLK_STS_IOERR;
}
}
/* sbi should already be gotten if the page is managed */ /* sbi should already be gotten if the page is managed */
if (sbi) if (sbi)
cachemngd = erofs_page_is_managed(sbi, page); cachemngd = erofs_page_is_managed(sbi, page);
...@@ -1430,10 +1436,8 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, ...@@ -1430,10 +1436,8 @@ static bool z_erofs_vle_submit_all(struct super_block *sb,
if (!bio) { if (!bio) {
bio = erofs_grab_bio(sb, first_index + i, bio = erofs_grab_bio(sb, first_index + i,
BIO_MAX_PAGES, BIO_MAX_PAGES, bi_private,
z_erofs_vle_read_endio, true); z_erofs_vle_read_endio, true);
bio->bi_private = bi_private;
++nr_bios; ++nr_bios;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment