diff options
author | Russ W. Knize <rknize@gmail.com> | 2013-09-24 10:40:57 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-09-25 04:59:32 -0400 |
commit | 2e5558f4a5cf16a7394fd5770087303db8912c66 (patch) | |
tree | 08bde9e64eaab5f9154596cf83979b03cc526861 /fs/f2fs/recovery.c | |
parent | 52ab956000214aa111254e52e5eac3d91bd7cf4b (diff) |
f2fs: account for orphan inodes during recovery
During recovery, orphan inodes are deleted via truncate_hole().
These orphans are added by recover_dentry() via f2fs_delete_entry().
However, f2fs_delete_entry() adds them via add_orphan_inode()
without calling acquire_orphan_inode() first. This prevents the
counters from being incremented properly, which causes them to
underflow when remove_orphan_inode() is called later on.
Signed-off-by: Russ Knize <rknize@motorola.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/recovery.c')
-rw-r--r-- | fs/f2fs/recovery.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index d43e4cd1f815..a15d122fdc50 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -64,24 +64,31 @@ static int recover_dentry(struct page *ipage, struct inode *inode) | |||
64 | name.name = raw_inode->i_name; | 64 | name.name = raw_inode->i_name; |
65 | retry: | 65 | retry: |
66 | de = f2fs_find_entry(dir, &name, &page); | 66 | de = f2fs_find_entry(dir, &name, &page); |
67 | if (de && inode->i_ino == le32_to_cpu(de->ino)) { | 67 | if (de && inode->i_ino == le32_to_cpu(de->ino)) |
68 | kunmap(page); | 68 | goto out_unmap_put; |
69 | f2fs_put_page(page, 0); | ||
70 | goto out; | ||
71 | } | ||
72 | if (de) { | 69 | if (de) { |
73 | einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); | 70 | einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); |
74 | if (IS_ERR(einode)) { | 71 | if (IS_ERR(einode)) { |
75 | WARN_ON(1); | 72 | WARN_ON(1); |
76 | if (PTR_ERR(einode) == -ENOENT) | 73 | if (PTR_ERR(einode) == -ENOENT) |
77 | err = -EEXIST; | 74 | err = -EEXIST; |
78 | goto out; | 75 | goto out_unmap_put; |
76 | } | ||
77 | err = acquire_orphan_inode(F2FS_SB(inode->i_sb)); | ||
78 | if (err) { | ||
79 | iput(einode); | ||
80 | goto out_unmap_put; | ||
79 | } | 81 | } |
80 | f2fs_delete_entry(de, page, einode); | 82 | f2fs_delete_entry(de, page, einode); |
81 | iput(einode); | 83 | iput(einode); |
82 | goto retry; | 84 | goto retry; |
83 | } | 85 | } |
84 | err = __f2fs_add_link(dir, &name, inode); | 86 | err = __f2fs_add_link(dir, &name, inode); |
87 | goto out; | ||
88 | |||
89 | out_unmap_put: | ||
90 | kunmap(page); | ||
91 | f2fs_put_page(page, 0); | ||
85 | out: | 92 | out: |
86 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: " | 93 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: " |
87 | "ino = %x, name = %s, dir = %lx, err = %d", | 94 | "ino = %x, name = %s, dir = %lx, err = %d", |