* [f2fs-dev] [PATCH 1/4] fsck.f2fs: wrap openned codes into fsck_sanity_check_nid()
@ 2023-05-12 10:03 Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 2/4] fsck.f2fs: use f2fs_is_valid_blkaddr() Chao Yu
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Chao Yu @ 2023-05-12 10:03 UTC (permalink / raw)
To: jaegeuk; +Cc: linux-f2fs-devel
read_all_xattrs() is the only user of fsck_sanity_check_nid(), wrap
openned codes of read_all_xattrs() into fsck_sanity_check_nid().
Then fsck_sanity_check_nid() can be reused later.
Signed-off-by: Chao Yu <chao@kernel.org>
---
fsck/fsck.c | 16 ++++++++++++----
fsck/fsck.h | 3 +--
fsck/xattr.c | 12 +-----------
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 324c3d5..64db1e5 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -515,11 +515,19 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
}
int fsck_sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
- struct f2fs_node *node_blk,
- enum FILE_TYPE ftype, enum NODE_TYPE ntype,
- struct node_info *ni)
+ enum FILE_TYPE ftype, enum NODE_TYPE ntype)
{
- return sanity_check_nid(sbi, nid, node_blk, ftype, ntype, ni);
+ struct f2fs_node *node_blk = NULL;
+ struct node_info ni;
+ int ret;
+
+ node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk != NULL);
+
+ ret = sanity_check_nid(sbi, nid, node_blk, ftype, ntype, &ni);
+
+ free(node_blk);
+ return ret;
}
static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
diff --git a/fsck/fsck.h b/fsck/fsck.h
index dabd8b9..02dcff8 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -166,8 +166,7 @@ extern int fsck_chk_orphan_node(struct f2fs_sb_info *);
extern int fsck_chk_quota_node(struct f2fs_sb_info *);
extern int fsck_chk_quota_files(struct f2fs_sb_info *);
extern int fsck_sanity_check_nid(struct f2fs_sb_info *, u32,
- struct f2fs_node *, enum FILE_TYPE, enum NODE_TYPE,
- struct node_info *);
+ enum FILE_TYPE, enum NODE_TYPE);
extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
enum FILE_TYPE, enum NODE_TYPE, u32 *,
struct f2fs_compr_blk_cnt *, struct child_info *);
diff --git a/fsck/xattr.c b/fsck/xattr.c
index 8e66873..04c2879 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -25,17 +25,7 @@ void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid);
if (c.func == FSCK && xnid) {
- struct f2fs_node *node_blk = NULL;
- struct node_info ni;
- int ret;
-
- node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
- ASSERT(node_blk != NULL);
-
- ret = fsck_sanity_check_nid(sbi, xnid, node_blk,
- F2FS_FT_XATTR, TYPE_XATTR, &ni);
- free(node_blk);
- if (ret)
+ if (fsck_sanity_check_nid(sbi, xnid, F2FS_FT_XATTR, TYPE_XATTR))
return NULL;
}
--
2.25.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [f2fs-dev] [PATCH 2/4] fsck.f2fs: use f2fs_is_valid_blkaddr()
2023-05-12 10:03 [f2fs-dev] [PATCH 1/4] fsck.f2fs: wrap openned codes into fsck_sanity_check_nid() Chao Yu
@ 2023-05-12 10:03 ` Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 3/4] fsck.f2fs: add more debug info in fsck_verify() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 4/4] fsck.f2fs: lookup and relink root inode Chao Yu
2 siblings, 0 replies; 4+ messages in thread
From: Chao Yu @ 2023-05-12 10:03 UTC (permalink / raw)
To: jaegeuk; +Cc: linux-f2fs-devel
use f2fs_is_valid_blkaddr() instead of IS_VALID_BLK_ADDR() to
check validity of data/node's block address.
use is_valid_data_blkaddr() in sanity_check_nid() to check NULL_ADDR
as NEW_ADDR, and print the value in error path explicitly.
Signed-off-by: Chao Yu <chao@kernel.org>
---
fsck/dump.c | 5 +++--
fsck/f2fs.h | 15 +--------------
fsck/fsck.c | 23 +++++++++++++----------
fsck/fsck.h | 2 ++
fsck/mount.c | 4 +++-
5 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/fsck/dump.c b/fsck/dump.c
index b8f6144..dd1f0ab 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -278,7 +278,8 @@ static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 blkaddr)
return;
/* get data */
- if (blkaddr == NEW_ADDR || !IS_VALID_BLK_ADDR(sbi, blkaddr)) {
+ if (blkaddr == NEW_ADDR ||
+ !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) {
memset(buf, 0, F2FS_BLKSIZE);
} else {
int ret;
@@ -588,7 +589,7 @@ int dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
DBG(1, "nat_entry.version [0x%x]\n", ni.version);
DBG(1, "nat_entry.ino [0x%x]\n", ni.ino);
- if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
+ if (!f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) {
MSG(force, "Invalid node blkaddr: %u\n\n", ni.blk_addr);
goto out;
}
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index e65644e..9791071 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -108,6 +108,7 @@ enum {
META_SSA,
META_MAX,
META_POR,
+ DATA_GENERIC,
};
#define MAX_RA_BLOCKS 64
@@ -520,20 +521,6 @@ static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid)
<< (sbi->log_blocks_per_seg - 1)));
}
-static inline bool IS_VALID_BLK_ADDR(struct f2fs_sb_info *sbi, u32 addr)
-{
- if (addr == NULL_ADDR || addr == NEW_ADDR)
- return 1;
-
- if (addr >= le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count) ||
- addr < SM_I(sbi)->main_blkaddr) {
- DBG(1, "block addr [0x%x]\n", addr);
- return 0;
- }
- /* next block offset will be checked at the end of fsck. */
- return 1;
-}
-
static inline bool is_valid_data_blkaddr(block_t blkaddr)
{
if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR ||
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 64db1e5..9180deb 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -236,7 +236,7 @@ static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
get_node_info(sbi, nid, &ni);
- if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+ if (!f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
goto out;
/* read node_block */
@@ -405,12 +405,12 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
return -EINVAL;
}
- if (ni->blk_addr == NEW_ADDR) {
- ASSERT_MSG("nid is NEW_ADDR. [0x%x]", nid);
+ if (!is_valid_data_blkaddr(ni->blk_addr)) {
+ ASSERT_MSG("nid->blk_addr is 0x%x. [0x%x]", ni->blk_addr, nid);
return -EINVAL;
}
- if (!IS_VALID_BLK_ADDR(sbi, ni->blk_addr)) {
+ if (!f2fs_is_valid_blkaddr(sbi, ni->blk_addr, DATA_GENERIC)) {
ASSERT_MSG("blkaddress is not valid. [0x%x]", ni->blk_addr);
return -EINVAL;
}
@@ -676,7 +676,7 @@ void fsck_reada_node_block(struct f2fs_sb_info *sbi, u32 nid)
if (nid != 0 && IS_VALID_NID(sbi, nid)) {
get_node_info(sbi, nid, &ni);
- if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+ if (f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
dev_reada_block(ni.blk_addr);
}
}
@@ -1612,7 +1612,8 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, int casefolded,
struct node_info ni;
get_node_info(sbi, ino, &ni);
- if (IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
+ if (f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
+ DATA_GENERIC)) {
dev_reada_block(ni.blk_addr);
name_len = le16_to_cpu(dentry[i].name_len);
if (name_len > 0)
@@ -1867,7 +1868,7 @@ int fsck_chk_data_blk(struct f2fs_sb_info *sbi, int casefolded,
return 0;
}
- if (!IS_VALID_BLK_ADDR(sbi, blk_addr)) {
+ if (!f2fs_is_valid_blkaddr(sbi, blk_addr, DATA_GENERIC)) {
ASSERT_MSG("blkaddress is not valid. [0x%x]", blk_addr);
return -EINVAL;
}
@@ -1939,7 +1940,8 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
if (c.preen_mode == PREEN_MODE_1 && !c.fix_on) {
get_node_info(sbi, ino, &ni);
if (!IS_VALID_NID(sbi, ino) ||
- !IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
+ !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
+ DATA_GENERIC)) {
free(orphan_blk);
free(new_blk);
return -EINVAL;
@@ -1997,7 +1999,8 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
if (c.preen_mode == PREEN_MODE_1 && !c.fix_on) {
get_node_info(sbi, ino, &ni);
if (!IS_VALID_NID(sbi, ino) ||
- !IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+ !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
+ DATA_GENERIC))
return -EINVAL;
continue;
}
@@ -2136,7 +2139,7 @@ int fsck_chk_meta(struct f2fs_sb_info *sbi)
*/
continue;
- if (!IS_VALID_BLK_ADDR(sbi, blk)) {
+ if (!f2fs_is_valid_blkaddr(sbi, blk, DATA_GENERIC)) {
MSG(0, "\tError: nat entry[ino %u block_addr 0x%x]"
" is in valid\n",
ino, blk);
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 02dcff8..89b1c6e 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -216,6 +216,8 @@ extern int f2fs_set_sit_bitmap(struct f2fs_sb_info *, u32);
extern void fsck_init(struct f2fs_sb_info *);
extern int fsck_verify(struct f2fs_sb_info *);
extern void fsck_free(struct f2fs_sb_info *);
+extern bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
+ block_t blkaddr, int type);
extern int f2fs_ra_meta_pages(struct f2fs_sb_info *, block_t, int, int);
extern int f2fs_do_mount(struct f2fs_sb_info *);
extern void f2fs_do_umount(struct f2fs_sb_info *);
diff --git a/fsck/mount.c b/fsck/mount.c
index 16c98cc..f0b0072 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -767,6 +767,7 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
return 0;
break;
case META_POR:
+ case DATA_GENERIC:
if (blkaddr >= MAX_BLKADDR(sbi) ||
blkaddr < MAIN_BLKADDR(sbi))
return 0;
@@ -1596,7 +1597,8 @@ static int f2fs_early_init_nid_bitmap(struct f2fs_sb_info *sbi)
block_t addr;
addr = le32_to_cpu(nat_in_journal(journal, i).block_addr);
- if (!IS_VALID_BLK_ADDR(sbi, addr)) {
+ if (addr != NULL_ADDR &&
+ !f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC)) {
MSG(0, "\tError: f2fs_init_nid_bitmap: addr(%u) is invalid!!!\n", addr);
journal->n_nats = cpu_to_le16(i);
c.fix_on = 1;
--
2.25.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [f2fs-dev] [PATCH 3/4] fsck.f2fs: add more debug info in fsck_verify()
2023-05-12 10:03 [f2fs-dev] [PATCH 1/4] fsck.f2fs: wrap openned codes into fsck_sanity_check_nid() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 2/4] fsck.f2fs: use f2fs_is_valid_blkaddr() Chao Yu
@ 2023-05-12 10:03 ` Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 4/4] fsck.f2fs: lookup and relink root inode Chao Yu
2 siblings, 0 replies; 4+ messages in thread
From: Chao Yu @ 2023-05-12 10:03 UTC (permalink / raw)
To: jaegeuk; +Cc: linux-f2fs-devel
In order to track details of stat info and repair flow.
[FSCK] valid_block_count matching with CP [Fail] [0x2, 0x0]
[FSCK] valid_node_count matching with CP (de lookup) [Fail] [0x1, 0x0]
[FSCK] valid_node_count matching with CP (nat lookup) [Fail] [0x1, 0x0]
[FSCK] valid_inode_count matched with CP [Fail] [0x1, 0x0]
Info: flush_journal_entries() n_nats: 1, n_sits: 6
Info: write_checkpoint() cur_cp:1
Info: fix_checkpoint() cur_cp:1
Signed-off-by: Chao Yu <chao@kernel.org>
---
fsck/fsck.c | 18 +++++++++++++-----
fsck/mount.c | 7 ++++++-
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 9180deb..3650873 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -2407,6 +2407,8 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi)
ret = f2fs_fsync_device();
ASSERT(ret >= 0);
+
+ MSG(0, "Info: fix_checkpoint() cur_cp:%d\n", sbi->cur_cp);
}
static void fix_checkpoints(struct f2fs_sb_info *sbi)
@@ -3284,7 +3286,8 @@ int fsck_verify(struct f2fs_sb_info *sbi)
if (sbi->total_valid_block_count == fsck->chk.valid_blk_cnt) {
printf(" [Ok..] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt);
} else {
- printf(" [Fail] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt);
+ printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_block_count,
+ (u32)fsck->chk.valid_blk_cnt);
verify_failed = true;
}
@@ -3292,7 +3295,8 @@ int fsck_verify(struct f2fs_sb_info *sbi)
if (sbi->total_valid_node_count == fsck->chk.valid_node_cnt) {
printf(" [Ok..] [0x%x]\n", fsck->chk.valid_node_cnt);
} else {
- printf(" [Fail] [0x%x]\n", fsck->chk.valid_node_cnt);
+ printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_node_count,
+ fsck->chk.valid_node_cnt);
verify_failed = true;
}
@@ -3300,7 +3304,8 @@ int fsck_verify(struct f2fs_sb_info *sbi)
if (sbi->total_valid_node_count == fsck->chk.valid_nat_entry_cnt) {
printf(" [Ok..] [0x%x]\n", fsck->chk.valid_nat_entry_cnt);
} else {
- printf(" [Fail] [0x%x]\n", fsck->chk.valid_nat_entry_cnt);
+ printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_node_count,
+ fsck->chk.valid_nat_entry_cnt);
verify_failed = true;
}
@@ -3308,7 +3313,8 @@ int fsck_verify(struct f2fs_sb_info *sbi)
if (sbi->total_valid_inode_count == fsck->chk.valid_inode_cnt) {
printf(" [Ok..] [0x%x]\n", fsck->chk.valid_inode_cnt);
} else {
- printf(" [Fail] [0x%x]\n", fsck->chk.valid_inode_cnt);
+ printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_inode_count,
+ fsck->chk.valid_inode_cnt);
verify_failed = true;
}
@@ -3317,7 +3323,9 @@ int fsck_verify(struct f2fs_sb_info *sbi)
fsck->chk.sit_free_segs) {
printf(" [Ok..] [0x%x]\n", fsck->chk.sit_free_segs);
} else {
- printf(" [Fail] [0x%x]\n", fsck->chk.sit_free_segs);
+ printf(" [Fail] [0x%x, 0x%x]\n",
+ le32_to_cpu(F2FS_CKPT(sbi)->free_segment_count),
+ fsck->chk.sit_free_segs);
verify_failed = true;
}
diff --git a/fsck/mount.c b/fsck/mount.c
index f0b0072..f19f081 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -2782,8 +2782,11 @@ void flush_journal_entries(struct f2fs_sb_info *sbi)
int n_nats = flush_nat_journal_entries(sbi);
int n_sits = flush_sit_journal_entries(sbi);
- if (n_nats || n_sits)
+ if (n_nats || n_sits) {
+ MSG(0, "Info: flush_journal_entries() n_nats: %d, n_sits: %d\n",
+ n_nats, n_sits);
write_checkpoints(sbi);
+ }
}
void flush_sit_entries(struct f2fs_sb_info *sbi)
@@ -3259,6 +3262,8 @@ void write_checkpoint(struct f2fs_sb_info *sbi)
ret = f2fs_fsync_device();
ASSERT(ret >= 0);
+
+ MSG(0, "Info: write_checkpoint() cur_cp:%d\n", sbi->cur_cp);
}
void write_checkpoints(struct f2fs_sb_info *sbi)
--
2.25.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [f2fs-dev] [PATCH 4/4] fsck.f2fs: lookup and relink root inode
2023-05-12 10:03 [f2fs-dev] [PATCH 1/4] fsck.f2fs: wrap openned codes into fsck_sanity_check_nid() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 2/4] fsck.f2fs: use f2fs_is_valid_blkaddr() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 3/4] fsck.f2fs: add more debug info in fsck_verify() Chao Yu
@ 2023-05-12 10:03 ` Chao Yu
2 siblings, 0 replies; 4+ messages in thread
From: Chao Yu @ 2023-05-12 10:03 UTC (permalink / raw)
To: jaegeuk; +Cc: linux-f2fs-devel
As Stephanos reported in mailing list:
Info: checkpoint state = 1 : unmount
[ASSERT] (sanity_check_nid: 362) --> nid[0x3] ino is 0
The root cause is root inode's nat entry is corrupted, this patch
add logic to search root inode from all node blocks, try to relink
root inode's nat to target node block.
Before:
Info: checkpoint state = 185 : trimmed nat_bits compacted_summary unmount
[lookup_nat_in_journal:3085] ==> Found nid [0x3] in nat cache
[ASSERT] (sanity_check_nat: 404) --> nid->blk_addr is 0x0. [0x3]
Info: root inode is corrupted, search and relink it
Info: possible root inode blkaddr: 0x5a00
[lookup_nat_in_journal:3085] ==> Found nid [0x3] in nat cache
[ASSERT] (sanity_check_nat: 404) --> nid->blk_addr is 0x0. [0x3]
[FSCK] Max image size: 94 MB, Free space: 12194 MB
[FSCK] Unreachable nat entries [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking [Fail]
[FSCK] Hard link checking for regular file [Ok..] [0x0]
[FSCK] valid_block_count matching with CP [Fail] [0x2, 0x0]
[FSCK] valid_node_count matching with CP (de lookup) [Fail] [0x1, 0x0]
[FSCK] valid_node_count matching with CP (nat lookup) [Fail] [0x1, 0x0]
[FSCK] valid_inode_count matched with CP [Fail] [0x1, 0x0]
[FSCK] free segment_count matched with CP [Ok..] [0x17cd]
[FSCK] next block offset is free [Ok..]
[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
Do you want to fix this partition? [Y/N] Y
After:
Info: checkpoint state = 185 : trimmed nat_bits compacted_summary unmount
[lookup_nat_in_journal:3085] ==> Found nid [0x3] in nat cache
[ASSERT] (sanity_check_nat: 404) --> nid->blk_addr is 0x0. [0x3]
Info: root inode is corrupted, search and relink it
Info: possible root inode blkaddr: 0x5a00
[FIX] (fsck_chk_root_inode: 730) --> Relink root inode, blkaddr: 0x5a00
update nat(nid:3) blkaddr [0x5a00] in journal
[fsck_chk_dentry_blk:1978] [ 1] Dentry Block [0x6000] Done : dentries:0 in 214 slots (len:255)
[fsck_chk_inode_blk:1244] Directory Inode: 0x3 [] depth: 1 has 0 files
[FSCK] Max image size: 94 MB, Free space: 12194 MB
[FSCK] Unreachable nat entries [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking [Ok..]
[FSCK] Hard link checking for regular file [Ok..] [0x0]
[FSCK] valid_block_count matching with CP [Ok..] [0x2]
[FSCK] valid_node_count matching with CP (de lookup) [Ok..] [0x1]
[FSCK] valid_node_count matching with CP (nat lookup) [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP [Ok..] [0x1]
[FSCK] free segment_count matched with CP [Ok..] [0x17cd]
[FSCK] next block offset is free [Ok..]
[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
Info: flush_journal_entries() n_nats: 1, n_sits: 6
Info: Duplicate valid checkpoint to mirror position 512 -> 1024
[write_nat_bits:1737] Writing NAT bits pages, at offset 0x000003ff
Info: Write valid nat_bits in checkpoint
Info: write_checkpoint() cur_cp:1
[write_nat_bits:1737] Writing NAT bits pages, at offset 0x000003ff
Info: Write valid nat_bits in checkpoint
Info: fix_checkpoint() cur_cp:1
Signed-off-by: Chao Yu <chao@kernel.org>
---
fsck/fsck.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++---
fsck/fsck.h | 4 ++
fsck/main.c | 4 ++
fsck/mount.c | 18 +++++++
4 files changed, 167 insertions(+), 7 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 3650873..d03f1da 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -386,14 +386,9 @@ err:
return -1;
}
-static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
- struct f2fs_node *node_blk,
- enum FILE_TYPE ftype, enum NODE_TYPE ntype,
- struct node_info *ni)
+static int sanity_check_nat(struct f2fs_sb_info *sbi, u32 nid,
+ struct node_info *ni)
{
- struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
- int ret;
-
if (!IS_VALID_NID(sbi, nid)) {
ASSERT_MSG("nid is not valid. [0x%x]", nid);
return -EINVAL;
@@ -415,6 +410,28 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
return -EINVAL;
}
+ return 0;
+}
+
+int fsck_sanity_check_nat(struct f2fs_sb_info *sbi, u32 nid)
+{
+ struct node_info ni;
+
+ return sanity_check_nat(sbi, nid, &ni);
+}
+
+static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
+ struct f2fs_node *node_blk,
+ enum FILE_TYPE ftype, enum NODE_TYPE ntype,
+ struct node_info *ni)
+{
+ struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+ int ret;
+
+ ret = sanity_check_nat(sbi, nid, ni);
+ if (ret)
+ return ret;
+
ret = dev_read_block(node_blk, ni->blk_addr);
ASSERT(ret >= 0);
@@ -609,6 +626,123 @@ err:
return -EINVAL;
}
+static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr)
+{
+ struct seg_entry *se;
+ u32 offset;
+
+ se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr));
+ offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+ return f2fs_test_bit(offset,
+ (const char *)se->cur_valid_map) != 0;
+}
+
+int fsck_chk_root_inode(struct f2fs_sb_info *sbi)
+{
+ struct f2fs_node *node_blk;
+ int segment_count = SM_I(sbi)->main_segments;
+ int segno;
+ bool valid_bitmap = true;
+ block_t last_blkaddr = NULL_ADDR;
+ nid_t root_ino = sbi->root_ino_num;
+ u64 last_ctime = 0;
+ u32 last_ctime_nsec = 0;
+ int ret = -EINVAL;
+
+ node_blk = calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk);
+
+ MSG(0, "Info: root inode is corrupted, search and relink it\n");
+
+retry:
+ for (segno = 0; segno < segment_count; segno++) {
+ struct seg_entry *se = get_seg_entry(sbi, segno);
+ block_t blkaddr = START_BLOCK(sbi, segno);
+ int ret;
+ int i;
+
+ if (IS_DATASEG(se->type))
+ continue;
+
+ dev_readahead(blkaddr << F2FS_BLKSIZE_BITS,
+ sbi->blocks_per_seg << F2FS_BLKSIZE_BITS);
+
+ for (i = 0; i < sbi->blocks_per_seg; i++, blkaddr++) {
+ if (valid_bitmap ^ is_sit_bitmap_set(sbi, blkaddr))
+ continue;
+
+ ret = dev_read_block(node_blk, blkaddr);
+ ASSERT(ret >= 0);
+
+ if (le32_to_cpu(node_blk->footer.ino) !=
+ root_ino ||
+ le32_to_cpu(node_blk->footer.nid) !=
+ root_ino)
+ continue;
+
+ if (!IS_INODE(node_blk))
+ continue;
+
+ if (le32_to_cpu(node_blk->i.i_generation) ||
+ le32_to_cpu(node_blk->i.i_namelen))
+ continue;
+ break;
+ }
+
+ if (i == sbi->blocks_per_seg)
+ continue;
+
+ if (valid_bitmap) {
+ last_blkaddr = blkaddr;
+ MSG(0, "Info: possible root inode blkaddr: 0x%x\n",
+ last_blkaddr);
+ goto fix;
+ }
+
+ if (last_blkaddr == NULL_ADDR)
+ goto init;
+ if (le64_to_cpu(node_blk->i.i_ctime) < last_ctime)
+ continue;
+ if (le64_to_cpu(node_blk->i.i_ctime) == last_ctime &&
+ le32_to_cpu(node_blk->i.i_ctime_nsec) <=
+ last_ctime_nsec)
+ continue;
+init:
+ last_blkaddr = blkaddr;
+ last_ctime = le64_to_cpu(node_blk->i.i_ctime);
+ last_ctime_nsec = le32_to_cpu(node_blk->i.i_ctime_nsec);
+
+ MSG(0, "Info: possible root inode blkaddr: %u\n",
+ last_blkaddr);
+ }
+
+ if (valid_bitmap) {
+ valid_bitmap = false;
+ goto retry;
+ }
+fix:
+ if (!last_blkaddr) {
+ MSG(0, "Info: there is no valid root inode\n");
+ } else if (c.fix_on) {
+ struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+
+ FIX_MSG("Relink root inode, blkaddr: 0x%x", last_blkaddr);
+ update_nat_journal_blkaddr(sbi, root_ino, last_blkaddr);
+ update_nat_blkaddr(sbi, root_ino, root_ino, last_blkaddr);
+
+ if (f2fs_test_bit(root_ino, fsck->nat_area_bitmap))
+ f2fs_clear_bit(root_ino, fsck->nat_area_bitmap);
+ fsck->chk.valid_nat_entry_cnt++;
+
+ if (!f2fs_test_sit_bitmap(sbi, last_blkaddr))
+ f2fs_set_sit_bitmap(sbi, last_blkaddr);
+ ret = 0;
+ }
+ free(node_blk);
+ return ret;
+}
+
static inline void get_extent_info(struct extent_info *ext,
struct f2fs_extent *i_ext)
{
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 89b1c6e..0f7caf4 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -167,9 +167,11 @@ extern int fsck_chk_quota_node(struct f2fs_sb_info *);
extern int fsck_chk_quota_files(struct f2fs_sb_info *);
extern int fsck_sanity_check_nid(struct f2fs_sb_info *, u32,
enum FILE_TYPE, enum NODE_TYPE);
+extern int fsck_sanity_check_nat(struct f2fs_sb_info *sbi, u32 nid);
extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
enum FILE_TYPE, enum NODE_TYPE, u32 *,
struct f2fs_compr_blk_cnt *, struct child_info *);
+extern int fsck_chk_root_inode(struct f2fs_sb_info *);
extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
struct f2fs_node *, u32 *, struct f2fs_compr_blk_cnt *,
struct node_info *, struct child_info *);
@@ -208,6 +210,8 @@ extern void update_sum_entry(struct f2fs_sb_info *, block_t,
struct f2fs_summary *);
extern void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
extern void nullify_nat_entry(struct f2fs_sb_info *, u32);
+extern void update_nat_journal_blkaddr(struct f2fs_sb_info *sbi, u32 nid,
+ block_t blkaddr);
extern void rewrite_sit_area_bitmap(struct f2fs_sb_info *);
extern void build_nat_area_bitmap(struct f2fs_sb_info *);
extern void build_sit_area_bitmap(struct f2fs_sb_info *);
diff --git a/fsck/main.c b/fsck/main.c
index b01b52c..e8c3dc4 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -885,6 +885,10 @@ static int do_fsck(struct f2fs_sb_info *sbi)
}
}
fsck_chk_orphan_node(sbi);
+
+ if (fsck_sanity_check_nat(sbi, sbi->root_ino_num))
+ fsck_chk_root_inode(sbi);
+
fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, NULL);
fsck_chk_quota_files(sbi);
diff --git a/fsck/mount.c b/fsck/mount.c
index f19f081..4c74888 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -3132,6 +3132,24 @@ void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
free(nat_block);
}
+void update_nat_journal_blkaddr(struct f2fs_sb_info *sbi, u32 nid,
+ block_t blkaddr)
+{
+ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+ struct f2fs_journal *journal = &curseg->sum_blk->journal;
+ int i;
+
+ for (i = 0; i < nats_in_cursum(journal); i++) {
+ if (le32_to_cpu(nid_in_journal(journal, i)) == nid) {
+ nat_in_journal(journal, i).block_addr =
+ cpu_to_le32(blkaddr);
+ MSG(0, "update nat(nid:%d) blkaddr [0x%x] in journal\n",
+ nid, blkaddr);
+ return;
+ }
+ }
+}
+
void duplicate_checkpoint(struct f2fs_sb_info *sbi)
{
struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
--
2.25.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-05-12 10:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-12 10:03 [f2fs-dev] [PATCH 1/4] fsck.f2fs: wrap openned codes into fsck_sanity_check_nid() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 2/4] fsck.f2fs: use f2fs_is_valid_blkaddr() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 3/4] fsck.f2fs: add more debug info in fsck_verify() Chao Yu
2023-05-12 10:03 ` [f2fs-dev] [PATCH 4/4] fsck.f2fs: lookup and relink root inode Chao Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).