补充一下之前略过的关于direct node、indirect node、dindirect node的检查。
fsck_chk_didnode_blk,对NIDS_PER_BLOCK个nid进行遍历,如果nid ==0,就直接跳过,nid!=0的话,就调用以TYPE_INDIRECT_NODE的标志调用fsck_chk_node_blk。如果成功就直接将i_block++。否则将该位置的nid置为0。最后如果进行过修复,则将修复过的node写回。
int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt, struct child_info *child)
{
int i = 0;
int need_fix = 0, ret = 0;
for (i = 0; i < NIDS_PER_BLOCK; i++) {
if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
goto skip;
ret = fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]),ftype,
TYPE_INDIRECT_NODE, blk_cnt, child);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL) {
if (!c.fix_on)
printf("should delete in.nid[i] = 0;\n");
else {
node_blk->in.nid[i] = 0;
need_fix = 1;
FIX_MSG("Set double indirect node 0x%x -> 0", i);
}
skip:
child->pgofs += ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
}
}
if (need_fix && !c.ro) {
struct node_info ni;
nid_t nid = le32_to_cpu(node_blk->footer.nid);
get_node_info(sbi, nid, &ni);
ret = dev_write_block(node_blk, ni.blk_addr);
ASSERT(ret >= 0);
}
return 0;
}
fsck_chk_idnode_blk,对NIDS_PER_BLOCK个nid进行遍历,如果nid ==0,就直接跳过,nid!=0的话,就调用以TYPE_DIRECT_NODE的标志调用fsck_chk_node_blk。如果成功就直接将i_block++。否则将该位置的nid置为0。最后如果进行过修复,则将修复过的node写回。
int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt, struct child_info *child)
{
int need_fix = 0, ret;
int i = 0;
for (i = 0; i < NIDS_PER_BLOCK; i++) {
if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
goto skip;
ret = fsck_chk_node_blk(sbi, inode, le32_to_cpu(node_blk->in.nid[i]), ftype,
TYPE_DIRECT_NODE, blk_cnt, child);
if (!ret)
*blk_cnt = *blk_cnt + 1;
else if (ret == -EINVAL) {
if (!c.fix_on)
printf("should delete in.nid[i] = 0;\n");
else {
node_blk->in.nid[i] = 0;
need_fix = 1;
FIX_MSG("Set indirect node 0x%x -> 0", i);
}
skip:
child->pgofs += ADDRS_PER_BLOCK;
}
}
if (need_fix && !c.ro) {
struct node_info ni;
nid_t nid = le32_to_cpu(node_blk->footer.nid);
get_node_info(sbi, nid, &ni);
ret = dev_write_block(node_blk, ni.blk_addr);
ASSERT(ret >= 0);
}
return 0;
}
fsck_chk_idnode_blk,对ADDRS_PER_BLOCK个块地址进行遍历,如果addr ==0,就直接跳过,addr!=0的话,就调用fsck_chk_data_blk对数据块进行检查。如果成功就直接将i_block++。否则将该位置的addr置为0。最后如果进行过修复,则将修复过的node写回。
int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk,
u32 *blk_cnt, struct child_info *child, struct node_info *ni)
{
int idx, ret;
int need_fix = 0;
child->p_ino = nid;
child->pp_ino = le32_to_cpu(inode->i_pino);
for (idx = 0; idx < ADDRS_PER_BLOCK; idx++, child->pgofs++) {
block_t blkaddr = le32_to_cpu(node_blk->dn.addr[idx]);
check_extent_info(child, blkaddr, 0);
if (blkaddr == 0x0)
continue;
ret = fsck_chk_data_blk(sbi, blkaddr, child, le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
nid, idx, ni->version, file_is_encrypt(inode));
if (!ret) {
*blk_cnt = *blk_cnt + 1;
} else if (c.fix_on) {
node_blk->dn.addr[idx] = 0;
need_fix = 1;
FIX_MSG("[0x%x] dn.addr[%d] = 0", nid, idx);
}
}
if (need_fix && !c.ro) {
ret = dev_write_block(node_blk, ni->blk_addr);
ASSERT(ret >= 0);
}
return 0;
}