f2fs: revisit error handling flows
[deliverable/linux.git] / fs / f2fs / inode.c
index 2adeff26be11b9689dde24a5d22b0bd3351c21b7..f4ac8512b7ba687515b3b06d0a306afa1dcdabf6 100644 (file)
@@ -83,7 +83,7 @@ static void __recover_inline_status(struct inode *inode, struct page *ipage)
 
        while (start < end) {
                if (*start++) {
-                       f2fs_wait_on_page_writeback(ipage, NODE);
+                       f2fs_wait_on_page_writeback(ipage, NODE, true);
 
                        set_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
                        set_raw_inline(F2FS_I(inode), F2FS_INODE(ipage));
@@ -227,7 +227,7 @@ int update_inode(struct inode *inode, struct page *node_page)
 {
        struct f2fs_inode *ri;
 
-       f2fs_wait_on_page_writeback(node_page, NODE);
+       f2fs_wait_on_page_writeback(node_page, NODE, true);
 
        ri = F2FS_INODE(node_page);
 
@@ -263,6 +263,10 @@ int update_inode(struct inode *inode, struct page *node_page)
        set_cold_node(inode, node_page);
        clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE);
 
+       /* deleted inode */
+       if (inode->i_nlink == 0)
+               clear_inline_node(node_page);
+
        return set_page_dirty(node_page);
 }
 
@@ -320,7 +324,7 @@ void f2fs_evict_inode(struct inode *inode)
 
        /* some remained atomic pages should discarded */
        if (f2fs_is_atomic_file(inode))
-               commit_inmem_pages(inode, true);
+               drop_inmem_pages(inode);
 
        trace_f2fs_evict_inode(inode);
        truncate_inode_pages_final(&inode->i_data);
@@ -364,10 +368,7 @@ no_delete:
        if (is_inode_flag_set(fi, FI_UPDATE_WRITE))
                add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
        if (is_inode_flag_set(fi, FI_FREE_NID)) {
-               if (err && err != -ENOENT)
-                       alloc_nid_done(sbi, inode->i_ino);
-               else
-                       alloc_nid_failed(sbi, inode->i_ino);
+               alloc_nid_failed(sbi, inode->i_ino);
                clear_inode_flag(fi, FI_FREE_NID);
        }
 
@@ -385,10 +386,7 @@ no_delete:
                }
        }
 out_clear:
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
-       if (fi->i_crypt_info)
-               f2fs_free_encryption_info(inode, fi->i_crypt_info);
-#endif
+       fscrypt_put_encryption_info(inode, NULL);
        clear_inode(inode);
 }
 
@@ -396,37 +394,32 @@ out_clear:
 void handle_failed_inode(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       int err = 0;
+       struct node_info ni;
 
-       clear_nlink(inode);
-       make_bad_inode(inode);
+       /* don't make bad inode, since it becomes a regular file. */
        unlock_new_inode(inode);
 
-       i_size_write(inode, 0);
-       if (F2FS_HAS_BLOCKS(inode))
-               err = f2fs_truncate(inode, false);
-
-       if (!err)
-               err = remove_inode_page(inode);
-
        /*
-        * if we skip truncate_node in remove_inode_page bacause we failed
-        * before, it's better to find another way to release resource of
-        * this inode (e.g. valid block count, node block or nid). Here we
-        * choose to add this inode to orphan list, so that we can call iput
-        * for releasing in orphan recovery flow.
-        *
         * Note: we should add inode to orphan list before f2fs_unlock_op()
         * so we can prevent losing this orphan when encoutering checkpoint
         * and following suddenly power-off.
         */
-       if (err && err != -ENOENT) {
-               err = acquire_orphan_inode(sbi);
-               if (!err)
+       get_node_info(sbi, inode->i_ino, &ni);
+
+       if (ni.blk_addr != NULL_ADDR) {
+               int err = acquire_orphan_inode(sbi);
+               if (err) {
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "Too many orphan inodes, run fsck to fix.");
+               } else {
                        add_orphan_inode(sbi, inode->i_ino);
+               }
+               alloc_nid_done(sbi, inode->i_ino);
+       } else {
+               set_inode_flag(F2FS_I(inode), FI_FREE_NID);
        }
 
-       set_inode_flag(F2FS_I(inode), FI_FREE_NID);
        f2fs_unlock_op(sbi);
 
        /* iput will drop the inode object */
This page took 0.029167 seconds and 5 git commands to generate.