Skip to contentSkip to conversation

f2fs: allow to recover node blocks given updated checkpoint

PATCH In review Jaegeuk Kim 2 participants 8 messages Jan 20, 2018 – Jan 21, 2018 F2FS file system

lore
Share & tools
lore

Jaegeuk Kim

author maintainer
#0 lore raw

PATCH 1/2 f2fs: allow to recover node blocks given updated checkpoint

If fsck.f2fs changes crc, we have no way to recover some inode blocks by roll- forward recovery. Let's relax the condition to recover them.

---
 fs/f2fs/node.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
fs/f2fs/node.h +4 -3
index 0ee3e5ff49a3..15280eeb24ea 100644
@@ -305,10 +305,11 @@ static inline bool is_recoverable_dnode(struct page *page)
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page));
 	__u64 cp_ver = cur_cp_version(ckpt);
 
-	if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
+	if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) {
 		cp_ver |= (cur_cp_crc(ckpt) << 32);
-
-	return cp_ver == cpver_of_node(page);
+		return cp_ver == cpver_of_node(page);
+	}
+	return (cp_ver << 32) == (cpver_of_node(page) << 32);
 }
 
 /*
Signature · 6 lines
2.15.0.531.g2ccb3012c9-goog


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
author maintainer
#1 lore raw

PATCH 2/2 f2fs: recover some i_inline flags

This fixes lost i_inline flags during roll-forward.

---
 fs/f2fs/recovery.c | 9 +++++++++
 1 file changed, 9 insertions(+)
fs/f2fs/recovery.c +9 -0
index cbeef73bc4dd..2354f1e05e19 100644
@@ -211,6 +211,15 @@ static void recover_inode(struct inode *inode, struct page *page)
 
 	F2FS_I(inode)->i_advise = raw->i_advise;
 
+	if (raw->i_inline & F2FS_PIN_FILE)
+		set_inode_flag(inode, FI_PIN_FILE);
+	if (raw->i_inline & F2FS_DATA_EXIST)
+		set_inode_flag(inode, FI_DATA_EXIST);
+	else
+		clear_inode_flag(inode, FI_DATA_EXIST);
+	if (!(raw->i_inline & F2FS_INLINE_DOTS))
+		clear_inode_flag(inode, FI_INLINE_DOTS);
+
 	if (file_enc_name(inode))
 		name = "<encrypted>";
 	else
Signature · 6 lines
2.15.0.531.g2ccb3012c9-goog


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
maintainer
#2 lore raw

Re: [f2fs-dev] [PATCH 2/2] f2fs: recover some i_inline flags

Quoted 12 lines · Jaegeuk Kim

This fixes lost i_inline flags during roll-forward.

---
 fs/f2fs/recovery.c | 9 +++++++++
 1 file changed, 9 insertions(+)
fs/f2fs/recovery.c +0 -0
index cbeef73bc4dd..2354f1e05e19 100644

fs/f2fs/recovery.c static void recover_inode(struct inode *inode, struct page *page) · line 212

Quoted 2 lines
fs/f2fs/recovery.c +0 -0
@@ -211,6 +211,15 @@ static void recover_inode(struct inode *inode, struct page *page)
 
 	F2FS_I(inode)->i_advise = raw->i_advise;

How about adding recover_inline_flags() including below changes?

fs/f2fs/recovery.c static void recover_inode(struct inode *inode, struct page *page) · line 215

Quoted 3 lines
fs/f2fs/recovery.c +2 -0
+	if (raw->i_inline & F2FS_PIN_FILE)
+		set_inode_flag(inode, FI_PIN_FILE);

else
clear_inode_flag(inode, FI_PIN_FILE); ?

Thanks,

fs/f2fs/recovery.c static void recover_inode(struct inode *inode, struct page *page)

Quoted 11 lines
fs/f2fs/recovery.c +7 -0
+	if (raw->i_inline & F2FS_DATA_EXIST)
+		set_inode_flag(inode, FI_DATA_EXIST);
+	else
+		clear_inode_flag(inode, FI_DATA_EXIST);
+	if (!(raw->i_inline & F2FS_INLINE_DOTS))
+		clear_inode_flag(inode, FI_INLINE_DOTS);
+
 	if (file_enc_name(inode))
 		name = "<encrypted>";
 	else
 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot

author maintainer
#3 lore raw

Re: [PATCH 2/2 v2] f2fs: recover some i_inline flags

In reply to Jaegeuk Kim

This fixes lost i_inline flags during roll-forward.

---

Change log from v1:
- add a new function to recover the flag
- fix missing pin_file unset

 fs/f2fs/recovery.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)
fs/f2fs/recovery.c +19 -2
index cbeef73bc4dd..337f3363f48f 100644
@@ -195,6 +195,20 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
 	return err;
 }
 
+static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
+{
+	if (ri->i_inline & F2FS_PIN_FILE)
+		set_inode_flag(inode, FI_PIN_FILE);
+	else
+		clear_inode_flag(inode, FI_PIN_FILE);
+	if (ri->i_inline & F2FS_DATA_EXIST)
+		set_inode_flag(inode, FI_DATA_EXIST);
+	else
+		clear_inode_flag(inode, FI_DATA_EXIST);
+	if (!(ri->i_inline & F2FS_INLINE_DOTS))
+		clear_inode_flag(inode, FI_INLINE_DOTS);
+}
+
 static void recover_inode(struct inode *inode, struct page *page)
 {
 	struct f2fs_inode *raw = F2FS_INODE(page);
@@ -211,13 +225,16 @@ static void recover_inode(struct inode *inode, struct page *page)
 
 	F2FS_I(inode)->i_advise = raw->i_advise;
 
+	recover_inline_flags(inode, raw);
+
 	if (file_enc_name(inode))
 		name = "<encrypted>";
 	else
 		name = F2FS_INODE(page)->i_name;
 
-	f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s",
-			ino_of_node(page), name);
+	f2fs_msg(inode->i_sb, KERN_NOTICE,
+		"recover_inode: ino = %x, name = %s, inline = %x",
+			ino_of_node(page), name, raw->i_inline);
 }
 
 static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
Signature · 6 lines
2.15.0.531.g2ccb3012c9-goog


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
maintainer Reviewed-by
#4 lore raw

Re: [f2fs-dev] [PATCH 2/2 v2] f2fs: recover some i_inline flags

Quoted 3 lines · Jaegeuk Kim

This fixes lost i_inline flags during roll-forward.

Thanks,

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot

maintainer
#5 lore raw
In reply to Jaegeuk Kim
Quoted 2 lines · Jaegeuk Kim

If fsck.f2fs changes crc, we have no way to recover some inode blocks by roll- forward recovery. Let's relax the condition to recover them.

As this is fsck case only, what about writing checkpoint with special flag for such case, and relax the condition if flag was set, so, for normal case, it can avoid recovering obsolete data.

Thanks,

Quoted 16 lines
---
 fs/f2fs/node.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
fs/f2fs/node.h +0 -1
index 0ee3e5ff49a3..15280eeb24ea 100644
@@ -305,10 +305,11 @@ static inline bool is_recoverable_dnode(struct page *page)
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page));
 	__u64 cp_ver = cur_cp_version(ckpt);
 
-	if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))

fs/f2fs/node.h static inline bool is_recoverable_dnode(struct page *page) · line 315

Quoted 10 lines
fs/f2fs/node.h +4 -2
+	if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) {
 		cp_ver |= (cur_cp_crc(ckpt) << 32);
-
-	return cp_ver == cpver_of_node(page);
+		return cp_ver == cpver_of_node(page);
+	}
+	return (cp_ver << 32) == (cpver_of_node(page) << 32);
 }
 
 /*

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot

author maintainer
#6 lore raw
In reply to Jaegeuk Kim

If fsck.f2fs changes crc, we have no way to recover some inode blocks by roll- forward recovery. Let's relax the condition to recover them.

---

Change log from v1:
- add a new checkpoint flag to handle this

 fs/f2fs/checkpoint.c    | 1 +
 fs/f2fs/node.h          | 4 ++++
 include/linux/f2fs_fs.h | 1 +
 3 files changed, 6 insertions(+)
fs/f2fs/checkpoint.c +1 -0
index 9c7596f7daae..512dca8abc7d 100644
@@ -1157,6 +1157,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 
 	/* set this flag to activate crc|cp_ver for recovery */
 	__set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG);
+	__clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG);
 
 	spin_unlock_irqrestore(&sbi->cp_lock, flags);
 }
fs/f2fs/node.h +4 -0
index 0ee3e5ff49a3..081ef0d672bf 100644
@@ -305,6 +305,10 @@ static inline bool is_recoverable_dnode(struct page *page)
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page));
 	__u64 cp_ver = cur_cp_version(ckpt);
 
+	/* Don't care crc part, if fsck.f2fs sets it. */
+	if (__is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG))
+		return (cp_ver << 32) == (cpver_of_node(page) << 32);
+
 	if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
 		cp_ver |= (cur_cp_crc(ckpt) << 32);
 
include/linux/f2fs_fs.h +1 -0
index cfb522e6affc..6eed677b6d9a 100644
@@ -117,6 +117,7 @@ struct f2fs_super_block {
 /*
  * For checkpoint
  */
+#define CP_NOCRC_RECOVERY_FLAG	0x00000200
 #define CP_TRIMMED_FLAG		0x00000100
 #define CP_NAT_BITS_FLAG	0x00000080
 #define CP_CRC_RECOVERY_FLAG	0x00000040
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog