trace_f2fs_register_inmem_page(page, INMEM);
 }
 
-static void __revoke_inmem_pages(struct inode *inode,
-                                                       struct list_head *head)
+static int __revoke_inmem_pages(struct inode *inode,
+                               struct list_head *head, bool drop, bool recover)
 {
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct inmem_pages *cur, *tmp;
+       int err = 0;
 
        list_for_each_entry_safe(cur, tmp, head, list) {
-               trace_f2fs_commit_inmem_page(cur->page, INMEM_DROP);
+               struct page *page = cur->page;
+
+               if (drop)
+                       trace_f2fs_commit_inmem_page(page, INMEM_DROP);
+
+               lock_page(page);
 
-               lock_page(cur->page);
-               ClearPageUptodate(cur->page);
-               set_page_private(cur->page, 0);
-               ClearPagePrivate(cur->page);
-               f2fs_put_page(cur->page, 1);
+               if (recover) {
+                       struct dnode_of_data dn;
+                       struct node_info ni;
+
+                       trace_f2fs_commit_inmem_page(page, INMEM_REVOKE);
+
+                       set_new_dnode(&dn, inode, NULL, NULL, 0);
+                       if (get_dnode_of_data(&dn, page->index, LOOKUP_NODE)) {
+                               err = -EAGAIN;
+                               goto next;
+                       }
+                       get_node_info(sbi, dn.nid, &ni);
+                       f2fs_replace_block(sbi, &dn, dn.data_blkaddr,
+                                       cur->old_addr, ni.version, true, true);
+                       f2fs_put_dnode(&dn);
+               }
+next:
+               ClearPageUptodate(page);
+               set_page_private(page, 0);
+               ClearPageUptodate(page);
+               f2fs_put_page(page, 1);
 
                list_del(&cur->list);
                kmem_cache_free(inmem_entry_slab, cur);
                dec_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
        }
+       return err;
 }
 
 void drop_inmem_pages(struct inode *inode)
        struct f2fs_inode_info *fi = F2FS_I(inode);
 
        mutex_lock(&fi->inmem_lock);
-       __revoke_inmem_pages(inode, &fi->inmem_pages);
+       __revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
        mutex_unlock(&fi->inmem_lock);
 }
 
-static int __commit_inmem_pages(struct inode *inode)
+static int __commit_inmem_pages(struct inode *inode,
+                                       struct list_head *revoke_list)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct f2fs_inode_info *fi = F2FS_I(inode);
        int err = 0;
 
        list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) {
-               lock_page(cur->page);
-               if (cur->page->mapping == inode->i_mapping) {
-                       set_page_dirty(cur->page);
-                       f2fs_wait_on_page_writeback(cur->page, DATA, true);
-                       if (clear_page_dirty_for_io(cur->page))
+               struct page *page = cur->page;
+
+               lock_page(page);
+               if (page->mapping == inode->i_mapping) {
+                       trace_f2fs_commit_inmem_page(page, INMEM);
+
+                       set_page_dirty(page);
+                       f2fs_wait_on_page_writeback(page, DATA, true);
+                       if (clear_page_dirty_for_io(page))
                                inode_dec_dirty_pages(inode);
-                       trace_f2fs_commit_inmem_page(cur->page, INMEM);
-                       fio.page = cur->page;
+
+                       fio.page = page;
                        err = do_write_data_page(&fio);
                        if (err) {
-                               unlock_page(cur->page);
+                               unlock_page(page);
                                break;
                        }
-                       clear_cold_data(cur->page);
-                       submit_bio = true;
-               }
 
-               set_page_private(cur->page, 0);
-               ClearPagePrivate(cur->page);
-               f2fs_put_page(cur->page, 1);
+                       /* record old blkaddr for revoking */
+                       cur->old_addr = fio.old_blkaddr;
 
-               list_del(&cur->list);
-               kmem_cache_free(inmem_entry_slab, cur);
-               dec_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
+                       clear_cold_data(page);
+                       submit_bio = true;
+               }
+               unlock_page(page);
+               list_move_tail(&cur->list, revoke_list);
        }
 
        if (submit_bio)
                f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, DATA, WRITE);
+
+       if (!err)
+               __revoke_inmem_pages(inode, revoke_list, false, false);
+
        return err;
 }
 
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct f2fs_inode_info *fi = F2FS_I(inode);
-       int err = 0;
+       struct list_head revoke_list;
+       int err;
 
+       INIT_LIST_HEAD(&revoke_list);
        f2fs_balance_fs(sbi, true);
        f2fs_lock_op(sbi);
 
        mutex_lock(&fi->inmem_lock);
-       err = __commit_inmem_pages(inode);
+       err = __commit_inmem_pages(inode, &revoke_list);
+       if (err) {
+               int ret;
+               /*
+                * try to revoke all committed pages, but still we could fail
+                * due to no memory or other reason, if that happened, EAGAIN
+                * will be returned, which means in such case, transaction is
+                * already not integrity, caller should use journal to do the
+                * recovery or rewrite & commit last transaction. For other
+                * error number, revoking was done by filesystem itself.
+                */
+               ret = __revoke_inmem_pages(inode, &revoke_list, false, true);
+               if (ret)
+                       err = ret;
+
+               /* drop all uncommitted pages */
+               __revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
+       }
        mutex_unlock(&fi->inmem_lock);
 
        f2fs_unlock_op(sbi);
 static void __f2fs_replace_block(struct f2fs_sb_info *sbi,
                                struct f2fs_summary *sum,
                                block_t old_blkaddr, block_t new_blkaddr,
-                               bool recover_curseg)
+                               bool recover_curseg, bool recover_newaddr)
 {
        struct sit_info *sit_i = SIT_I(sbi);
        struct curseg_info *curseg;
        curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
        __add_sum_entry(sbi, type, sum);
 
-       if (!recover_curseg)
+       if (!recover_curseg || recover_newaddr)
                update_sit_entry(sbi, new_blkaddr, 1);
        if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
                update_sit_entry(sbi, old_blkaddr, -1);
 
 void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
                                block_t old_addr, block_t new_addr,
-                               unsigned char version, bool recover_curseg)
+                               unsigned char version, bool recover_curseg,
+                               bool recover_newaddr)
 {
        struct f2fs_summary sum;
 
        set_summary(&sum, dn->nid, dn->ofs_in_node, version);
 
-       __f2fs_replace_block(sbi, &sum, old_addr, new_addr, recover_curseg);
+       __f2fs_replace_block(sbi, &sum, old_addr, new_addr,
+                                       recover_curseg, recover_newaddr);
 
        dn->data_blkaddr = new_addr;
        set_data_blkaddr(dn);