Skip to content

Commit 39a8695

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: refactor ->page_mkwrite() flow
Thread A Thread B - f2fs_vm_page_mkwrite - f2fs_setattr - down_write(i_mmap_sem) - truncate_setsize - f2fs_truncate - up_write(i_mmap_sem) - f2fs_reserve_block reserve NEW_ADDR - skip dirty page due to truncation 1. we don't need to rserve new block address for a truncated page. 2. dn.data_blkaddr is used out of node page lock coverage. Refactor ->page_mkwrite() flow to fix above issues: - use __do_map_lock() to avoid racing checkpoint() - lock data page in prior to dnode page - cover f2fs_reserve_block with i_mmap_sem lock - wait page writeback before zeroing page Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent bab475c commit 39a8695

File tree

3 files changed

+24
-24
lines changed

3 files changed

+24
-24
lines changed

fs/f2fs/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
972972
return err;
973973
}
974974

975-
static inline void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
975+
void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
976976
{
977977
if (flag == F2FS_GET_BLOCK_PRE_AIO) {
978978
if (lock)

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,7 @@ struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index,
30553055
struct page *f2fs_get_new_data_page(struct inode *inode,
30563056
struct page *ipage, pgoff_t index, bool new_i_size);
30573057
int f2fs_do_write_data_page(struct f2fs_io_info *fio);
3058+
void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock);
30583059
int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
30593060
int create, int flag);
30603061
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,

fs/f2fs/file.c

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
4747
struct page *page = vmf->page;
4848
struct inode *inode = file_inode(vmf->vma->vm_file);
4949
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
50-
struct dnode_of_data dn;
50+
struct dnode_of_data dn = { .node_changed = false };
5151
int err;
5252

5353
if (unlikely(f2fs_cp_error(sbi))) {
@@ -59,19 +59,6 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
5959

6060
f2fs_bug_on(sbi, f2fs_has_inline_data(inode));
6161

62-
/* block allocation */
63-
f2fs_lock_op(sbi);
64-
set_new_dnode(&dn, inode, NULL, NULL, 0);
65-
err = f2fs_reserve_block(&dn, page->index);
66-
if (err) {
67-
f2fs_unlock_op(sbi);
68-
goto out;
69-
}
70-
f2fs_put_dnode(&dn);
71-
f2fs_unlock_op(sbi);
72-
73-
f2fs_balance_fs(sbi, dn.node_changed);
74-
7562
file_update_time(vmf->vma->vm_file);
7663
down_read(&F2FS_I(inode)->i_mmap_sem);
7764
lock_page(page);
@@ -83,11 +70,28 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
8370
goto out_sem;
8471
}
8572

73+
/* block allocation */
74+
__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true);
75+
set_new_dnode(&dn, inode, NULL, NULL, 0);
76+
err = f2fs_get_block(&dn, page->index);
77+
f2fs_put_dnode(&dn);
78+
__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
79+
if (err) {
80+
unlock_page(page);
81+
goto out_sem;
82+
}
83+
84+
/* fill the page */
85+
f2fs_wait_on_page_writeback(page, DATA, false);
86+
87+
/* wait for GCed page writeback via META_MAPPING */
88+
f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
89+
8690
/*
8791
* check to see if the page is mapped already (no holes)
8892
*/
8993
if (PageMappedToDisk(page))
90-
goto mapped;
94+
goto out_sem;
9195

9296
/* page is wholly or partially inside EOF */
9397
if (((loff_t)(page->index + 1) << PAGE_SHIFT) >
@@ -104,16 +108,11 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
104108
f2fs_update_iostat(sbi, APP_MAPPED_IO, F2FS_BLKSIZE);
105109

106110
trace_f2fs_vm_page_mkwrite(page, DATA);
107-
mapped:
108-
/* fill the page */
109-
f2fs_wait_on_page_writeback(page, DATA, false);
110-
111-
/* wait for GCed page writeback via META_MAPPING */
112-
f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
113-
114111
out_sem:
115112
up_read(&F2FS_I(inode)->i_mmap_sem);
116-
out:
113+
114+
f2fs_balance_fs(sbi, dn.node_changed);
115+
117116
sb_end_pagefault(inode->i_sb);
118117
f2fs_update_time(sbi, REQ_TIME);
119118
err:

0 commit comments

Comments
 (0)