mirror of https://gitee.com/openkylin/linux.git
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: Gao Xiang <gaoxiang25@huawei.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d61fbb6b16
commit
14a56ec65b
|
@ -60,6 +60,7 @@ fault_injection=%d Enable fault injection in all supported types with
|
|||
specified injection rate. Supported injection type:
|
||||
Type_Name Type_Value
|
||||
FAULT_KMALLOC 0x000000001
|
||||
FAULT_READ_IO 0x000000002
|
||||
(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled
|
||||
by default if CONFIG_EROFS_FS_XATTR is selected.
|
||||
(no)acl Setup POSIX Access Control List. Note: acl is enabled
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
|
||||
static inline void read_endio(struct bio *bio)
|
||||
{
|
||||
struct super_block *const sb = bio->bi_private;
|
||||
int i;
|
||||
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;
|
||||
|
||||
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) {
|
||||
struct page *page = bvec->bv_page;
|
||||
|
||||
|
@ -63,7 +69,7 @@ struct page *__erofs_get_meta_page(struct super_block *sb,
|
|||
if (!PageUptodate(page)) {
|
||||
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)) {
|
||||
DBG_BUGON(nofail);
|
||||
err = PTR_ERR(bio);
|
||||
|
@ -188,7 +194,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio,
|
|||
unsigned int nblocks,
|
||||
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;
|
||||
int err;
|
||||
|
||||
|
@ -280,9 +287,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio,
|
|||
if (nblocks > BIO_MAX_PAGES)
|
||||
nblocks = BIO_MAX_PAGES;
|
||||
|
||||
bio = erofs_grab_bio(inode->i_sb,
|
||||
blknr, nblocks, read_endio, false);
|
||||
|
||||
bio = erofs_grab_bio(sb, blknr, nblocks, sb,
|
||||
read_endio, false);
|
||||
if (IS_ERR(bio)) {
|
||||
err = PTR_ERR(bio);
|
||||
bio = NULL;
|
||||
|
|
|
@ -44,11 +44,12 @@
|
|||
|
||||
enum {
|
||||
FAULT_KMALLOC,
|
||||
FAULT_READ_IO,
|
||||
FAULT_MAX,
|
||||
};
|
||||
|
||||
#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)))
|
||||
|
||||
struct erofs_fault_info {
|
||||
|
@ -467,7 +468,7 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode,
|
|||
/* data.c */
|
||||
static inline struct bio *
|
||||
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)
|
||||
{
|
||||
const gfp_t gfp = GFP_NOIO;
|
||||
|
@ -489,6 +490,7 @@ erofs_grab_bio(struct super_block *sb,
|
|||
bio->bi_end_io = endio;
|
||||
bio_set_dev(bio, sb->s_bdev);
|
||||
bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK;
|
||||
bio->bi_private = bi_private;
|
||||
return bio;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,8 +142,9 @@ static int superblock_read(struct super_block *sb)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FAULT_INJECTION
|
||||
char *erofs_fault_name[FAULT_MAX] = {
|
||||
const char *erofs_fault_name[FAULT_MAX] = {
|
||||
[FAULT_KMALLOC] = "kmalloc",
|
||||
[FAULT_READ_IO] = "read IO error",
|
||||
};
|
||||
|
||||
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)
|
|||
|
||||
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;
|
||||
blk_status_t err = bio->bi_status;
|
||||
unsigned int i;
|
||||
struct bio_vec *bvec;
|
||||
struct bvec_iter_all iter_all;
|
||||
|
@ -857,9 +857,15 @@ static inline void z_erofs_vle_read_endio(struct bio *bio)
|
|||
DBG_BUGON(PageUptodate(page));
|
||||
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);
|
||||
|
||||
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 */
|
||||
if (sbi)
|
||||
cachemngd = erofs_page_is_managed(sbi, page);
|
||||
|
@ -1430,10 +1436,8 @@ static bool z_erofs_vle_submit_all(struct super_block *sb,
|
|||
|
||||
if (!bio) {
|
||||
bio = erofs_grab_bio(sb, first_index + i,
|
||||
BIO_MAX_PAGES,
|
||||
BIO_MAX_PAGES, bi_private,
|
||||
z_erofs_vle_read_endio, true);
|
||||
bio->bi_private = bi_private;
|
||||
|
||||
++nr_bios;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue