aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/data.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2014-02-17 05:29:27 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-02-24 02:00:33 -0500
commit8618b881e9fd0e1817ff5cb7befadd3240d54830 (patch)
tree340890f2597879fc08cc61af403812691d913c6f /fs/f2fs/data.c
parentb63da15e8b475245026bdf2096853683f189706b (diff)
f2fs: fix not to write data pages on the page reclaiming path
Even if f2fs_write_data_page is called by the page reclaiming path, we should not write the page to provide enough free segments for the worst case scenario. Otherwise, f2fs can face with no free segment while gc is conducted, resulting in: ------------[ cut here ]------------ kernel BUG at /home/zeus/f2fs_test/src/fs/f2fs/segment.c:565! RIP: 0010:[<ffffffffa02c3b11>] [<ffffffffa02c3b11>] new_curseg+0x331/0x340 [f2fs] Call Trace: allocate_segment_by_default+0x204/0x280 [f2fs] allocate_data_block+0x108/0x210 [f2fs] write_data_page+0x8a/0xc0 [f2fs] do_write_data_page+0xe1/0x2a0 [f2fs] move_data_page+0x8a/0xf0 [f2fs] f2fs_gc+0x446/0x970 [f2fs] f2fs_balance_fs+0xb6/0xd0 [f2fs] f2fs_write_begin+0x50/0x350 [f2fs] ? unlock_page+0x27/0x30 ? unlock_page+0x27/0x30 generic_file_buffered_write+0x10a/0x280 ? file_update_time+0xa3/0xf0 __generic_file_aio_write+0x1c8/0x3d0 ? generic_file_aio_write+0x52/0xb0 ? generic_file_aio_write+0x52/0xb0 generic_file_aio_write+0x65/0xb0 do_sync_write+0x5a/0x90 vfs_write+0xc5/0x1f0 SyS_write+0x55/0xa0 system_call_fastpath+0x16/0x1b Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r--fs/f2fs/data.c38
1 files changed, 15 insertions, 23 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index b401be71ecbd..93d80ea4674b 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -805,38 +805,30 @@ static int f2fs_write_data_page(struct page *page,
805 805
806 zero_user_segment(page, offset, PAGE_CACHE_SIZE); 806 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
807write: 807write:
808 if (unlikely(sbi->por_doing)) { 808 if (unlikely(sbi->por_doing))
809 err = AOP_WRITEPAGE_ACTIVATE;
810 goto redirty_out; 809 goto redirty_out;
811 }
812 810
813 /* Dentry blocks are controlled by checkpoint */ 811 /* Dentry blocks are controlled by checkpoint */
814 if (S_ISDIR(inode->i_mode)) { 812 if (S_ISDIR(inode->i_mode)) {
815 inode_dec_dirty_dents(inode); 813 inode_dec_dirty_dents(inode);
816 err = do_write_data_page(page, &fio); 814 err = do_write_data_page(page, &fio);
817 } else { 815 goto done;
818 f2fs_lock_op(sbi); 816 }
819
820 if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode)) {
821 err = f2fs_write_inline_data(inode, page, offset);
822 f2fs_unlock_op(sbi);
823 goto out;
824 } else {
825 err = do_write_data_page(page, &fio);
826 }
827 817
828 f2fs_unlock_op(sbi); 818 if (!wbc->for_reclaim)
829 need_balance_fs = true; 819 need_balance_fs = true;
830 } 820 else if (has_not_enough_free_secs(sbi, 0))
831 if (err == -ENOENT)
832 goto out;
833 else if (err)
834 goto redirty_out; 821 goto redirty_out;
835 822
836 if (wbc->for_reclaim) { 823 f2fs_lock_op(sbi);
837 f2fs_submit_merged_bio(sbi, DATA, WRITE); 824 if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode))
838 need_balance_fs = false; 825 err = f2fs_write_inline_data(inode, page, offset);
839 } 826 else
827 err = do_write_data_page(page, &fio);
828 f2fs_unlock_op(sbi);
829done:
830 if (err && err != -ENOENT)
831 goto redirty_out;
840 832
841 clear_cold_data(page); 833 clear_cold_data(page);
842out: 834out:
@@ -848,7 +840,7 @@ out:
848redirty_out: 840redirty_out:
849 wbc->pages_skipped++; 841 wbc->pages_skipped++;
850 set_page_dirty(page); 842 set_page_dirty(page);
851 return err; 843 return AOP_WRITEPAGE_ACTIVATE;
852} 844}
853 845
854#define MAX_DESIRED_PAGES_WP 4096 846#define MAX_DESIRED_PAGES_WP 4096