f2fs: use generic EFSBADCRC/EFSCORRUPTED
[platform/kernel/linux-rpi.git] / fs / f2fs / data.c
index 382c1ef..9511466 100644 (file)
@@ -80,7 +80,8 @@ static void __read_end_io(struct bio *bio)
                /* PG_error was set if any post_read step failed */
                if (bio->bi_status || PageError(page)) {
                        ClearPageUptodate(page);
-                       SetPageError(page);
+                       /* will re-read again later */
+                       ClearPageError(page);
                } else {
                        SetPageUptodate(page);
                }
@@ -196,12 +197,14 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
        struct block_device *bdev = sbi->sb->s_bdev;
        int i;
 
-       for (i = 0; i < sbi->s_ndevs; i++) {
-               if (FDEV(i).start_blk <= blk_addr &&
-                                       FDEV(i).end_blk >= blk_addr) {
-                       blk_addr -= FDEV(i).start_blk;
-                       bdev = FDEV(i).bdev;
-                       break;
+       if (f2fs_is_multi_device(sbi)) {
+               for (i = 0; i < sbi->s_ndevs; i++) {
+                       if (FDEV(i).start_blk <= blk_addr &&
+                           FDEV(i).end_blk >= blk_addr) {
+                               blk_addr -= FDEV(i).start_blk;
+                               bdev = FDEV(i).bdev;
+                               break;
+                       }
                }
        }
        if (bio) {
@@ -215,6 +218,9 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr)
 {
        int i;
 
+       if (!f2fs_is_multi_device(sbi))
+               return 0;
+
        for (i = 0; i < sbi->s_ndevs; i++)
                if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr)
                        return i;
@@ -443,7 +449,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
 
        if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
                        __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
-               return -EFAULT;
+               return -EFSCORRUPTED;
 
        trace_f2fs_submit_page_bio(page, fio);
        f2fs_trace_ios(fio, 0);
@@ -456,12 +462,16 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
                bio_put(bio);
                return -EFAULT;
        }
-       bio_set_op_attrs(bio, fio->op, fio->op_flags);
 
-       __submit_bio(fio->sbi, bio, fio->type);
+       if (fio->io_wbc && !is_read_io(fio->op))
+               wbc_account_io(fio->io_wbc, page, PAGE_SIZE);
+
+       bio_set_op_attrs(bio, fio->op, fio->op_flags);
 
        if (!is_read_io(fio->op))
                inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page));
+
+       __submit_bio(fio->sbi, bio, fio->type);
        return 0;
 }
 
@@ -586,6 +596,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
                bio_put(bio);
                return -EFAULT;
        }
+       ClearPageError(page);
        __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
 }
@@ -1060,7 +1071,7 @@ next_block:
 
        if (__is_valid_data_blkaddr(blkaddr) &&
                !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) {
-               err = -EFAULT;
+               err = -EFSCORRUPTED;
                goto sync_out;
        }
 
@@ -1561,6 +1572,7 @@ submit_and_realloc:
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
                        goto submit_and_realloc;
 
+               ClearPageError(page);
                last_block_in_bio = block_nr;
                goto next_page;
 set_error_page:
@@ -1743,7 +1755,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
 
                if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
                                                        DATA_GENERIC))
-                       return -EFAULT;
+                       return -EFSCORRUPTED;
 
                ipu_force = true;
                fio->need_lock = LOCK_DONE;
@@ -1769,7 +1781,7 @@ got_it:
        if (__is_valid_data_blkaddr(fio->old_blkaddr) &&
                !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
                                                        DATA_GENERIC)) {
-               err = -EFAULT;
+               err = -EFSCORRUPTED;
                goto out_writepage;
        }
        /*
@@ -2252,6 +2264,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
        bool locked = false;
        struct extent_info ei = {0,0,0};
        int err = 0;
+       int flag;
 
        /*
         * we already allocated all the blocks, so we don't need to get
@@ -2261,9 +2274,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
                        !is_inode_flag_set(inode, FI_NO_PREALLOC))
                return 0;
 
+       /* f2fs_lock_op avoids race between write CP and convert_inline_page */
+       if (f2fs_has_inline_data(inode) && pos + len > MAX_INLINE_DATA(inode))
+               flag = F2FS_GET_BLOCK_DEFAULT;
+       else
+               flag = F2FS_GET_BLOCK_PRE_AIO;
+
        if (f2fs_has_inline_data(inode) ||
                        (pos & PAGE_MASK) >= i_size_read(inode)) {
-               __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true);
+               __do_map_lock(sbi, flag, true);
                locked = true;
        }
 restart:
@@ -2301,6 +2320,7 @@ restart:
                                f2fs_put_dnode(&dn);
                                __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO,
                                                                true);
+                               WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
                                locked = true;
                                goto restart;
                        }
@@ -2314,7 +2334,7 @@ out:
        f2fs_put_dnode(&dn);
 unlock_out:
        if (locked)
-               __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
+               __do_map_lock(sbi, flag, false);
        return err;
 }
 
@@ -2583,10 +2603,6 @@ static int f2fs_set_data_page_dirty(struct page *page)
        if (!PageUptodate(page))
                SetPageUptodate(page);
 
-       /* don't remain PG_checked flag which was set during GC */
-       if (is_cold_data(page))
-               clear_cold_data(page);
-
        if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
                if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
                        f2fs_register_inmem_page(inode, page);