Hook inline data read/write in address space operations. Signed-off-by: Huajun Li <huajun.li@xxxxxxxxx> Signed-off-by: Haicheng Li <haicheng.li@xxxxxxxxxxxxxxx> --- fs/f2fs/data.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/file.c | 9 +++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 93917e3..bac25f3 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -64,6 +64,23 @@ int reserve_new_block(struct dnode_of_data *dn) return 0; } +int f2fs_reserve_block(struct inode *inode, pgoff_t index) +{ + int err; + struct dnode_of_data dn; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, index, ALLOC_NODE); + if (err) + return err; + if (dn.data_blkaddr == NULL_ADDR) + err = reserve_new_block(&dn); + + f2fs_put_dnode(&dn); + + return err; +} + static int check_extent_cache(struct inode *inode, pgoff_t pgofs, struct buffer_head *bh_result) { @@ -461,13 +478,28 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock, static int f2fs_read_data_page(struct file *file, struct page *page) { - return mpage_readpage(page, get_data_block_ro); + int ret; + struct inode *inode = file->f_mapping->host; + + /* If the file has inline data, try to read it directlly */ + if (f2fs_has_inline_data(inode)) + ret = f2fs_read_inline_data_page(inode, page); + else + ret = mpage_readpage(page, get_data_block_ro); + + 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_ro); } @@ -517,7 +549,7 @@ static int f2fs_write_data_page(struct page *page, 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; @@ -551,7 +583,16 @@ write: err = do_write_data_page(page); } else { int ilock = mutex_lock_op(sbi); + +#ifdef CONFIG_F2FS_INLINE_DATA + if (i_size <= MAX_INLINE_DATA) + err = f2fs_write_inline_data(inode, page, offset); + else + err = do_write_data_page(page); +#else err = do_write_data_page(page); +#endif + mutex_unlock_op(sbi, ilock); need_balance_fs = true; } @@ -643,6 +684,25 @@ repeat: return -ENOMEM; *pagep = page; +#ifdef CONFIG_F2FS_INLINE_DATA + if ((pos + len) <= MAX_INLINE_DATA) { + set_inode_dyn_flag(F2FS_I(inode), F2FS_INLINE_DATA_ATTEMPT); + goto inline_data; + } else if (f2fs_has_inline_data(inode)) { + err = f2fs_convert_inline_data(page, inode, flags); + if (err) + return err; + } else if (f2fs_inline_data_attempt(inode)) { + clear_inode_dyn_flag(F2FS_I(inode), F2FS_INLINE_DATA_ATTEMPT); + + ilock = mutex_lock_op(sbi); + err = f2fs_reserve_block(inode, 0); + if (err) + goto err; + mutex_unlock_op(sbi, ilock); + } +#endif + ilock = mutex_lock_op(sbi); set_new_dnode(&dn, inode, NULL, NULL, 0); @@ -659,6 +719,7 @@ repeat: mutex_unlock_op(sbi, ilock); +inline_data: if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) return 0; @@ -674,7 +735,16 @@ repeat: if (dn.data_blkaddr == NEW_ADDR) { zero_user_segment(page, 0, PAGE_CACHE_SIZE); } else { +#ifdef CONFIG_F2FS_INLINE_DATA + if ((pos + len) <= MAX_INLINE_DATA) + err = f2fs_read_inline_data_page(inode, page); + else + err = f2fs_readpage(sbi, page, + dn.data_blkaddr, READ_SYNC); +#else err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC); +#endif + if (err) return err; lock_page(page); @@ -707,6 +777,10 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, if (rw == WRITE) return 0; + /* Let buffer I/O handle the inline data case. */ + if (f2fs_has_inline_data(inode)) + return 0; + /* Needs synchronization with the cleaner */ return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, get_data_block_ro); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index deefd25..03b13b3 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -178,6 +178,9 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) raw_node = page_address(dn->node_page); addr = blkaddr_in_node(raw_node) + ofs; + if (f2fs_has_inline_data(dn->inode)) + return nr_free; + for ( ; count > 0; count--, addr++, dn->ofs_in_node++) { block_t blkaddr = le32_to_cpu(*addr); if (blkaddr == NULL_ADDR) @@ -267,11 +270,13 @@ static int truncate_blocks(struct inode *inode, u64 from) f2fs_put_dnode(&dn); free_next: - err = truncate_inode_blocks(inode, free_from); + if (!f2fs_has_inline_data(inode)) + err = truncate_inode_blocks(inode, free_from); mutex_unlock_op(sbi, ilock); /* lastly zero out the first data page */ - truncate_partial_data_page(inode, from); + if (!f2fs_has_inline_data(inode)) + truncate_partial_data_page(inode, from); trace_f2fs_truncate_blocks_exit(inode, err); return err; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html