summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/file.c
diff options
context:
space:
mode:
authorHuajun Li <huajun.li@intel.com>2013-11-10 10:13:20 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-12-26 06:40:41 -0500
commit9ffe0fb5f3bbd01c766162bb17a62dee0df7e125 (patch)
tree055460e4451d562f1a59792eeed3cb840e6c7d22 /fs/f2fs/file.c
parente18c65b2ac91aa59f89333da595d5155184f76cf (diff)
f2fs: handle inline data operations
Hook inline data read/write, truncate, fallocate, setattr, etc. Files need meet following 2 requirement to inline: 1) file size is not greater than MAX_INLINE_DATA; 2) file doesn't pre-allocate data blocks by fallocate(). FI_INLINE_DATA will not be set while creating a new regular inode because most of the files are bigger than ~3.4K. Set FI_INLINE_DATA only when data is submitted to block layer, ranther than set it while creating a new inode, this also avoids converting data from inline to normal data block and vice versa. While writting inline data to inode block, the first data block should be released if the file has a block indexed by i_addr[0]. On the other hand, when a file operation is appied to a file with inline data, we need to test if this file can remain inline by doing this operation, otherwise it should be convert into normal file by reserving a new data block, copying inline data to this new block and clear FI_INLINE_DATA flag. Because reserve a new data block here will make use of i_addr[0], if we save inline data in i_addr[0..872], then the first 4 bytes would be overwriten. This problem can be avoided simply by not using i_addr[0] for inline data. Signed-off-by: Huajun Li <huajun.li@intel.com> Signed-off-by: Haicheng Li <haicheng.li@linux.intel.com> Signed-off-by: Weihong Xu <weihong.xu@intel.com> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r--fs/f2fs/file.c45
1 files changed, 42 insertions, 3 deletions
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)
257 unsigned int blocksize = inode->i_sb->s_blocksize; 257 unsigned int blocksize = inode->i_sb->s_blocksize;
258 struct dnode_of_data dn; 258 struct dnode_of_data dn;
259 pgoff_t free_from; 259 pgoff_t free_from;
260 int count = 0; 260 int count = 0, err = 0;
261 int err;
262 261
263 trace_f2fs_truncate_blocks_enter(inode, from); 262 trace_f2fs_truncate_blocks_enter(inode, from);
264 263
@@ -266,6 +265,10 @@ static int truncate_blocks(struct inode *inode, u64 from)
266 ((from + blocksize - 1) >> (sbi->log_blocksize)); 265 ((from + blocksize - 1) >> (sbi->log_blocksize));
267 266
268 f2fs_lock_op(sbi); 267 f2fs_lock_op(sbi);
268
269 if (f2fs_has_inline_data(inode))
270 goto done;
271
269 set_new_dnode(&dn, inode, NULL, NULL, 0); 272 set_new_dnode(&dn, inode, NULL, NULL, 0);
270 err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE); 273 err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
271 if (err) { 274 if (err) {
@@ -292,6 +295,7 @@ static int truncate_blocks(struct inode *inode, u64 from)
292 f2fs_put_dnode(&dn); 295 f2fs_put_dnode(&dn);
293free_next: 296free_next:
294 err = truncate_inode_blocks(inode, free_from); 297 err = truncate_inode_blocks(inode, free_from);
298done:
295 f2fs_unlock_op(sbi); 299 f2fs_unlock_op(sbi);
296 300
297 /* lastly zero out the first data page */ 301 /* lastly zero out the first data page */
@@ -367,8 +371,17 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
367 371
368 if ((attr->ia_valid & ATTR_SIZE) && 372 if ((attr->ia_valid & ATTR_SIZE) &&
369 attr->ia_size != i_size_read(inode)) { 373 attr->ia_size != i_size_read(inode)) {
374 if (f2fs_has_inline_data(inode) &&
375 (attr->ia_size > MAX_INLINE_DATA)) {
376 unsigned flags = AOP_FLAG_NOFS;
377 err = f2fs_convert_inline_data(inode, NULL, flags);
378 if (err)
379 return err;
380 }
381
370 truncate_setsize(inode, attr->ia_size); 382 truncate_setsize(inode, attr->ia_size);
371 f2fs_truncate(inode); 383 if (!f2fs_has_inline_data(inode))
384 f2fs_truncate(inode);
372 f2fs_balance_fs(F2FS_SB(inode->i_sb)); 385 f2fs_balance_fs(F2FS_SB(inode->i_sb));
373 } 386 }
374 387
@@ -450,6 +463,26 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
450 loff_t off_start, off_end; 463 loff_t off_start, off_end;
451 int ret = 0; 464 int ret = 0;
452 465
466 if (f2fs_has_inline_data(inode)) {
467 struct page *page;
468 unsigned flags = AOP_FLAG_NOFS;
469 page = grab_cache_page_write_begin(inode->i_mapping, 0, flags);
470 if (IS_ERR(page))
471 return PTR_ERR(page);
472 if (offset + len > MAX_INLINE_DATA) {
473 ret = f2fs_convert_inline_data(inode, page, flags);
474 f2fs_put_page(page, 1);
475 if (ret)
476 return ret;
477 } else {
478 zero_user_segment(page, offset, offset + len);
479 SetPageUptodate(page);
480 set_page_dirty(page);
481 f2fs_put_page(page, 1);
482 return ret;
483 }
484 }
485
453 pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; 486 pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
454 pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; 487 pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
455 488
@@ -496,6 +529,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
496 loff_t off_start, off_end; 529 loff_t off_start, off_end;
497 int ret = 0; 530 int ret = 0;
498 531
532 if (f2fs_has_inline_data(inode) && (offset + len > MAX_INLINE_DATA)) {
533 ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS);
534 if (ret)
535 return ret;
536 }
537
499 ret = inode_newsize_ok(inode, (len + offset)); 538 ret = inode_newsize_ok(inode, (len + offset));
500 if (ret) 539 if (ret)
501 return ret; 540 return ret;