diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-03 14:14:40 -0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-04 11:52:36 -0800 |
commit | 807b1e1c8e08452948495b1a9985ab46d329e5c2 (patch) | |
tree | 948567d46b544423f793d4c5783cbad72cfd15ea | |
parent | 760de7914e27781abb44564449c761ea4440f982 (diff) | |
download | op-kernel-dev-807b1e1c8e08452948495b1a9985ab46d329e5c2.zip op-kernel-dev-807b1e1c8e08452948495b1a9985ab46d329e5c2.tar.gz |
f2fs: do not recover from previous remained wrong dnodes
If device does not support discard, some obsolete dnodes can be recovered
by roll-forward. This patch enhances the recovery flow.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/recovery.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index cbf74f4..fad010f 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -168,6 +168,32 @@ static void recover_inode(struct inode *inode, struct page *page) ino_of_node(page), name); } +static bool is_same_inode(struct inode *inode, struct page *ipage) +{ + struct f2fs_inode *ri = F2FS_INODE(ipage); + struct timespec disk; + + if (!IS_INODE(ipage)) + return true; + + disk.tv_sec = le64_to_cpu(ri->i_ctime); + disk.tv_nsec = le32_to_cpu(ri->i_ctime_nsec); + if (timespec_compare(&inode->i_ctime, &disk) > 0) + return false; + + disk.tv_sec = le64_to_cpu(ri->i_atime); + disk.tv_nsec = le32_to_cpu(ri->i_atime_nsec); + if (timespec_compare(&inode->i_atime, &disk) > 0) + return false; + + disk.tv_sec = le64_to_cpu(ri->i_mtime); + disk.tv_nsec = le32_to_cpu(ri->i_mtime_nsec); + if (timespec_compare(&inode->i_mtime, &disk) > 0) + return false; + + return true; +} + static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) { unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); @@ -197,7 +223,10 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) goto next; entry = get_fsync_inode(head, ino_of_node(page)); - if (!entry) { + if (entry) { + if (!is_same_inode(entry->inode, page)) + goto next; + } else { if (IS_INODE(page) && is_dent_dnode(page)) { err = recover_inode_page(sbi, page); if (err) |