前言
在前面的介绍中,f2fs保证一致性有两种方法:前滚恢复和后滚恢复。前滚恢复需要配合fsync流程使用,先不进行介绍。而后滚恢复就是本章节需要介绍的CheckPoint相关内容。所谓的文件系统一致性,可以简单类比交易操作,即交易双方中一方资金减少,另一方资金增加,任何时候(即使系统崩溃)都不应该出现一方资金减少,另一方资金没有增加,或者反过来,一方资金没有减少,另一方资金却增加了。这些都是违背了一致性。交易操作中常使用原子事务原理,只有最终提交交易完成操作,才算最终完成交易。如果没有提交交易完成操作,那么这笔交易可以被撤销。
CP介绍
CP是Checkpoint的缩写。上面将CP原理和交易流程做了类比,如果具体来说CP功能就是:将当前内存缓存的管理数据,写入到存储介质,一旦发生掉电或者宕机等事件,还可以恢复到上一次CP的状态。当然,还没有来得及做CP的修改,最终会丢失,所以掌握CP的时机显得尤为重要。因为CP可能需要做大量IO操作,非常耗时,但是不做CP的话,刚修改的数据可能会丢失,所以需要平衡好两者。
CP数据结构
盘上布局
struct f2fs_checkpoint {
__le64 checkpoint_ver; /* checkpoint block version number */
__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 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 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[];
} __packed;
一个f2fs_checkpoint代表CP pack,其作用是记录本次CP的基本信息,包括版本号、sit和nat的bitmap使用情况、block的使用情况等等。
- checkpoint_ver:本次CP的版本号。每次写CP时,都会将版本号递增,版本号越大,表示数据越新。在恢复时,优先选择版本号大的CP。
- user_block_count:当前用户已经使用的block数量。
- valid_block_count:Main Area区域已经使用的block数量。
- rsvd_segment_count:为GC流程保留的segment数量。
- free_segment_count:Main Area区域空闲的segment数量。
- cur_node_segno:当前正在使用的node segment id号,对应curseg的数据。
- cur_node_blkoff:当前正在使用node segment的下一个待使用的node id。
- cur_data_segno:当前正在使用的data segment id号,对应curseg的数据。
- cur_data_blkoff:当前正在使用data segment的下一个待使用