summaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorDaeho Jeong <daeho.jeong@samsung.com>2018-01-10 21:26:19 -0500
committerJaegeuk Kim <jaegeuk@kernel.org>2018-01-19 01:09:12 -0500
commit9ac1e2d88d076aa1ae9e33d44a9bbc8ae3bfa791 (patch)
tree3136e84225b7e1c311cd38a20698f56af67973c1 /fs/f2fs
parent442a9dbd577e38211d296f35443b5e257bb5a9b3 (diff)
f2fs: prevent newly created inode from being dirtied incorrectly
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>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/inode.c3
-rw-r--r--fs/f2fs/namei.c4
3 files changed, 6 insertions, 2 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index e9299463be20..1b2b0acbc83d 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2150,6 +2150,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
2150 case FI_INLINE_XATTR: 2150 case FI_INLINE_XATTR:
2151 case FI_INLINE_DATA: 2151 case FI_INLINE_DATA:
2152 case FI_INLINE_DENTRY: 2152 case FI_INLINE_DENTRY:
2153 case FI_NEW_INODE:
2153 if (set) 2154 if (set)
2154 return; 2155 return;
2155 case FI_DATA_EXIST: 2156 case FI_DATA_EXIST:
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 234322889e65..1dc77a40d0ad 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -22,6 +22,9 @@
22 22
23void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) 23void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
24{ 24{
25 if (is_inode_flag_set(inode, FI_NEW_INODE))
26 return;
27
25 if (f2fs_inode_dirtied(inode, sync)) 28 if (f2fs_inode_dirtied(inode, sync))
26 return; 29 return;
27 30
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index a885c6e659f8..3ee97ba9d2d7 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -74,12 +74,12 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
74 if (err) 74 if (err)
75 goto fail_drop; 75 goto fail_drop;
76 76
77 set_inode_flag(inode, FI_NEW_INODE);
78
77 /* If the directory encrypted, then we should encrypt the inode. */ 79 /* If the directory encrypted, then we should encrypt the inode. */
78 if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) 80 if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode))
79 f2fs_set_encrypted_inode(inode); 81 f2fs_set_encrypted_inode(inode);
80 82
81 set_inode_flag(inode, FI_NEW_INODE);
82
83 if (f2fs_sb_has_extra_attr(sbi->sb)) { 83 if (f2fs_sb_has_extra_attr(sbi->sb)) {
84 set_inode_flag(inode, FI_EXTRA_ATTR); 84 set_inode_flag(inode, FI_EXTRA_ATTR);
85 F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE; 85 F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;