mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
f2fs: fix an error case of missing update inode page
-Thread A Thread B
-write_checkpoint
-block_operations
-f2fs_unlock_all -f2fs_sync_file
-f2fs_write_inode
-f2fs_inode_synced
-f2fs_sync_inode_meta
-sync_node_pages
-set_page_drity
In this case, if sudden power off without next new checkpoint,
the last inode page update will lost. wb_writeback is same with
fsync.
Yunlei also reproduced the bug by:
@@ -366,7 +366,7 @@ int update_inode(struct inode *inode, struct page *node_page)
struct extent_tree *et = F2FS_I(inode)->extent_tree;
f2fs_inode_synced(inode);
-
+ msleep(10000);
f2fs_wait_on_page_writeback(node_page, NODE, true);
shell 1: shell2:
dd if=/dev/zero of=./test bs=1M count=10
sync
echo "hello" >> ./test
fsync test // sleep 10s
sync //return quickly
echo c > /proc/sysrq-trigger
Signed-off-by: Yunlei He <heyunlei@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
@@ -2607,8 +2607,8 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page);
|
|||||||
struct inode *f2fs_iget(struct super_block *sb, unsigned long ino);
|
struct inode *f2fs_iget(struct super_block *sb, unsigned long ino);
|
||||||
struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino);
|
struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino);
|
||||||
int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink);
|
int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink);
|
||||||
int update_inode(struct inode *inode, struct page *node_page);
|
void update_inode(struct inode *inode, struct page *node_page);
|
||||||
int update_inode_page(struct inode *inode);
|
void update_inode_page(struct inode *inode);
|
||||||
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc);
|
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc);
|
||||||
void f2fs_evict_inode(struct inode *inode);
|
void f2fs_evict_inode(struct inode *inode);
|
||||||
void handle_failed_inode(struct inode *inode);
|
void handle_failed_inode(struct inode *inode);
|
||||||
|
|||||||
@@ -360,14 +360,15 @@ retry:
|
|||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_inode(struct inode *inode, struct page *node_page)
|
void update_inode(struct inode *inode, struct page *node_page)
|
||||||
{
|
{
|
||||||
struct f2fs_inode *ri;
|
struct f2fs_inode *ri;
|
||||||
struct extent_tree *et = F2FS_I(inode)->extent_tree;
|
struct extent_tree *et = F2FS_I(inode)->extent_tree;
|
||||||
|
|
||||||
f2fs_inode_synced(inode);
|
|
||||||
|
|
||||||
f2fs_wait_on_page_writeback(node_page, NODE, true);
|
f2fs_wait_on_page_writeback(node_page, NODE, true);
|
||||||
|
set_page_dirty(node_page);
|
||||||
|
|
||||||
|
f2fs_inode_synced(inode);
|
||||||
|
|
||||||
ri = F2FS_INODE(node_page);
|
ri = F2FS_INODE(node_page);
|
||||||
|
|
||||||
@@ -426,14 +427,12 @@ int update_inode(struct inode *inode, struct page *node_page)
|
|||||||
if (inode->i_nlink == 0)
|
if (inode->i_nlink == 0)
|
||||||
clear_inline_node(node_page);
|
clear_inline_node(node_page);
|
||||||
|
|
||||||
return set_page_dirty(node_page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_inode_page(struct inode *inode)
|
void update_inode_page(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||||
struct page *node_page;
|
struct page *node_page;
|
||||||
int ret = 0;
|
|
||||||
retry:
|
retry:
|
||||||
node_page = get_node_page(sbi, inode->i_ino);
|
node_page = get_node_page(sbi, inode->i_ino);
|
||||||
if (IS_ERR(node_page)) {
|
if (IS_ERR(node_page)) {
|
||||||
@@ -444,11 +443,10 @@ retry:
|
|||||||
} else if (err != -ENOENT) {
|
} else if (err != -ENOENT) {
|
||||||
f2fs_stop_checkpoint(sbi, false);
|
f2fs_stop_checkpoint(sbi, false);
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
ret = update_inode(inode, node_page);
|
update_inode(inode, node_page);
|
||||||
f2fs_put_page(node_page, 1);
|
f2fs_put_page(node_page, 1);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
|
|||||||
Reference in New Issue
Block a user