diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e0965b43d16e..bf39eed2442f 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -706,13 +706,28 @@ static int get_data_block(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); + 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); } @@ -761,7 +776,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; struct f2fs_io_info fio = { @@ -799,7 +814,15 @@ static int f2fs_write_data_page(struct page *page, 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; } @@ -888,6 +911,15 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, 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); @@ -897,7 +929,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, f2fs_put_page(page, 1); return err; } - +inline_data: if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) return 0; @@ -913,7 +945,10 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, 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; @@ -977,6 +1012,10 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, 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; diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 5accc964368d..dd80e725acb6 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -257,8 +257,7 @@ static int truncate_blocks(struct inode *inode, u64 from) 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); @@ -266,6 +265,10 @@ static int truncate_blocks(struct inode *inode, u64 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) { @@ -292,6 +295,7 @@ static int truncate_blocks(struct inode *inode, u64 from) 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 */ @@ -367,8 +371,17 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) 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)); } @@ -450,6 +463,26 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len) 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; @@ -496,6 +529,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset, 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;