f2fs: avoid data race between FI_DIRTY_INODE flag and update_inode
authorJaegeuk Kim <jaegeuk@kernel.org>
Thu, 2 Jun 2016 21:15:56 +0000 (14:15 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 7 Jun 2016 16:45:40 +0000 (09:45 -0700)
FI_DIRTY_INODE flag is not covered by inode page lock, so it can be unset
at any time like below.

Thread #1                        Thread #2
- lock_page(ipage)
- update i_fields
                                 - update i_size/i_blocks/and so on
 - set FI_DIRTY_INODE
- reset FI_DIRTY_INODE
- set_page_dirty(ipage)

In this case, we can lose the latest i_field information.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/inode.c

index fb3d9bd597e36066bc9f16cbfae1eab4657451c7..63c432673c71f37659d092411473a32a9489c858 100644 (file)
@@ -231,6 +231,8 @@ int update_inode(struct inode *inode, struct page *node_page)
 {
        struct f2fs_inode *ri;
 
+       f2fs_inode_synced(inode);
+
        f2fs_wait_on_page_writeback(node_page, NODE, true);
 
        ri = F2FS_INODE(node_page);
@@ -265,7 +267,6 @@ int update_inode(struct inode *inode, struct page *node_page)
 
        __set_inode_rdev(inode, ri);
        set_cold_node(inode, node_page);
-       f2fs_inode_synced(inode);
 
        /* deleted inode */
        if (inode->i_nlink == 0)