summaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2018-10-03 22:32:44 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-11-13 11:08:39 -0800
commit56db43fd8c9f7f3704071c938dc17441d9c30e88 (patch)
treed57bceb5d0981b28be1b6607a125bc11668d209a /fs/f2fs
parentd224115ac1229d4a74dd023703dd024ff2c6a383 (diff)
downloadlinux-stable-56db43fd8c9f7f3704071c938dc17441d9c30e88.tar.gz
linux-stable-56db43fd8c9f7f3704071c938dc17441d9c30e88.tar.bz2
linux-stable-56db43fd8c9f7f3704071c938dc17441d9c30e88.zip
f2fs: fix to recover cold bit of inode block during POR
commit ef2a007134b4eaa39264c885999f296577bc87d2 upstream. Testcase to reproduce this bug: 1. mkfs.f2fs /dev/sdd 2. mount -t f2fs /dev/sdd /mnt/f2fs 3. touch /mnt/f2fs/file 4. sync 5. chattr +A /mnt/f2fs/file 6. xfs_io -f /mnt/f2fs/file -c "fsync" 7. godown /mnt/f2fs 8. umount /mnt/f2fs 9. mount -t f2fs /dev/sdd /mnt/f2fs 10. chattr -A /mnt/f2fs/file 11. xfs_io -f /mnt/f2fs/file -c "fsync" 12. umount /mnt/f2fs 13. mount -t f2fs /dev/sdd /mnt/f2fs 14. lsattr /mnt/f2fs/file -----------------N- /mnt/f2fs/file But actually, we expect the corrct result is: -------A---------N- /mnt/f2fs/file The reason is in step 9) we missed to recover cold bit flag in inode block, so later, in fsync, we will skip write inode block due to below condition check, result in lossing data in another SPOR. f2fs_fsync_node_pages() if (!IS_DNODE(page) || !is_cold_node(page)) continue; Note that, I guess that some non-dir inode has already lost cold bit during POR, so in order to reenable recovery for those inode, let's try to recover cold bit in f2fs_iget() to save more fsynced data. Fixes: c56675750d7c ("f2fs: remove unneeded set_cold_node()") Cc: <stable@vger.kernel.org> 4.17+ Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/inode.c6
-rw-r--r--fs/f2fs/node.c2
2 files changed, 7 insertions, 1 deletions
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 959df2249875..dd608b819a3c 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -368,6 +368,12 @@ static int do_read_inode(struct inode *inode)
if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode))
__recover_inline_status(inode, node_page);
+ /* try to recover cold bit for non-dir inode */
+ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) {
+ set_cold_node(node_page, false);
+ set_page_dirty(node_page);
+ }
+
/* get rdev by using inline_info */
__get_inode_rdev(inode, ri);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 96e6f47862a5..42ea42acb487 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -2539,7 +2539,7 @@ retry:
if (!PageUptodate(ipage))
SetPageUptodate(ipage);
fill_node_footer(ipage, ino, ino, 0, true);
- set_cold_node(page, false);
+ set_cold_node(ipage, false);
src = F2FS_INODE(page);
dst = F2FS_INODE(ipage);