]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
f2fs: prevent newly created inode from being dirtied incorrectly
authorDaeho Jeong <daeho.jeong@samsung.com>
Thu, 11 Jan 2018 02:26:19 +0000 (11:26 +0900)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 19 Jan 2018 06:09:12 +0000 (22:09 -0800)
Now, we invoke f2fs_mark_inode_dirty_sync() to make an inode dirty in
advance of creating a new node page for the inode. By this, some inodes
whose node page is not created yet can be linked into the global dirty
list.

If the checkpoint is executed at this moment, the inode will be written
back by writeback_single_inode() and finally update_inode_page() will
fail to detach the inode from the global dirty list because the inode
doesn't have a node page.

The problem is that the inode's state in VFS layer will become clean
after execution of writeback_single_inode() and it's still linked in
the global dirty list of f2fs and this will cause a kernel panic.

So, we will prevent the newly created inode from being dirtied during
the FI_NEW_INODE flag of the inode is set. We will make it dirty
right after the flag is cleared.

Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
Signed-off-by: Youngjin Gil <youngjin.gil@samsung.com>
Tested-by: Hobin Woo <hobin.woo@samsung.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/inode.c
fs/f2fs/namei.c

index e9299463be20237fa745158d422bdd74a7494d4f..1b2b0acbc83d267a62fd81fb70deec9176b0e2cf 100644 (file)
@@ -2150,6 +2150,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
        case FI_INLINE_XATTR:
        case FI_INLINE_DATA:
        case FI_INLINE_DENTRY:
+       case FI_NEW_INODE:
                if (set)
                        return;
        case FI_DATA_EXIST:
index 234322889e657d36733ad07e0bcc1e7505fddb01..1dc77a40d0ad87cdce3a16d9110b4c245ed9abb6 100644 (file)
@@ -22,6 +22,9 @@
 
 void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
 {
+       if (is_inode_flag_set(inode, FI_NEW_INODE))
+               return;
+
        if (f2fs_inode_dirtied(inode, sync))
                return;
 
index a885c6e659f81e8c8267ad3ee5556d9da7ba1612..3ee97ba9d2d710301b31ebbe45538d8f4b960e90 100644 (file)
@@ -74,12 +74,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
        if (err)
                goto fail_drop;
 
+       set_inode_flag(inode, FI_NEW_INODE);
+
        /* If the directory encrypted, then we should encrypt the inode. */
        if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode))
                f2fs_set_encrypted_inode(inode);
 
-       set_inode_flag(inode, FI_NEW_INODE);
-
        if (f2fs_sb_has_extra_attr(sbi->sb)) {
                set_inode_flag(inode, FI_EXTRA_ATTR);
                F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;