f2fs: use generic EFSBADCRC/EFSCORRUPTED
[platform/kernel/linux-rpi.git] / fs / f2fs / node.c
index dd2e45a..aa8f19e 100644 (file)
@@ -40,7 +40,7 @@ int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
                f2fs_msg(sbi->sb, KERN_WARNING,
                                "%s: out-of-range nid=%x, run fsck to fix.",
                                __func__, nid);
-               return -EINVAL;
+               return -EFSCORRUPTED;
        }
        return 0;
 }
@@ -827,6 +827,7 @@ static int truncate_node(struct dnode_of_data *dn)
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct node_info ni;
        int err;
+       pgoff_t index;
 
        err = f2fs_get_node_info(sbi, dn->nid, &ni);
        if (err)
@@ -846,10 +847,11 @@ static int truncate_node(struct dnode_of_data *dn)
        clear_node_page_dirty(dn->node_page);
        set_sbi_flag(sbi, SBI_IS_DIRTY);
 
+       index = dn->node_page->index;
        f2fs_put_page(dn->node_page, 1);
 
        invalidate_mapping_pages(NODE_MAPPING(sbi),
-                       dn->node_page->index, dn->node_page->index);
+                       index, index);
 
        dn->node_page = NULL;
        trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
@@ -1178,8 +1180,14 @@ int f2fs_remove_inode_page(struct inode *inode)
                f2fs_put_dnode(&dn);
                return -EIO;
        }
-       f2fs_bug_on(F2FS_I_SB(inode),
-                       inode->i_blocks != 0 && inode->i_blocks != 8);
+
+       if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) {
+               f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
+                       "Inconsistent i_blocks, ino:%lu, iblocks:%llu",
+                       inode->i_ino,
+                       (unsigned long long)inode->i_blocks);
+               set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
+       }
 
        /* will put inode & node pages */
        err = truncate_node(&dn);
@@ -1274,9 +1282,10 @@ static int read_node_page(struct page *page, int op_flags)
        int err;
 
        if (PageUptodate(page)) {
-#ifdef CONFIG_F2FS_CHECK_FS
-               f2fs_bug_on(sbi, !f2fs_inode_chksum_verify(sbi, page));
-#endif
+               if (!f2fs_inode_chksum_verify(sbi, page)) {
+                       ClearPageUptodate(page);
+                       return -EFSBADCRC;
+               }
                return LOCKED_PAGE;
        }
 
@@ -1361,7 +1370,7 @@ repeat:
        }
 
        if (!f2fs_inode_chksum_verify(sbi, page)) {
-               err = -EBADMSG;
+               err = -EFSBADCRC;
                goto out_err;
        }
 page_hit:
@@ -1542,8 +1551,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
        }
 
        if (__is_valid_data_blkaddr(ni.blk_addr) &&
-               !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
+               !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) {
+               up_read(&sbi->node_write);
                goto redirty_out;
+       }
 
        if (atomic && !test_opt(sbi, NOBARRIER))
                fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
@@ -2069,6 +2080,9 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
        if (unlikely(nid == 0))
                return false;
 
+       if (unlikely(f2fs_check_nid_range(sbi, nid)))
+               return false;
+
        i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
        i->nid = nid;
        i->state = FREE_NID;
@@ -2537,7 +2551,7 @@ retry:
        if (!PageUptodate(ipage))
                SetPageUptodate(ipage);
        fill_node_footer(ipage, ino, ino, 0, true);
-       set_cold_node(page, false);
+       set_cold_node(ipage, false);
 
        src = F2FS_INODE(page);
        dst = F2FS_INODE(ipage);
@@ -2560,6 +2574,13 @@ retry:
                        F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize),
                                                                i_projid))
                        dst->i_projid = src->i_projid;
+
+               if (f2fs_sb_has_inode_crtime(sbi->sb) &&
+                       F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize),
+                                                       i_crtime_nsec)) {
+                       dst->i_crtime = src->i_crtime;
+                       dst->i_crtime_nsec = src->i_crtime_nsec;
+               }
        }
 
        new_ni = old_ni;