Checkpoint维护了f2fs的数据一致性,例如segment、node、active segment的状态等。
F2FS在满足一定的条件的情况下,会将当前系统的分配状态写入到Checkpoint中,万一系统出现突然宕机,可以从Checkpoint中恢复到上次回写时的状态。
F2FS维护了两个Checkpoint结构,其中一个是当前正在使用的Checkpoint。另外一个上次回写的稳定的cp。
如果系统出现了宕机,就恢复到上次的稳定cp中。
CP占用2个segment大小(4M)。
有资料说CP区域就是两个struct f2fs_checkpoint。但是还有资料说还包含orphan node和active segments。
暂且认为盘上的cp区域由两套f2fs_checkpoint+orphan node+active segment组成。
F2FS使用数据结构f2fs_checkpoint
表示Checkpoint结构,它保存在磁盘中f2fs_super_block
之后区域中,数据结构如下。
需要特别注意的是cur_node_segno
、cur_node_blkoff
、cur_data_segno
、cur_data_blkoff
。
cur_xxx_segno
以及cur_xxx_blkoff
记录了上次Checkpoint时,系统正在使用的log的segment number,以及分配到这个segment的哪个位置。struct f2fs_checkpoint {
__le64 checkpoint_ver; /* CP版本,用于比较新旧版本进行恢复 */
__le64 user_block_count; /* # of user blocks */
__le64 valid_block_count; /* # of valid blocks in main area */
__le32 rsvd_segment_count; /* # of reserved segments for gc */
__le32 overprov_segment_count; /* # of overprovision segments */
__le32 free_segment_count; /* # of free segments in main area */
/* information of current node segments */
__le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
__le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
/* information of current data segments */
__le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
__le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
__le32 ckpt_flags; /* Flags : umount and journal_present */
__le32 cp_pack_total_block_count; /* total # of one cp pack */
__le32 cp_pack_start_sum; /* start block number of data summary */
__le32 valid_node_count; /* Total number of valid nodes */
__le32 valid_inode_count; /* Total number of valid inodes */
__le32 next_free_nid; /* Next free node number */
__le32 sit_ver_bitmap_bytesize; /* Default value 64 */
__le32 nat_ver_bitmap_bytesize; /* Default value 256 */
__le32 checksum_offset; /* checksum offset inside cp block */
__le64 elapsed_time; /* mounted time */
/* allocation type of current segment */
unsigned char alloc_type[MAX_ACTIVE_LOGS];
/* SIT and NAT version bitmap */
unsigned char sit_nat_version_bitmap[1];
} __packed;
为了维护数据一致性还有其他结构,如orphan node和active segment
orphan node区域保存orphan node list。这个区域是动态的,不一定有。
active segment(或CURSEG)区域正在分配数据的log对应的segment。一共有6个。
cur_node_segno[MAX_ACTIVE_NODE_LOGS]
和cur_data_segno[MAX_ACTIVE_DATA_LOGS]
定位cp时的segment。cur_node_blkoff[MAX_ACTIVE_NODE_LOGS]
以及cur_data_blkoff[MAX_ACTIVE_DATA_LOGS]
定位分配到了curseg的哪一个block