write:
        if (unlikely(sbi->por_doing))
                goto redirty_out;
+       if (f2fs_is_drop_cache(inode))
+               goto out;
+       if (f2fs_is_volatile_file(inode) && !wbc->for_reclaim &&
+                       available_free_memory(sbi, BASE_CHECK))
+               goto redirty_out;
 
        /* Dentry blocks are controlled by checkpoint */
        if (S_ISDIR(inode->i_mode)) {
        if (offset % PAGE_CACHE_SIZE || length != PAGE_CACHE_SIZE)
                return;
 
-       if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
+       if (f2fs_is_atomic_file(inode))
                invalidate_inmem_page(inode, page);
 
        if (PageDirty(page))
 
        SetPageUptodate(page);
 
-       if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) {
+       if (f2fs_is_atomic_file(inode)) {
                register_inmem_page(inode, page);
                return 1;
        }
 
 #define F2FS_IOC_START_ATOMIC_WRITE    _IO(F2FS_IOCTL_MAGIC, 1)
 #define F2FS_IOC_COMMIT_ATOMIC_WRITE   _IO(F2FS_IOCTL_MAGIC, 2)
 #define F2FS_IOC_START_VOLATILE_WRITE  _IO(F2FS_IOCTL_MAGIC, 3)
+#define F2FS_IOC_RELEASE_VOLATILE_WRITE        _IO(F2FS_IOCTL_MAGIC, 4)
+#define F2FS_IOC_ABORT_VOLATILE_WRITE  _IO(F2FS_IOCTL_MAGIC, 5)
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
        FI_NEED_IPU,            /* used for ipu per file */
        FI_ATOMIC_FILE,         /* indicate atomic file */
        FI_VOLATILE_FILE,       /* indicate volatile file */
+       FI_DROP_CACHE,          /* drop dirty page cache */
        FI_DATA_EXIST,          /* indicate data exists */
 };
 
        return is_inode_flag_set(F2FS_I(inode), FI_VOLATILE_FILE);
 }
 
+static inline bool f2fs_is_drop_cache(struct inode *inode)
+{
+       return is_inode_flag_set(F2FS_I(inode), FI_DROP_CACHE);
+}
+
 static inline void *inline_data_addr(struct page *page)
 {
        struct f2fs_inode *ri = F2FS_INODE(page);
 
        return ret;
 }
 
+static int f2fs_release_file(struct inode *inode, struct file *filp)
+{
+       /* some remained atomic pages should discarded */
+       if (f2fs_is_atomic_file(inode))
+               commit_inmem_pages(inode, true);
+       if (f2fs_is_volatile_file(inode)) {
+               set_inode_flag(F2FS_I(inode), FI_DROP_CACHE);
+               filemap_fdatawrite(inode->i_mapping);
+               clear_inode_flag(F2FS_I(inode), FI_DROP_CACHE);
+       }
+       return 0;
+}
+
 #define F2FS_REG_FLMASK                (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
 #define F2FS_OTHER_FLMASK      (FS_NODUMP_FL | FS_NOATIME_FL)
 
 static int f2fs_ioc_start_atomic_write(struct file *filp)
 {
        struct inode *inode = file_inode(filp);
-       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 
        if (!inode_owner_or_capable(inode))
                return -EACCES;
 
-       f2fs_balance_fs(sbi);
+       f2fs_balance_fs(F2FS_I_SB(inode));
+
+       if (f2fs_is_atomic_file(inode))
+               return 0;
 
        set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
 
        return f2fs_convert_inline_inode(inode);
 }
 
-static int f2fs_release_file(struct inode *inode, struct file *filp)
-{
-       /* some remained atomic pages should discarded */
-       if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
-               commit_inmem_pages(inode, true);
-       return 0;
-}
-
 static int f2fs_ioc_commit_atomic_write(struct file *filp)
 {
        struct inode *inode = file_inode(filp);
 
        ret = f2fs_sync_file(filp, 0, LONG_MAX, 0);
        mnt_drop_write_file(filp);
+       clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
        return ret;
 }
 
        if (!inode_owner_or_capable(inode))
                return -EACCES;
 
+       if (f2fs_is_volatile_file(inode))
+               return 0;
+
        set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
 
        return f2fs_convert_inline_inode(inode);
 }
 
+static int f2fs_ioc_release_volatile_write(struct file *filp)
+{
+       struct inode *inode = file_inode(filp);
+
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+
+       if (!f2fs_is_volatile_file(inode))
+               return 0;
+
+       punch_hole(inode, 0, F2FS_BLKSIZE);
+       return 0;
+}
+
+static int f2fs_ioc_abort_volatile_write(struct file *filp)
+{
+       struct inode *inode = file_inode(filp);
+       int ret;
+
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+
+       ret = mnt_want_write_file(filp);
+       if (ret)
+               return ret;
+
+       f2fs_balance_fs(F2FS_I_SB(inode));
+
+       if (f2fs_is_atomic_file(inode)) {
+               commit_inmem_pages(inode, false);
+               clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
+       }
+
+       if (f2fs_is_volatile_file(inode)) {
+               clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
+               filemap_fdatawrite(inode->i_mapping);
+               set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
+       }
+       mnt_drop_write_file(filp);
+       return ret;
+}
+
 static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
                return f2fs_ioc_commit_atomic_write(filp);
        case F2FS_IOC_START_VOLATILE_WRITE:
                return f2fs_ioc_start_volatile_write(filp);
+       case F2FS_IOC_RELEASE_VOLATILE_WRITE:
+               return f2fs_ioc_release_volatile_write(filp);
+       case F2FS_IOC_ABORT_VOLATILE_WRITE:
+               return f2fs_ioc_abort_volatile_write(filp);
        case FITRIM:
                return f2fs_ioc_fitrim(filp, arg);
        default: