diff options
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r-- | fs/f2fs/data.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 91ff93b0b0f4..035f9a345cdf 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -68,7 +68,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
68 | struct buffer_head *bh_result) | 68 | struct buffer_head *bh_result) |
69 | { | 69 | { |
70 | struct f2fs_inode_info *fi = F2FS_I(inode); | 70 | struct f2fs_inode_info *fi = F2FS_I(inode); |
71 | #ifdef CONFIG_F2FS_STAT_FS | ||
71 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 72 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
73 | #endif | ||
72 | pgoff_t start_fofs, end_fofs; | 74 | pgoff_t start_fofs, end_fofs; |
73 | block_t start_blkaddr; | 75 | block_t start_blkaddr; |
74 | 76 | ||
@@ -78,7 +80,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
78 | return 0; | 80 | return 0; |
79 | } | 81 | } |
80 | 82 | ||
83 | #ifdef CONFIG_F2FS_STAT_FS | ||
81 | sbi->total_hit_ext++; | 84 | sbi->total_hit_ext++; |
85 | #endif | ||
82 | start_fofs = fi->ext.fofs; | 86 | start_fofs = fi->ext.fofs; |
83 | end_fofs = fi->ext.fofs + fi->ext.len - 1; | 87 | end_fofs = fi->ext.fofs + fi->ext.len - 1; |
84 | start_blkaddr = fi->ext.blk_addr; | 88 | start_blkaddr = fi->ext.blk_addr; |
@@ -96,7 +100,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
96 | else | 100 | else |
97 | bh_result->b_size = UINT_MAX; | 101 | bh_result->b_size = UINT_MAX; |
98 | 102 | ||
103 | #ifdef CONFIG_F2FS_STAT_FS | ||
99 | sbi->read_hit_ext++; | 104 | sbi->read_hit_ext++; |
105 | #endif | ||
100 | read_unlock(&fi->ext.ext_lock); | 106 | read_unlock(&fi->ext.ext_lock); |
101 | return 1; | 107 | return 1; |
102 | } | 108 | } |
@@ -199,7 +205,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) | |||
199 | if (dn.data_blkaddr == NEW_ADDR) | 205 | if (dn.data_blkaddr == NEW_ADDR) |
200 | return ERR_PTR(-EINVAL); | 206 | return ERR_PTR(-EINVAL); |
201 | 207 | ||
202 | page = grab_cache_page(mapping, index); | 208 | page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS); |
203 | if (!page) | 209 | if (!page) |
204 | return ERR_PTR(-ENOMEM); | 210 | return ERR_PTR(-ENOMEM); |
205 | 211 | ||
@@ -233,18 +239,23 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index) | |||
233 | struct page *page; | 239 | struct page *page; |
234 | int err; | 240 | int err; |
235 | 241 | ||
242 | repeat: | ||
243 | page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS); | ||
244 | if (!page) | ||
245 | return ERR_PTR(-ENOMEM); | ||
246 | |||
236 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 247 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
237 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); | 248 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); |
238 | if (err) | 249 | if (err) { |
250 | f2fs_put_page(page, 1); | ||
239 | return ERR_PTR(err); | 251 | return ERR_PTR(err); |
252 | } | ||
240 | f2fs_put_dnode(&dn); | 253 | f2fs_put_dnode(&dn); |
241 | 254 | ||
242 | if (dn.data_blkaddr == NULL_ADDR) | 255 | if (dn.data_blkaddr == NULL_ADDR) { |
256 | f2fs_put_page(page, 1); | ||
243 | return ERR_PTR(-ENOENT); | 257 | return ERR_PTR(-ENOENT); |
244 | repeat: | 258 | } |
245 | page = grab_cache_page(mapping, index); | ||
246 | if (!page) | ||
247 | return ERR_PTR(-ENOMEM); | ||
248 | 259 | ||
249 | if (PageUptodate(page)) | 260 | if (PageUptodate(page)) |
250 | return page; | 261 | return page; |
@@ -274,9 +285,10 @@ repeat: | |||
274 | * | 285 | * |
275 | * Also, caller should grab and release a mutex by calling mutex_lock_op() and | 286 | * Also, caller should grab and release a mutex by calling mutex_lock_op() and |
276 | * mutex_unlock_op(). | 287 | * mutex_unlock_op(). |
288 | * Note that, npage is set only by make_empty_dir. | ||
277 | */ | 289 | */ |
278 | struct page *get_new_data_page(struct inode *inode, pgoff_t index, | 290 | struct page *get_new_data_page(struct inode *inode, |
279 | bool new_i_size) | 291 | struct page *npage, pgoff_t index, bool new_i_size) |
280 | { | 292 | { |
281 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 293 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
282 | struct address_space *mapping = inode->i_mapping; | 294 | struct address_space *mapping = inode->i_mapping; |
@@ -284,18 +296,20 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index, | |||
284 | struct dnode_of_data dn; | 296 | struct dnode_of_data dn; |
285 | int err; | 297 | int err; |
286 | 298 | ||
287 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 299 | set_new_dnode(&dn, inode, npage, npage, 0); |
288 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); | 300 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); |
289 | if (err) | 301 | if (err) |
290 | return ERR_PTR(err); | 302 | return ERR_PTR(err); |
291 | 303 | ||
292 | if (dn.data_blkaddr == NULL_ADDR) { | 304 | if (dn.data_blkaddr == NULL_ADDR) { |
293 | if (reserve_new_block(&dn)) { | 305 | if (reserve_new_block(&dn)) { |
294 | f2fs_put_dnode(&dn); | 306 | if (!npage) |
307 | f2fs_put_dnode(&dn); | ||
295 | return ERR_PTR(-ENOSPC); | 308 | return ERR_PTR(-ENOSPC); |
296 | } | 309 | } |
297 | } | 310 | } |
298 | f2fs_put_dnode(&dn); | 311 | if (!npage) |
312 | f2fs_put_dnode(&dn); | ||
299 | repeat: | 313 | repeat: |
300 | page = grab_cache_page(mapping, index); | 314 | page = grab_cache_page(mapping, index); |
301 | if (!page) | 315 | if (!page) |
@@ -325,6 +339,8 @@ repeat: | |||
325 | if (new_i_size && | 339 | if (new_i_size && |
326 | i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) { | 340 | i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) { |
327 | i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT)); | 341 | i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT)); |
342 | /* Only the directory inode sets new_i_size */ | ||
343 | set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR); | ||
328 | mark_inode_dirty_sync(inode); | 344 | mark_inode_dirty_sync(inode); |
329 | } | 345 | } |
330 | return page; | 346 | return page; |
@@ -481,8 +497,9 @@ int do_write_data_page(struct page *page) | |||
481 | * If current allocation needs SSR, | 497 | * If current allocation needs SSR, |
482 | * it had better in-place writes for updated data. | 498 | * it had better in-place writes for updated data. |
483 | */ | 499 | */ |
484 | if (old_blk_addr != NEW_ADDR && !is_cold_data(page) && | 500 | if (unlikely(old_blk_addr != NEW_ADDR && |
485 | need_inplace_update(inode)) { | 501 | !is_cold_data(page) && |
502 | need_inplace_update(inode))) { | ||
486 | rewrite_data_page(F2FS_SB(inode->i_sb), page, | 503 | rewrite_data_page(F2FS_SB(inode->i_sb), page, |
487 | old_blk_addr); | 504 | old_blk_addr); |
488 | } else { | 505 | } else { |
@@ -684,6 +701,27 @@ err: | |||
684 | return err; | 701 | return err; |
685 | } | 702 | } |
686 | 703 | ||
704 | static int f2fs_write_end(struct file *file, | ||
705 | struct address_space *mapping, | ||
706 | loff_t pos, unsigned len, unsigned copied, | ||
707 | struct page *page, void *fsdata) | ||
708 | { | ||
709 | struct inode *inode = page->mapping->host; | ||
710 | |||
711 | SetPageUptodate(page); | ||
712 | set_page_dirty(page); | ||
713 | |||
714 | if (pos + copied > i_size_read(inode)) { | ||
715 | i_size_write(inode, pos + copied); | ||
716 | mark_inode_dirty(inode); | ||
717 | update_inode_page(inode); | ||
718 | } | ||
719 | |||
720 | unlock_page(page); | ||
721 | page_cache_release(page); | ||
722 | return copied; | ||
723 | } | ||
724 | |||
687 | static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, | 725 | static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, |
688 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) | 726 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) |
689 | { | 727 | { |
@@ -698,7 +736,8 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, | |||
698 | get_data_block_ro); | 736 | get_data_block_ro); |
699 | } | 737 | } |
700 | 738 | ||
701 | static void f2fs_invalidate_data_page(struct page *page, unsigned long offset) | 739 | static void f2fs_invalidate_data_page(struct page *page, unsigned int offset, |
740 | unsigned int length) | ||
702 | { | 741 | { |
703 | struct inode *inode = page->mapping->host; | 742 | struct inode *inode = page->mapping->host; |
704 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 743 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
@@ -740,7 +779,7 @@ const struct address_space_operations f2fs_dblock_aops = { | |||
740 | .writepage = f2fs_write_data_page, | 779 | .writepage = f2fs_write_data_page, |
741 | .writepages = f2fs_write_data_pages, | 780 | .writepages = f2fs_write_data_pages, |
742 | .write_begin = f2fs_write_begin, | 781 | .write_begin = f2fs_write_begin, |
743 | .write_end = nobh_write_end, | 782 | .write_end = f2fs_write_end, |
744 | .set_page_dirty = f2fs_set_data_page_dirty, | 783 | .set_page_dirty = f2fs_set_data_page_dirty, |
745 | .invalidatepage = f2fs_invalidate_data_page, | 784 | .invalidatepage = f2fs_invalidate_data_page, |
746 | .releasepage = f2fs_release_data_page, | 785 | .releasepage = f2fs_release_data_page, |