Merge tag 'f2fs-for-v5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeu...
[linux-2.6-microblaze.git] / fs / f2fs / node.c
index d6e48a6..18a038a 100644 (file)
@@ -454,7 +454,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
                        new_blkaddr == NULL_ADDR);
        f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
                        new_blkaddr == NEW_ADDR);
-       f2fs_bug_on(sbi, is_valid_data_blkaddr(sbi, nat_get_blkaddr(e)) &&
+       f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) &&
                        new_blkaddr == NEW_ADDR);
 
        /* increment version no as node is removed */
@@ -465,7 +465,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 
        /* change address */
        nat_set_blkaddr(e, new_blkaddr);
-       if (!is_valid_data_blkaddr(sbi, new_blkaddr))
+       if (!__is_valid_data_blkaddr(new_blkaddr))
                set_nat_flag(e, IS_CHECKPOINTED, false);
        __set_nat_cache_dirty(nm_i, e);
 
@@ -526,6 +526,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        struct f2fs_nat_entry ne;
        struct nat_entry *e;
        pgoff_t index;
+       block_t blkaddr;
        int i;
 
        ni->nid = nid;
@@ -569,6 +570,11 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        node_info_from_raw_nat(ni, &ne);
        f2fs_put_page(page, 1);
 cache:
+       blkaddr = le32_to_cpu(ne.block_addr);
+       if (__is_valid_data_blkaddr(blkaddr) &&
+               !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE))
+               return -EFAULT;
+
        /* cache nat entry */
        cache_nat_entry(sbi, nid, &ne);
        return 0;
@@ -600,9 +606,9 @@ static void f2fs_ra_node_pages(struct page *parent, int start, int n)
 pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
 {
        const long direct_index = ADDRS_PER_INODE(dn->inode);
-       const long direct_blks = ADDRS_PER_BLOCK;
-       const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
-       unsigned int skipped_unit = ADDRS_PER_BLOCK;
+       const long direct_blks = ADDRS_PER_BLOCK(dn->inode);
+       const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK;
+       unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode);
        int cur_level = dn->cur_level;
        int max_level = dn->max_level;
        pgoff_t base = 0;
@@ -638,9 +644,9 @@ static int get_node_path(struct inode *inode, long block,
                                int offset[4], unsigned int noffset[4])
 {
        const long direct_index = ADDRS_PER_INODE(inode);
-       const long direct_blks = ADDRS_PER_BLOCK;
+       const long direct_blks = ADDRS_PER_BLOCK(inode);
        const long dptrs_per_blk = NIDS_PER_BLOCK;
-       const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+       const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK;
        const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
        int n = 0;
        int level = 0;
@@ -1181,8 +1187,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);
@@ -1277,9 +1289,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 -EBADMSG;
+               }
                return LOCKED_PAGE;
        }
 
@@ -1543,7 +1556,8 @@ 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_ENHANCE)) {
                up_read(&sbi->node_write);
                goto redirty_out;
        }
@@ -2078,6 +2092,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;