f2fs: use generic EFSBADCRC/EFSCORRUPTED
[platform/kernel/linux-rpi.git] / fs / f2fs / node.c
index 10643b1..aa8f19e 100644 (file)
@@ -28,6 +28,7 @@
 static struct kmem_cache *nat_entry_slab;
 static struct kmem_cache *free_nid_slab;
 static struct kmem_cache *nat_entry_set_slab;
+static struct kmem_cache *fsync_node_entry_slab;
 
 /*
  * Check whether the given nid is within node id range.
@@ -39,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;
 }
@@ -112,25 +113,22 @@ static void clear_node_page_dirty(struct page *page)
 
 static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
 {
-       pgoff_t index = current_nat_addr(sbi, nid);
-       return f2fs_get_meta_page(sbi, index);
+       return f2fs_get_meta_page_nofail(sbi, current_nat_addr(sbi, nid));
 }
 
 static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
 {
        struct page *src_page;
        struct page *dst_page;
-       pgoff_t src_off;
        pgoff_t dst_off;
        void *src_addr;
        void *dst_addr;
        struct f2fs_nm_info *nm_i = NM_I(sbi);
 
-       src_off = current_nat_addr(sbi, nid);
-       dst_off = next_nat_addr(sbi, src_off);
+       dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid));
 
        /* get current nat block page with lock */
-       src_page = f2fs_get_meta_page(sbi, src_off);
+       src_page = get_current_nat_page(sbi, nid);
        dst_page = f2fs_grab_meta_page(sbi, dst_off);
        f2fs_bug_on(sbi, PageDirty(src_page));
 
@@ -176,14 +174,30 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
 
        if (raw_ne)
                node_info_from_raw_nat(&ne->ni, raw_ne);
+
+       spin_lock(&nm_i->nat_list_lock);
        list_add_tail(&ne->list, &nm_i->nat_entries);
+       spin_unlock(&nm_i->nat_list_lock);
+
        nm_i->nat_cnt++;
        return ne;
 }
 
 static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
 {
-       return radix_tree_lookup(&nm_i->nat_root, n);
+       struct nat_entry *ne;
+
+       ne = radix_tree_lookup(&nm_i->nat_root, n);
+
+       /* for recent accessed nat entry, move it to tail of lru list */
+       if (ne && !get_nat_flag(ne, IS_DIRTY)) {
+               spin_lock(&nm_i->nat_list_lock);
+               if (!list_empty(&ne->list))
+                       list_move_tail(&ne->list, &nm_i->nat_entries);
+               spin_unlock(&nm_i->nat_list_lock);
+       }
+
+       return ne;
 }
 
 static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
@@ -194,7 +208,6 @@ static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
 
 static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
 {
-       list_del(&e->list);
        radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
        nm_i->nat_cnt--;
        __free_nat_entry(e);
@@ -245,16 +258,21 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
        nm_i->dirty_nat_cnt++;
        set_nat_flag(ne, IS_DIRTY, true);
 refresh_list:
+       spin_lock(&nm_i->nat_list_lock);
        if (new_ne)
                list_del_init(&ne->list);
        else
                list_move_tail(&ne->list, &head->entry_list);
+       spin_unlock(&nm_i->nat_list_lock);
 }
 
 static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
                struct nat_entry_set *set, struct nat_entry *ne)
 {
+       spin_lock(&nm_i->nat_list_lock);
        list_move_tail(&ne->list, &nm_i->nat_entries);
+       spin_unlock(&nm_i->nat_list_lock);
+
        set_nat_flag(ne, IS_DIRTY, false);
        set->entry_cnt--;
        nm_i->dirty_nat_cnt--;
@@ -267,6 +285,72 @@ static unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i,
                                                        start, nr);
 }
 
+bool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page)
+{
+       return NODE_MAPPING(sbi) == page->mapping &&
+                       IS_DNODE(page) && is_cold_node(page);
+}
+
+void f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi)
+{
+       spin_lock_init(&sbi->fsync_node_lock);
+       INIT_LIST_HEAD(&sbi->fsync_node_list);
+       sbi->fsync_seg_id = 0;
+       sbi->fsync_node_num = 0;
+}
+
+static unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi,
+                                                       struct page *page)
+{
+       struct fsync_node_entry *fn;
+       unsigned long flags;
+       unsigned int seq_id;
+
+       fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, GFP_NOFS);
+
+       get_page(page);
+       fn->page = page;
+       INIT_LIST_HEAD(&fn->list);
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       list_add_tail(&fn->list, &sbi->fsync_node_list);
+       fn->seq_id = sbi->fsync_seg_id++;
+       seq_id = fn->seq_id;
+       sbi->fsync_node_num++;
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+
+       return seq_id;
+}
+
+void f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page)
+{
+       struct fsync_node_entry *fn;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       list_for_each_entry(fn, &sbi->fsync_node_list, list) {
+               if (fn->page == page) {
+                       list_del(&fn->list);
+                       sbi->fsync_node_num--;
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       kmem_cache_free(fsync_node_entry_slab, fn);
+                       put_page(page);
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+       f2fs_bug_on(sbi, 1);
+}
+
+void f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       sbi->fsync_seg_id = 0;
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+}
+
 int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -371,7 +455,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_blkaddr(nat_get_blkaddr(e)) &&
+       f2fs_bug_on(sbi, is_valid_data_blkaddr(sbi, nat_get_blkaddr(e)) &&
                        new_blkaddr == NEW_ADDR);
 
        /* increment version no as node is removed */
@@ -382,7 +466,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_blkaddr(new_blkaddr))
+       if (!is_valid_data_blkaddr(sbi, new_blkaddr))
                set_nat_flag(e, IS_CHECKPOINTED, false);
        __set_nat_cache_dirty(nm_i, e);
 
@@ -405,13 +489,25 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
        if (!down_write_trylock(&nm_i->nat_tree_lock))
                return 0;
 
-       while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
+       spin_lock(&nm_i->nat_list_lock);
+       while (nr_shrink) {
                struct nat_entry *ne;
+
+               if (list_empty(&nm_i->nat_entries))
+                       break;
+
                ne = list_first_entry(&nm_i->nat_entries,
                                        struct nat_entry, list);
+               list_del(&ne->list);
+               spin_unlock(&nm_i->nat_list_lock);
+
                __del_from_nat_cache(nm_i, ne);
                nr_shrink--;
+
+               spin_lock(&nm_i->nat_list_lock);
        }
+       spin_unlock(&nm_i->nat_list_lock);
+
        up_write(&nm_i->nat_tree_lock);
        return nr - nr_shrink;
 }
@@ -419,7 +515,7 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
 /*
  * This function always returns success
  */
-void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
+int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
                                                struct node_info *ni)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -443,7 +539,7 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
                ni->blk_addr = nat_get_blkaddr(e);
                ni->version = nat_get_version(e);
                up_read(&nm_i->nat_tree_lock);
-               return;
+               return 0;
        }
 
        memset(&ne, 0, sizeof(struct f2fs_nat_entry));
@@ -466,6 +562,9 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        up_read(&nm_i->nat_tree_lock);
 
        page = f2fs_get_meta_page(sbi, index);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+
        nat_blk = (struct f2fs_nat_block *)page_address(page);
        ne = nat_blk->entries[nid - start_nid];
        node_info_from_raw_nat(ni, &ne);
@@ -473,6 +572,7 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
 cache:
        /* cache nat entry */
        cache_nat_entry(sbi, nid, &ne);
+       return 0;
 }
 
 /*
@@ -722,12 +822,16 @@ release_out:
        return err;
 }
 
-static void truncate_node(struct dnode_of_data *dn)
+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;
 
-       f2fs_get_node_info(sbi, dn->nid, &ni);
+       err = f2fs_get_node_info(sbi, dn->nid, &ni);
+       if (err)
+               return err;
 
        /* Deallocate node address */
        f2fs_invalidate_blocks(sbi, ni.blk_addr);
@@ -743,18 +847,22 @@ static void 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);
+
+       return 0;
 }
 
 static int truncate_dnode(struct dnode_of_data *dn)
 {
        struct page *page;
+       int err;
 
        if (dn->nid == 0)
                return 1;
@@ -770,7 +878,10 @@ static int truncate_dnode(struct dnode_of_data *dn)
        dn->node_page = page;
        dn->ofs_in_node = 0;
        f2fs_truncate_data_blocks(dn);
-       truncate_node(dn);
+       err = truncate_node(dn);
+       if (err)
+               return err;
+
        return 1;
 }
 
@@ -835,7 +946,9 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
        if (!ofs) {
                /* remove current indirect node */
                dn->node_page = page;
-               truncate_node(dn);
+               ret = truncate_node(dn);
+               if (ret)
+                       goto out_err;
                freed++;
        } else {
                f2fs_put_page(page, 1);
@@ -893,7 +1006,9 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
        if (offset[idx + 1] == 0) {
                dn->node_page = pages[idx];
                dn->nid = nid[idx];
-               truncate_node(dn);
+               err = truncate_node(dn);
+               if (err)
+                       goto fail;
        } else {
                f2fs_put_page(pages[idx], 1);
        }
@@ -1014,6 +1129,7 @@ int f2fs_truncate_xattr_node(struct inode *inode)
        nid_t nid = F2FS_I(inode)->i_xattr_nid;
        struct dnode_of_data dn;
        struct page *npage;
+       int err;
 
        if (!nid)
                return 0;
@@ -1022,10 +1138,15 @@ int f2fs_truncate_xattr_node(struct inode *inode)
        if (IS_ERR(npage))
                return PTR_ERR(npage);
 
+       set_new_dnode(&dn, inode, NULL, npage, nid);
+       err = truncate_node(&dn);
+       if (err) {
+               f2fs_put_page(npage, 1);
+               return err;
+       }
+
        f2fs_i_xnid_write(inode, 0);
 
-       set_new_dnode(&dn, inode, NULL, npage, nid);
-       truncate_node(&dn);
        return 0;
 }
 
@@ -1055,11 +1176,25 @@ int f2fs_remove_inode_page(struct inode *inode)
                f2fs_truncate_data_blocks_range(&dn, 1);
 
        /* 0 is possible, after f2fs_new_inode() has failed */
-       f2fs_bug_on(F2FS_I_SB(inode),
-                       inode->i_blocks != 0 && inode->i_blocks != 8);
+       if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
+               f2fs_put_dnode(&dn);
+               return -EIO;
+       }
+
+       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 */
-       truncate_node(&dn);
+       err = truncate_node(&dn);
+       if (err) {
+               f2fs_put_dnode(&dn);
+               return err;
+       }
        return 0;
 }
 
@@ -1092,7 +1227,11 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
                goto fail;
 
 #ifdef CONFIG_F2FS_CHECK_FS
-       f2fs_get_node_info(sbi, dn->nid, &new_ni);
+       err = f2fs_get_node_info(sbi, dn->nid, &new_ni);
+       if (err) {
+               dec_valid_node_count(sbi, dn->inode, !ofs);
+               goto fail;
+       }
        f2fs_bug_on(sbi, new_ni.blk_addr != NULL_ADDR);
 #endif
        new_ni.nid = dn->nid;
@@ -1140,13 +1279,22 @@ static int read_node_page(struct page *page, int op_flags)
                .page = page,
                .encrypted_page = NULL,
        };
+       int err;
 
-       if (PageUptodate(page))
+       if (PageUptodate(page)) {
+               if (!f2fs_inode_chksum_verify(sbi, page)) {
+                       ClearPageUptodate(page);
+                       return -EFSBADCRC;
+               }
                return LOCKED_PAGE;
+       }
 
-       f2fs_get_node_info(sbi, page->index, &ni);
+       err = f2fs_get_node_info(sbi, page->index, &ni);
+       if (err)
+               return err;
 
-       if (unlikely(ni.blk_addr == NULL_ADDR)) {
+       if (unlikely(ni.blk_addr == NULL_ADDR) ||
+                       is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
                ClearPageUptodate(page);
                return -ENOENT;
        }
@@ -1222,7 +1370,7 @@ repeat:
        }
 
        if (!f2fs_inode_chksum_verify(sbi, page)) {
-               err = -EBADMSG;
+               err = -EFSBADCRC;
                goto out_err;
        }
 page_hit:
@@ -1348,7 +1496,7 @@ continue_unlock:
 
 static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                                struct writeback_control *wbc, bool do_balance,
-                               enum iostat_type io_type)
+                               enum iostat_type io_type, unsigned int *seq_id)
 {
        struct f2fs_sb_info *sbi = F2FS_P_SB(page);
        nid_t nid;
@@ -1365,6 +1513,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                .io_type = io_type,
                .io_wbc = wbc,
        };
+       unsigned int seq;
 
        trace_f2fs_writepage(page, NODE);
 
@@ -1374,10 +1523,17 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto redirty_out;
 
+       if (wbc->sync_mode == WB_SYNC_NONE &&
+                       IS_DNODE(page) && is_cold_node(page))
+               goto redirty_out;
+
        /* get old block addr of this node page */
        nid = nid_of_node(page);
        f2fs_bug_on(sbi, page->index != nid);
 
+       if (f2fs_get_node_info(sbi, nid, &ni))
+               goto redirty_out;
+
        if (wbc->for_reclaim) {
                if (!down_read_trylock(&sbi->node_write))
                        goto redirty_out;
@@ -1385,8 +1541,6 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                down_read(&sbi->node_write);
        }
 
-       f2fs_get_node_info(sbi, nid, &ni);
-
        /* This page is already truncated */
        if (unlikely(ni.blk_addr == NULL_ADDR)) {
                ClearPageUptodate(page);
@@ -1396,11 +1550,24 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                return 0;
        }
 
+       if (__is_valid_data_blkaddr(ni.blk_addr) &&
+               !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;
 
        set_page_writeback(page);
        ClearPageError(page);
+
+       if (f2fs_in_warm_node_list(sbi, page)) {
+               seq = f2fs_add_fsync_node_entry(sbi, page);
+               if (seq_id)
+                       *seq_id = seq;
+       }
+
        fio.old_blkaddr = ni.blk_addr;
        f2fs_do_write_node_page(nid, &fio);
        set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
@@ -1448,7 +1615,7 @@ void f2fs_move_node_page(struct page *node_page, int gc_type)
                        goto out_page;
 
                if (__write_node_page(node_page, false, NULL,
-                                       &wbc, false, FS_GC_NODE_IO))
+                                       &wbc, false, FS_GC_NODE_IO, NULL))
                        unlock_page(node_page);
                goto release_page;
        } else {
@@ -1465,11 +1632,13 @@ release_page:
 static int f2fs_write_node_page(struct page *page,
                                struct writeback_control *wbc)
 {
-       return __write_node_page(page, false, NULL, wbc, false, FS_NODE_IO);
+       return __write_node_page(page, false, NULL, wbc, false,
+                                               FS_NODE_IO, NULL);
 }
 
 int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
-                       struct writeback_control *wbc, bool atomic)
+                       struct writeback_control *wbc, bool atomic,
+                       unsigned int *seq_id)
 {
        pgoff_t index;
        pgoff_t last_idx = ULONG_MAX;
@@ -1550,7 +1719,7 @@ continue_unlock:
                        ret = __write_node_page(page, atomic &&
                                                page == last_page,
                                                &submitted, wbc, true,
-                                               FS_NODE_IO);
+                                               FS_NODE_IO, seq_id);
                        if (ret) {
                                unlock_page(page);
                                f2fs_put_page(last_page, 0);
@@ -1633,7 +1802,9 @@ next_step:
                                                !is_cold_node(page)))
                                continue;
 lock_node:
-                       if (!trylock_page(page))
+                       if (wbc->sync_mode == WB_SYNC_ALL)
+                               lock_page(page);
+                       else if (!trylock_page(page))
                                continue;
 
                        if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
@@ -1665,7 +1836,7 @@ continue_unlock:
                        set_dentry_mark(page, 0);
 
                        ret = __write_node_page(page, false, &submitted,
-                                               wbc, do_balance, io_type);
+                                               wbc, do_balance, io_type, NULL);
                        if (ret)
                                unlock_page(page);
                        else if (submitted)
@@ -1684,10 +1855,12 @@ continue_unlock:
        }
 
        if (step < 2) {
+               if (wbc->sync_mode == WB_SYNC_NONE && step == 1)
+                       goto out;
                step++;
                goto next_step;
        }
-
+out:
        if (nwritten)
                f2fs_submit_merged_write(sbi, NODE);
 
@@ -1696,35 +1869,46 @@ continue_unlock:
        return ret;
 }
 
-int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
+int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi,
+                                               unsigned int seq_id)
 {
-       pgoff_t index = 0;
-       struct pagevec pvec;
+       struct fsync_node_entry *fn;
+       struct page *page;
+       struct list_head *head = &sbi->fsync_node_list;
+       unsigned long flags;
+       unsigned int cur_seq_id = 0;
        int ret2, ret = 0;
-       int nr_pages;
 
-       pagevec_init(&pvec);
+       while (seq_id && cur_seq_id < seq_id) {
+               spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       break;
+               }
+               fn = list_first_entry(head, struct fsync_node_entry, list);
+               if (fn->seq_id > seq_id) {
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       break;
+               }
+               cur_seq_id = fn->seq_id;
+               page = fn->page;
+               get_page(page);
+               spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
 
-       while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
-                               PAGECACHE_TAG_WRITEBACK))) {
-               int i;
+               f2fs_wait_on_page_writeback(page, NODE, true);
+               if (TestClearPageError(page))
+                       ret = -EIO;
 
-               for (i = 0; i < nr_pages; i++) {
-                       struct page *page = pvec.pages[i];
+               put_page(page);
 
-                       if (ino && ino_of_node(page) == ino) {
-                               f2fs_wait_on_page_writeback(page, NODE, true);
-                               if (TestClearPageError(page))
-                                       ret = -EIO;
-                       }
-               }
-               pagevec_release(&pvec);
-               cond_resched();
+               if (ret)
+                       break;
        }
 
        ret2 = filemap_check_errors(NODE_MAPPING(sbi));
        if (!ret)
                ret = ret2;
+
        return ret;
 }
 
@@ -1774,6 +1958,10 @@ static int f2fs_set_node_page_dirty(struct page *page)
 
        if (!PageUptodate(page))
                SetPageUptodate(page);
+#ifdef CONFIG_F2FS_CHECK_FS
+       if (IS_INODE(page))
+               f2fs_inode_chksum_set(F2FS_P_SB(page), page);
+#endif
        if (!PageDirty(page)) {
                __set_page_dirty_nobuffers(page);
                inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
@@ -1892,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;
@@ -1968,7 +2159,7 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid)
                kmem_cache_free(free_nid_slab, i);
 }
 
-static void scan_nat_page(struct f2fs_sb_info *sbi,
+static int scan_nat_page(struct f2fs_sb_info *sbi,
                        struct page *nat_page, nid_t start_nid)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -1986,7 +2177,10 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
                        break;
 
                blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
-               f2fs_bug_on(sbi, blk_addr == NEW_ADDR);
+
+               if (blk_addr == NEW_ADDR)
+                       return -EINVAL;
+
                if (blk_addr == NULL_ADDR) {
                        add_free_nid(sbi, start_nid, true, true);
                } else {
@@ -1995,6 +2189,8 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
                        spin_unlock(&NM_I(sbi)->nid_list_lock);
                }
        }
+
+       return 0;
 }
 
 static void scan_curseg_cache(struct f2fs_sb_info *sbi)
@@ -2050,11 +2246,11 @@ out:
        up_read(&nm_i->nat_tree_lock);
 }
 
-static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
+static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
                                                bool sync, bool mount)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
-       int i = 0;
+       int i = 0, ret;
        nid_t nid = nm_i->next_scan_nid;
 
        if (unlikely(nid >= nm_i->max_nid))
@@ -2062,17 +2258,17 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
 
        /* Enough entries */
        if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
-               return;
+               return 0;
 
        if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
-               return;
+               return 0;
 
        if (!mount) {
                /* try to find free nids in free_nid_bitmap */
                scan_free_nid_bits(sbi);
 
                if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
-                       return;
+                       return 0;
        }
 
        /* readahead nat pages to be scanned */
@@ -2086,8 +2282,16 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
                                                nm_i->nat_block_bitmap)) {
                        struct page *page = get_current_nat_page(sbi, nid);
 
-                       scan_nat_page(sbi, page, nid);
+                       ret = scan_nat_page(sbi, page, nid);
                        f2fs_put_page(page, 1);
+
+                       if (ret) {
+                               up_read(&nm_i->nat_tree_lock);
+                               f2fs_bug_on(sbi, !mount);
+                               f2fs_msg(sbi->sb, KERN_ERR,
+                                       "NAT is corrupt, run fsck to fix it");
+                               return -EINVAL;
+                       }
                }
 
                nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
@@ -2108,13 +2312,19 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
 
        f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
                                        nm_i->ra_nid_pages, META_NAT, false);
+
+       return 0;
 }
 
-void f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
+int f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
 {
+       int ret;
+
        mutex_lock(&NM_I(sbi)->build_lock);
-       __f2fs_build_free_nids(sbi, sync, mount);
+       ret = __f2fs_build_free_nids(sbi, sync, mount);
        mutex_unlock(&NM_I(sbi)->build_lock);
+
+       return ret;
 }
 
 /*
@@ -2127,12 +2337,11 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        struct free_nid *i = NULL;
 retry:
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_ALLOC_NID)) {
                f2fs_show_injection_info(FAULT_ALLOC_NID);
                return false;
        }
-#endif
+
        spin_lock(&nm_i->nid_list_lock);
 
        if (unlikely(nm_i->available_nids == 0)) {
@@ -2277,12 +2486,16 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page)
        struct dnode_of_data dn;
        struct node_info ni;
        struct page *xpage;
+       int err;
 
        if (!prev_xnid)
                goto recover_xnid;
 
        /* 1: invalidate the previous xattr nid */
-       f2fs_get_node_info(sbi, prev_xnid, &ni);
+       err = f2fs_get_node_info(sbi, prev_xnid, &ni);
+       if (err)
+               return err;
+
        f2fs_invalidate_blocks(sbi, ni.blk_addr);
        dec_valid_node_count(sbi, inode, false);
        set_node_addr(sbi, &ni, NULL_ADDR, false);
@@ -2317,8 +2530,11 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        nid_t ino = ino_of_node(page);
        struct node_info old_ni, new_ni;
        struct page *ipage;
+       int err;
 
-       f2fs_get_node_info(sbi, ino, &old_ni);
+       err = f2fs_get_node_info(sbi, ino, &old_ni);
+       if (err)
+               return err;
 
        if (unlikely(old_ni.blk_addr != NULL_ADDR))
                return -EINVAL;
@@ -2335,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);
@@ -2358,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;
@@ -2372,7 +2595,7 @@ retry:
        return 0;
 }
 
-void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
+int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                        unsigned int segno, struct f2fs_summary_block *sum)
 {
        struct f2fs_node *rn;
@@ -2394,6 +2617,9 @@ void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                for (idx = addr; idx < addr + nrpages; idx++) {
                        struct page *page = f2fs_get_tmp_page(sbi, idx);
 
+                       if (IS_ERR(page))
+                               return PTR_ERR(page);
+
                        rn = F2FS_NODE(page);
                        sum_entry->nid = rn->footer.nid;
                        sum_entry->version = 0;
@@ -2405,6 +2631,7 @@ void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                invalidate_mapping_pages(META_MAPPING(sbi), addr,
                                                        addr + nrpages);
        }
+       return 0;
 }
 
 static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
@@ -2582,6 +2809,13 @@ void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        nid_t set_idx = 0;
        LIST_HEAD(sets);
 
+       /* during unmount, let's flush nat_bits before checking dirty_nat_cnt */
+       if (enabled_nat_bits(sbi, cpc)) {
+               down_write(&nm_i->nat_tree_lock);
+               remove_nats_in_journal(sbi);
+               up_write(&nm_i->nat_tree_lock);
+       }
+
        if (!nm_i->dirty_nat_cnt)
                return;
 
@@ -2634,7 +2868,13 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
        nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg -
                                                nm_i->nat_bits_blocks;
        for (i = 0; i < nm_i->nat_bits_blocks; i++) {
-               struct page *page = f2fs_get_meta_page(sbi, nat_bits_addr++);
+               struct page *page;
+
+               page = f2fs_get_meta_page(sbi, nat_bits_addr++);
+               if (IS_ERR(page)) {
+                       disable_nat_bits(sbi, true);
+                       return PTR_ERR(page);
+               }
 
                memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS),
                                        page_address(page), F2FS_BLKSIZE);
@@ -2718,6 +2958,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
        INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO);
        INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO);
        INIT_LIST_HEAD(&nm_i->nat_entries);
+       spin_lock_init(&nm_i->nat_list_lock);
 
        mutex_init(&nm_i->build_lock);
        spin_lock_init(&nm_i->nid_list_lock);
@@ -2762,8 +3003,8 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 
        for (i = 0; i < nm_i->nat_blocks; i++) {
                nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
-                               NAT_ENTRY_BITMAP_SIZE_ALIGNED, GFP_KERNEL);
-               if (!nm_i->free_nid_bitmap)
+                       f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL);
+               if (!nm_i->free_nid_bitmap[i])
                        return -ENOMEM;
        }
 
@@ -2801,8 +3042,7 @@ int f2fs_build_node_manager(struct f2fs_sb_info *sbi)
        /* load free nid status from nat_bits table */
        load_free_nid_bitmap(sbi);
 
-       f2fs_build_free_nids(sbi, true, true);
-       return 0;
+       return f2fs_build_free_nids(sbi, true, true);
 }
 
 void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
@@ -2837,8 +3077,13 @@ void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
                unsigned idx;
 
                nid = nat_get_nid(natvec[found - 1]) + 1;
-               for (idx = 0; idx < found; idx++)
+               for (idx = 0; idx < found; idx++) {
+                       spin_lock(&nm_i->nat_list_lock);
+                       list_del(&natvec[idx]->list);
+                       spin_unlock(&nm_i->nat_list_lock);
+
                        __del_from_nat_cache(nm_i, natvec[idx]);
+               }
        }
        f2fs_bug_on(sbi, nm_i->nat_cnt);
 
@@ -2893,8 +3138,15 @@ int __init f2fs_create_node_manager_caches(void)
                        sizeof(struct nat_entry_set));
        if (!nat_entry_set_slab)
                goto destroy_free_nid;
+
+       fsync_node_entry_slab = f2fs_kmem_cache_create("fsync_node_entry",
+                       sizeof(struct fsync_node_entry));
+       if (!fsync_node_entry_slab)
+               goto destroy_nat_entry_set;
        return 0;
 
+destroy_nat_entry_set:
+       kmem_cache_destroy(nat_entry_set_slab);
 destroy_free_nid:
        kmem_cache_destroy(free_nid_slab);
 destroy_nat_entry:
@@ -2905,6 +3157,7 @@ fail:
 
 void f2fs_destroy_node_manager_caches(void)
 {
+       kmem_cache_destroy(fsync_node_entry_slab);
        kmem_cache_destroy(nat_entry_set_slab);
        kmem_cache_destroy(free_nid_slab);
        kmem_cache_destroy(nat_entry_slab);