f2fs将分区分为super block、cp pack、sit、nat、ssa、main area四个区域,除了cp pack外,其他的区域的组成都比较简单,基本只有一种数据结构,只有cp pack由于承载了check point的功能,所以其组成比较复杂,这篇文章就cp pack的组成来详细讲述。
cp pack是由f2fs_checkpoint、sit_version_bitmap、nat_version_bitmap、orphan inode、data summary、node summary(可能没有)、f2fs_checkpoint来组成。下面将从mount和do_checkpoint两个方位来对cp pack的组成进行详细讲述。
下面是在do_checkpoint的时候关于cp pack的写入过程
static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{
...
start_blk = __start_cp_addr(sbi);
...
update_meta_page(sbi, ckpt, start_blk++);
for (i = 1; i < 1 + cp_payload_blks; i++)
update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE, start_blk++);
if (orphan_num) {
write_orphan_inodes(sbi, start_blk);
start_blk += orphan_blocks;
}
write_data_summaries(sbi, start_blk);
start_blk += data_sum_blocks;
...
if (__remain_node_summaries(cpc->reason)) {
write_node_summaries(sbi, start_blk);
start_blk += NR_CURSEG_NODE_TYPE;
}
update_meta_page(sbi, ckpt, start_blk);
...
}
下面是关于mount时候的读入过程。
int get_valid_checkpoint(struct f2fs_sb_info *sbi)
{
struct f2fs_checkpoint *cp_block;
struct f2fs_super_block *fsb = sbi->raw_super;
struct page *cp1, *cp2, *cur_page;
unsigned long blk_size = sbi->blocksize;
unsigned long long cp1_version = 0, cp2_version = 0;
unsigned long long cp_start_blk_no;
unsigned int cp_blks = 1 + __cp_payload(sbi);
block_t cp_blk_no;
int i;
sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
if (!sbi->ckpt)
return -ENOMEM;
cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr);
cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
cp_start_blk_no += ((unsigned long long)1) << le32_to_cpu(fsb->log_blocks_per_seg);
cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
if (cp1 && cp2) {
if (ver_after(cp2_version, cp1_version))
cur_page = cp2;
else
cur_page = cp1;
} else if (cp1) {
cur_page =