Skip to contentSkip to conversation

f2fs: fix to recover cold bit of inode block during POR

PATCH New Chao Yu 1 participant 1 message Oct 3, 2018

Subsystems (2)
lore
Share & tools
lore

Chao Yu

author maintainer
#0 lore raw

PATCH v2 1/1 f2fs: fix to recover cold bit of inode block during POR

From: Chao Yu <[email protected]>

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()")

---
v2:
- call set_page_dirty to recalculate checksum.

 fs/f2fs/inode.c | 6 ++++++
 fs/f2fs/node.c  | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
fs/f2fs/inode.c +6 -0
index 86e7333d60c1..4edfa03f3807 100644
@@ -365,6 +365,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);
 
fs/f2fs/node.c +1 -1
index b1e3ff8147f6..033ce067509e 100644
@@ -2542,7 +2542,7 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
 	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);
Signature · 1 line
2.18.0