aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-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:
706 706
707static int f2fs_read_data_page(struct file *file, struct page *page) 707static int f2fs_read_data_page(struct file *file, struct page *page)
708{ 708{
709 return mpage_readpage(page, get_data_block); 709 struct inode *inode = page->mapping->host;
710 int ret;
711
712 /* If the file has inline data, try to read it directlly */
713 if (f2fs_has_inline_data(inode))
714 ret = f2fs_read_inline_data(inode, page);
715 else
716 ret = mpage_readpage(page, get_data_block);
717
718 return ret;
710} 719}
711 720
712static int f2fs_read_data_pages(struct file *file, 721static int f2fs_read_data_pages(struct file *file,
713 struct address_space *mapping, 722 struct address_space *mapping,
714 struct list_head *pages, unsigned nr_pages) 723 struct list_head *pages, unsigned nr_pages)
715{ 724{
725 struct inode *inode = file->f_mapping->host;
726
727 /* If the file has inline data, skip readpages */
728 if (f2fs_has_inline_data(inode))
729 return 0;
730
716 return mpage_readpages(mapping, pages, nr_pages, get_data_block); 731 return mpage_readpages(mapping, pages, nr_pages, get_data_block);
717} 732}
718 733
@@ -761,7 +776,7 @@ static int f2fs_write_data_page(struct page *page,
761 loff_t i_size = i_size_read(inode); 776 loff_t i_size = i_size_read(inode);
762 const pgoff_t end_index = ((unsigned long long) i_size) 777 const pgoff_t end_index = ((unsigned long long) i_size)
763 >> PAGE_CACHE_SHIFT; 778 >> PAGE_CACHE_SHIFT;
764 unsigned offset; 779 unsigned offset = 0;
765 bool need_balance_fs = false; 780 bool need_balance_fs = false;
766 int err = 0; 781 int err = 0;
767 struct f2fs_io_info fio = { 782 struct f2fs_io_info fio = {
@@ -799,7 +814,15 @@ write:
799 err = do_write_data_page(page, &fio); 814 err = do_write_data_page(page, &fio);
800 } else { 815 } else {
801 f2fs_lock_op(sbi); 816 f2fs_lock_op(sbi);
802 err = do_write_data_page(page, &fio); 817
818 if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode)) {
819 err = f2fs_write_inline_data(inode, page, offset);
820 f2fs_unlock_op(sbi);
821 goto out;
822 } else {
823 err = do_write_data_page(page, &fio);
824 }
825
803 f2fs_unlock_op(sbi); 826 f2fs_unlock_op(sbi);
804 need_balance_fs = true; 827 need_balance_fs = true;
805 } 828 }
@@ -888,6 +911,15 @@ repeat:
888 return -ENOMEM; 911 return -ENOMEM;
889 *pagep = page; 912 *pagep = page;
890 913
914 if ((pos + len) < MAX_INLINE_DATA) {
915 if (f2fs_has_inline_data(inode))
916 goto inline_data;
917 } else if (f2fs_has_inline_data(inode)) {
918 err = f2fs_convert_inline_data(inode, page, flags);
919 if (err)
920 return err;
921 }
922
891 f2fs_lock_op(sbi); 923 f2fs_lock_op(sbi);
892 set_new_dnode(&dn, inode, NULL, NULL, 0); 924 set_new_dnode(&dn, inode, NULL, NULL, 0);
893 err = f2fs_reserve_block(&dn, index); 925 err = f2fs_reserve_block(&dn, index);
@@ -897,7 +929,7 @@ repeat:
897 f2fs_put_page(page, 1); 929 f2fs_put_page(page, 1);
898 return err; 930 return err;
899 } 931 }
900 932inline_data:
901 if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) 933 if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
902 return 0; 934 return 0;
903 935
@@ -913,7 +945,10 @@ repeat:
913 if (dn.data_blkaddr == NEW_ADDR) { 945 if (dn.data_blkaddr == NEW_ADDR) {
914 zero_user_segment(page, 0, PAGE_CACHE_SIZE); 946 zero_user_segment(page, 0, PAGE_CACHE_SIZE);
915 } else { 947 } else {
916 err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, 948 if (f2fs_has_inline_data(inode))
949 err = f2fs_read_inline_data(inode, page);
950 else
951 err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
917 READ_SYNC); 952 READ_SYNC);
918 if (err) 953 if (err)
919 return err; 954 return err;
@@ -977,6 +1012,10 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
977 struct file *file = iocb->ki_filp; 1012 struct file *file = iocb->ki_filp;
978 struct inode *inode = file->f_mapping->host; 1013 struct inode *inode = file->f_mapping->host;
979 1014
1015 /* Let buffer I/O handle the inline data case. */
1016 if (f2fs_has_inline_data(inode))
1017 return 0;
1018
980 if (check_direct_IO(inode, rw, iov, offset, nr_segs)) 1019 if (check_direct_IO(inode, rw, iov, offset, nr_segs))
981 return 0; 1020 return 0;
982 1021
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;