diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-26 22:28:59 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-01-06 02:42:19 -0500 |
commit | 9e09fc855dd6f6ed510b3db7f3c3c1dd73631ac7 (patch) | |
tree | 85c3dddd41255d4ba8d83583f0550b1693338209 | |
parent | 26f466f4a948ddc765f9b474ad6e0bdb94fb1a66 (diff) |
f2fs: refactor f2fs_convert_inline_data
Change log from v1:
o handle NULL pointer of grab_cache_page_write_begin() pointed by Chao Yu.
This patch refactors f2fs_convert_inline_data to check a couple of conditions
internally for deciding whether it needs to convert inline_data or not.
So, the new f2fs_convert_inline_data initially checks:
1) f2fs_has_inline_data(), and
2) the data size to be changed.
If the inode has inline_data but the size to fill is less than MAX_INLINE_DATA,
then we don't need to convert the inline_data with data allocation.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r-- | fs/f2fs/data.c | 16 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/file.c | 25 | ||||
-rw-r--r-- | fs/f2fs/inline.c | 26 |
4 files changed, 28 insertions, 41 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 253e6633dbf6..fc7a28c5ad23 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -906,21 +906,17 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
906 | 906 | ||
907 | f2fs_balance_fs(sbi); | 907 | f2fs_balance_fs(sbi); |
908 | repeat: | 908 | repeat: |
909 | err = f2fs_convert_inline_data(inode, pos + len); | ||
910 | if (err) | ||
911 | return err; | ||
912 | |||
909 | page = grab_cache_page_write_begin(mapping, index, flags); | 913 | page = grab_cache_page_write_begin(mapping, index, flags); |
910 | if (!page) | 914 | if (!page) |
911 | return -ENOMEM; | 915 | return -ENOMEM; |
912 | *pagep = page; | 916 | *pagep = page; |
913 | 917 | ||
914 | if ((pos + len) < MAX_INLINE_DATA) { | 918 | if (f2fs_has_inline_data(inode) && (pos + len) <= MAX_INLINE_DATA) |
915 | if (f2fs_has_inline_data(inode)) | 919 | goto inline_data; |
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 | f2fs_put_page(page, 1); | ||
921 | return err; | ||
922 | } | ||
923 | } | ||
924 | 920 | ||
925 | f2fs_lock_op(sbi); | 921 | f2fs_lock_op(sbi); |
926 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 922 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b01ccaa73b23..af35039c38f8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -1302,6 +1302,6 @@ extern const struct inode_operations f2fs_special_inode_operations; | |||
1302 | inline int f2fs_has_inline_data(struct inode *); | 1302 | inline int f2fs_has_inline_data(struct inode *); |
1303 | bool f2fs_may_inline(struct inode *); | 1303 | bool f2fs_may_inline(struct inode *); |
1304 | int f2fs_read_inline_data(struct inode *, struct page *); | 1304 | int f2fs_read_inline_data(struct inode *, struct page *); |
1305 | int f2fs_convert_inline_data(struct inode *, struct page *, unsigned); | 1305 | int f2fs_convert_inline_data(struct inode *, pgoff_t); |
1306 | int f2fs_write_inline_data(struct inode *, struct page *, unsigned int); | 1306 | int f2fs_write_inline_data(struct inode *, struct page *, unsigned int); |
1307 | #endif | 1307 | #endif |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f64a1c8291af..68dd7bfce1a1 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -370,17 +370,12 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) | |||
370 | 370 | ||
371 | if ((attr->ia_valid & ATTR_SIZE) && | 371 | if ((attr->ia_valid & ATTR_SIZE) && |
372 | attr->ia_size != i_size_read(inode)) { | 372 | attr->ia_size != i_size_read(inode)) { |
373 | if (f2fs_has_inline_data(inode) && | 373 | err = f2fs_convert_inline_data(inode, attr->ia_size); |
374 | (attr->ia_size > MAX_INLINE_DATA)) { | 374 | if (err) |
375 | unsigned flags = AOP_FLAG_NOFS; | 375 | return err; |
376 | err = f2fs_convert_inline_data(inode, NULL, flags); | ||
377 | if (err) | ||
378 | return err; | ||
379 | } | ||
380 | 376 | ||
381 | truncate_setsize(inode, attr->ia_size); | 377 | truncate_setsize(inode, attr->ia_size); |
382 | if (!f2fs_has_inline_data(inode)) | 378 | f2fs_truncate(inode); |
383 | f2fs_truncate(inode); | ||
384 | f2fs_balance_fs(F2FS_SB(inode->i_sb)); | 379 | f2fs_balance_fs(F2FS_SB(inode->i_sb)); |
385 | } | 380 | } |
386 | 381 | ||
@@ -462,7 +457,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
462 | loff_t off_start, off_end; | 457 | loff_t off_start, off_end; |
463 | int ret = 0; | 458 | int ret = 0; |
464 | 459 | ||
465 | ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS); | 460 | ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1); |
466 | if (ret) | 461 | if (ret) |
467 | return ret; | 462 | return ret; |
468 | 463 | ||
@@ -512,16 +507,14 @@ static int expand_inode_data(struct inode *inode, loff_t offset, | |||
512 | loff_t off_start, off_end; | 507 | loff_t off_start, off_end; |
513 | int ret = 0; | 508 | int ret = 0; |
514 | 509 | ||
515 | if (f2fs_has_inline_data(inode) && (offset + len > MAX_INLINE_DATA)) { | ||
516 | ret = f2fs_convert_inline_data(inode, NULL, AOP_FLAG_NOFS); | ||
517 | if (ret) | ||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | ret = inode_newsize_ok(inode, (len + offset)); | 510 | ret = inode_newsize_ok(inode, (len + offset)); |
522 | if (ret) | 511 | if (ret) |
523 | return ret; | 512 | return ret; |
524 | 513 | ||
514 | ret = f2fs_convert_inline_data(inode, offset + len); | ||
515 | if (ret) | ||
516 | return ret; | ||
517 | |||
525 | pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; | 518 | pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; |
526 | pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; | 519 | pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; |
527 | 520 | ||
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 62c72aa84acc..e8891aa3ab8c 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c | |||
@@ -101,6 +101,7 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page) | |||
101 | dst_addr = kmap(page); | 101 | dst_addr = kmap(page); |
102 | memcpy(dst_addr, src_addr, MAX_INLINE_DATA); | 102 | memcpy(dst_addr, src_addr, MAX_INLINE_DATA); |
103 | kunmap(page); | 103 | kunmap(page); |
104 | SetPageUptodate(page); | ||
104 | 105 | ||
105 | /* write data page to try to make data consistent */ | 106 | /* write data page to try to make data consistent */ |
106 | set_page_writeback(page); | 107 | set_page_writeback(page); |
@@ -120,25 +121,22 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page) | |||
120 | return err; | 121 | return err; |
121 | } | 122 | } |
122 | 123 | ||
123 | int f2fs_convert_inline_data(struct inode *inode, | 124 | int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size) |
124 | struct page *p, unsigned flags) | ||
125 | { | 125 | { |
126 | int err; | ||
127 | struct page *page; | 126 | struct page *page; |
127 | int err; | ||
128 | 128 | ||
129 | if (!p || p->index) { | 129 | if (!f2fs_has_inline_data(inode)) |
130 | page = grab_cache_page_write_begin(inode->i_mapping, 0, flags); | 130 | return 0; |
131 | if (IS_ERR(page)) | 131 | else if (to_size <= MAX_INLINE_DATA) |
132 | return PTR_ERR(page); | 132 | return 0; |
133 | } else { | ||
134 | page = p; | ||
135 | } | ||
136 | |||
137 | err = __f2fs_convert_inline_data(inode, page); | ||
138 | 133 | ||
139 | if (!p || p->index) | 134 | page = grab_cache_page_write_begin(inode->i_mapping, 0, AOP_FLAG_NOFS); |
140 | f2fs_put_page(page, 1); | 135 | if (!page) |
136 | return -ENOMEM; | ||
141 | 137 | ||
138 | err = __f2fs_convert_inline_data(inode, page); | ||
139 | f2fs_put_page(page, 1); | ||
142 | return err; | 140 | return err; |
143 | } | 141 | } |
144 | 142 | ||