diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-06-06 14:05:03 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-06-06 14:18:36 -0400 |
commit | 86928f984e8b166fcd0c7c241501bc00f53eb623 (patch) | |
tree | 15ac0986725b469160baae2ed0fb1d598a63e996 | |
parent | 6fa1df533a93161c54c987bbffaadf03563aa78d (diff) |
f2fs: avoid not to call remove_dirty_inode
There is an errorneous case during the recovery like below.
In recovery_dentry,
1) dir = f2fs_iget();
2) mark the dir with FI_DELAY_IPUT
3) goto unmap_out
After the end of recovery routine, there is no dirty dentries so the dir cannot
be released by iput in remove_dirty_dir_inode.
This patch fixes such the bug case by handling the iget and iput in the
recovery_dentry procedure.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/recovery.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index e950a2f50ac1..a112368a4a86 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -52,20 +52,13 @@ static int recover_dentry(struct page *ipage, struct inode *inode) | |||
52 | goto out; | 52 | goto out; |
53 | } | 53 | } |
54 | 54 | ||
55 | if (is_inode_flag_set(F2FS_I(dir), FI_DIRTY_DIR)) { | ||
56 | iput(dir); | ||
57 | } else { | ||
58 | add_dirty_dir_inode(dir); | ||
59 | set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); | ||
60 | } | ||
61 | |||
62 | name.len = le32_to_cpu(raw_inode->i_namelen); | 55 | name.len = le32_to_cpu(raw_inode->i_namelen); |
63 | name.name = raw_inode->i_name; | 56 | name.name = raw_inode->i_name; |
64 | 57 | ||
65 | if (unlikely(name.len > F2FS_NAME_LEN)) { | 58 | if (unlikely(name.len > F2FS_NAME_LEN)) { |
66 | WARN_ON(1); | 59 | WARN_ON(1); |
67 | err = -ENAMETOOLONG; | 60 | err = -ENAMETOOLONG; |
68 | goto out; | 61 | goto out_err; |
69 | } | 62 | } |
70 | retry: | 63 | retry: |
71 | de = f2fs_find_entry(dir, &name, &page); | 64 | de = f2fs_find_entry(dir, &name, &page); |
@@ -90,11 +83,23 @@ retry: | |||
90 | goto retry; | 83 | goto retry; |
91 | } | 84 | } |
92 | err = __f2fs_add_link(dir, &name, inode); | 85 | err = __f2fs_add_link(dir, &name, inode); |
86 | if (err) | ||
87 | goto out_err; | ||
88 | |||
89 | if (is_inode_flag_set(F2FS_I(dir), FI_DELAY_IPUT)) { | ||
90 | iput(dir); | ||
91 | } else { | ||
92 | add_dirty_dir_inode(dir); | ||
93 | set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); | ||
94 | } | ||
95 | |||
93 | goto out; | 96 | goto out; |
94 | 97 | ||
95 | out_unmap_put: | 98 | out_unmap_put: |
96 | kunmap(page); | 99 | kunmap(page); |
97 | f2fs_put_page(page, 0); | 100 | f2fs_put_page(page, 0); |
101 | out_err: | ||
102 | iput(dir); | ||
98 | out: | 103 | out: |
99 | f2fs_msg(inode->i_sb, KERN_NOTICE, | 104 | f2fs_msg(inode->i_sb, KERN_NOTICE, |
100 | "%s: ino = %x, name = %s, dir = %lx, err = %d", | 105 | "%s: ino = %x, name = %s, dir = %lx, err = %d", |