static int f2fs_read_data_page(struct file *file, struct page *page)
 {
-       return mpage_readpage(page, get_data_block);
+       struct inode *inode = page->mapping->host;
+       int ret;
+
+       /* If the file has inline data, try to read it directlly */
+       if (f2fs_has_inline_data(inode))
+               ret = f2fs_read_inline_data(inode, page);
+       else
+               ret = mpage_readpage(page, get_data_block);
+
+       return ret;
 }
 
 static int f2fs_read_data_pages(struct file *file,
                        struct address_space *mapping,
                        struct list_head *pages, unsigned nr_pages)
 {
+       struct inode *inode = file->f_mapping->host;
+
+       /* If the file has inline data, skip readpages */
+       if (f2fs_has_inline_data(inode))
+               return 0;
+
        return mpage_readpages(mapping, pages, nr_pages, get_data_block);
 }
 
        loff_t i_size = i_size_read(inode);
        const pgoff_t end_index = ((unsigned long long) i_size)
                                                        >> PAGE_CACHE_SHIFT;
-       unsigned offset;
+       unsigned offset = 0;
        bool need_balance_fs = false;
        int err = 0;
        struct f2fs_io_info fio = {
                err = do_write_data_page(page, &fio);
        } else {
                f2fs_lock_op(sbi);
-               err = do_write_data_page(page, &fio);
+
+               if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode)) {
+                       err = f2fs_write_inline_data(inode, page, offset);
+                       f2fs_unlock_op(sbi);
+                       goto out;
+               } else {
+                       err = do_write_data_page(page, &fio);
+               }
+
                f2fs_unlock_op(sbi);
                need_balance_fs = true;
        }
                return -ENOMEM;
        *pagep = page;
 
+       if ((pos + len) < MAX_INLINE_DATA) {
+               if (f2fs_has_inline_data(inode))
+                       goto inline_data;
+       } else if (f2fs_has_inline_data(inode)) {
+               err = f2fs_convert_inline_data(inode, page, flags);
+               if (err)
+                       return err;
+       }
+
        f2fs_lock_op(sbi);
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = f2fs_reserve_block(&dn, index);
                f2fs_put_page(page, 1);
                return err;
        }
-
+inline_data:
        if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
                return 0;
 
        if (dn.data_blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_CACHE_SIZE);
        } else {
-               err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
+               if (f2fs_has_inline_data(inode))
+                       err = f2fs_read_inline_data(inode, page);
+               else
+                       err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
                                                        READ_SYNC);
                if (err)
                        return err;
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
 
+       /* Let buffer I/O handle the inline data case. */
+       if (f2fs_has_inline_data(inode))
+               return 0;
+
        if (check_direct_IO(inode, rw, iov, offset, nr_segs))
                return 0;
 
 
        unsigned int blocksize = inode->i_sb->s_blocksize;
        struct dnode_of_data dn;
        pgoff_t free_from;
-       int count = 0;
-       int err;
+       int count = 0, err = 0;
 
        trace_f2fs_truncate_blocks_enter(inode, from);
 
                        ((from + blocksize - 1) >> (sbi->log_blocksize));
 
        f2fs_lock_op(sbi);
+
+       if (f2fs_has_inline_data(inode))
+               goto done;
+
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
        if (err) {
        f2fs_put_dnode(&dn);
 free_next:
        err = truncate_inode_blocks(inode, free_from);
+done:
        f2fs_unlock_op(sbi);
 
        /* lastly zero out the first data page */
 
        if ((attr->ia_valid & ATTR_SIZE) &&
                        attr->ia_size != i_size_read(inode)) {
+               if (f2fs_has_inline_data(inode) &&
+                               (attr->ia_size > MAX_INLINE_DATA)) {
+                       unsigned flags = AOP_FLAG_NOFS;
+                       err = f2fs_convert_inline_data(inode, NULL, flags);
+                       if (err)
+                               return err;
+               }
+
                truncate_setsize(inode, attr->ia_size);
-               f2fs_truncate(inode);
+               if (!f2fs_has_inline_data(inode))
+                       f2fs_truncate(inode);
                f2fs_balance_fs(F2FS_SB(inode->i_sb));
        }
 
        loff_t off_start, off_end;
        int ret = 0;
 
+       if (f2fs_has_inline_data(inode)) {
+               struct page *page;
+               unsigned flags = AOP_FLAG_NOFS;
+               page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
+               if (IS_ERR(page))
+                       return PTR_ERR(page);
+               if (offset + len > MAX_INLINE_DATA) {
+                       ret = f2fs_convert_inline_data(inode, page, flags);
+                       f2fs_put_page(page, 1);
+                       if (ret)
+                               return ret;
+               } else {
+                       zero_user_segment(page, offset, offset + len);
+                       SetPageUptodate(page);
+                       set_page_dirty(page);
+                       f2fs_put_page(page, 1);
+                       return ret;
+               }
+       }
+
        pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
        pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
 
        loff_t off_start, off_end;
        int ret = 0;
 
+       if (f2fs_has_inline_data(inode) && (offset + len > MAX_INLINE_DATA)) {
+               ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
+               if (ret)
+                       return ret;
+       }
+
        ret = inode_newsize_ok(inode, (len + offset));
        if (ret)
                return ret;