aboutsummaryrefslogtreecommitdiff
path: root/fs/f2fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c49
-rw-r--r--fs/f2fs/file.c45
2 files changed, 86 insertions, 8 deletions
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 @@ out:
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 @@ write:
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 @@ repeat:
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 @@ repeat:
f2fs_put_page(page, 1);
return err;
}
-
+inline_data:
if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
return 0;
@@ -913,7 +945,10 @@ repeat:
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;