]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
staging: erofs: support IO read error injection
authorGao Xiang <gaoxiang25@huawei.com>
Mon, 25 Mar 2019 03:40:09 +0000 (11:40 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 25 Mar 2019 20:51:17 +0000 (05:51 +0900)
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>
drivers/staging/erofs/Documentation/filesystems/erofs.txt
drivers/staging/erofs/data.c
drivers/staging/erofs/internal.h
drivers/staging/erofs/super.c
drivers/staging/erofs/unzip_vle.c

index 961ec4da77056cbf2df8b4f00d778ee158949c4d..74cf84ac48a36e1477b116c79d546a46e4848ad4 100644 (file)
@@ -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
index 526e0dbea5b5714618b463cb3eab98b0895e99f6..0714061ba888dacadd3771b28663e43b4191279c 100644 (file)
 
 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;
index a66c7d495c3555d7028c9d8428040764dfbac57a..c47778b3fabd31a3648b285907b7ff1377b9dae2 100644 (file)
 
 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;
 }
 
index 7b460a3ca4d6e58b6ee282a1cac463c5d32e7e6f..8bee0d3a161b5b8985bafddf02135ca97992075a 100644 (file)
@@ -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,
index 8e720bb882c7efdd5609ae9cec8be15b2e627fb6..566835cf6f2fef1dfcddb3f9d86b0579ebfc9ca9 100644 (file)
@@ -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;
                }