fsck_chk_inode_blk接下来就是对一个文件进行处理了,内容比较丰富。首先对inode对应的地址在f2fs_fsck的main_area_bitmap中有没有置位,如果没有置位,也就是检查到了一个新的inode,将f2fs_fsck中的check_result的valid_inode_cnt++,这里需要检查的原因是,可能有硬链接这些在之前就已经将main_area_bitmap相应的位置位了。
if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0)
fsck->chk.valid_inode_cnt++;
接下来处理文件的硬链接问题。由于目录是没有硬链接的,所以检查该inode对应的文件类型时候不是目录F2FS_FT_DIR,如果是目录就直接将main_area_bitmap中相应的位置位,然后跳过硬链接的处理。如果不是目录就需要检查该inode所在的block地址在main_area_bitmap中有没有置位过,如果没有置位,那就是第一次检查这个inode,检查其i_links是否大于1,也就是这个inode存不存在其他的硬链接,满足就先通过函数add_into_hard_link_list其加入到f2fs_fsck管理的一个硬链接链表hard_link_list_head中。如果i_link不大于1,那就说明不存在硬链接,不用管了。如果置位过,那就说明,这是之前检查的inode的硬链接了。通过函数find_and_dec_hard_link_list在f2fs_fsck管理的一个硬链接链表hard_link_list_head中找到该inode对应的链表node,然后减少链表node中的链接数,当这个链接数达到1时,说明这个inode所有链接的地方全部处理完了,从链表里面删掉。但是如果出现意外,没有在硬链接的链表中找到对应的链表node,那就说明,实际的硬链接数超过了inode字段中的i_links,这个时候如果要修复那就需要将inode中的i_links++。所以正常情况下,这个链表在所有的inode检查完成之后是NULL,如果不为NULL,那就说明该链表node对应的inode的i_links字段多了,而其实际的链接数就记录在链表node的actual_links字段中,这个会在f2fs_verify中处理。
if (ftype == F2FS_FT_DIR) {
f2fs_set_main_bitmap(sbi, ni->blk_addr, CURSEG_HOT_NODE);
} else {
if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
f2fs_set_main_bitmap(sbi, ni->blk_addr, CURSEG_WARM_NODE);
if (i_links > 1 && ftype != F2FS_FT_ORPHAN && !is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
add_into_hard_link_list(sbi, nid, i_links);
fsck->chk.multi_hard_link_files++;
}
} else {
DBG(3, "[0x%x] has hard links [0x%x]\n", nid, i_links);
if (find_and_dec_hard_link_list(sbi, nid)) {
ASSERT_MSG("[0x%x] needs more i_links=0x%x", nid, i_links);
if (c.fix_on) {
node_blk->i.i_links = cpu_to_le32(i_links + 1);
need_fix = 1;
FIX_MSG("File: 0x%x " "i_links= 0x%x -> 0x%x", nid, i_links, i_links + 1);
}
goto skip_blkcnt_fix;
}
return;
}
}
接下来是内联属性的问题,这个通过函数fsck_chk_xattr_blk完成。fsck_chk_xattr_blk首先检查i_xattr_nid字段==0看一下存不存在内联属性块,如果没有直接返回。如果i_xattr_nid!=0,那就说明存在内联属性的node。存在内联属性的node之后,先调用sanity_check_nid对nid进行基本的检查,然后需要将inode的i_blocks++;并将内联node所在的block地址在f2fs_fsck的main_area_bitmap置位。如果检查过程中出错的话,这时其nid在f2fs_fsck的nat_area_bitmap是没有clear的,这个留着f2fs_verify处理,这时在inode对应的i_xattr_nid赋值0,表示丢掉这个内联的node。
if (fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt) && c.fix_on) {
node_blk->i.i_xattr_nid = 0;
need_fix = 1;
FIX_MSG("Remove xattr block: 0x%x, x_nid = 0x%x", nid, le32_to_cpu(node_blk->i.i_xattr_nid));
}
static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cnt)
{
struct f2fs_node *node_blk = NULL;
struct node_info ni;
int ret = 0;
if (x_nid == 0x0)
return 0;
node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
ASSERT(node_blk != NULL);
if (sanity_check_nid(sbi, x_nid, node_blk, F2FS_FT_XATTR, TYPE_XATTR, &ni)) {
ret = -EINVAL;
goto out;
}
*blk_cnt = *blk_cnt + 1;
f2fs_set_main_bitmap(sbi, ni.blk_addr, CURSEG_COLD_NODE);
DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid);
out:
free(node_blk);
return ret;
}
如果文件类型是F2FS_FT_CHRDEV、F2FS_FT_BLKDEV、F2FS_FT_FIFO、F2FS_FT_SOCK直接跨过数据的检查。
if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK)
goto check;
接下来是处理inode下的数据的问题了,数据的检查分为下面的三种情况:
第一种情况是内联数据F2FS_INLINE_DATA。首先检查i_addr的起始地址应该是0,不是就进行修复。另外就是如果没有设置F2FS_DATA_EXIST,但是在f2fs_inode的盛放内联数据的区域有数据(不是全是