f2fs系列文章——sit/nat_version_bitmap

    f2fs为了防止宕机对元数据造成不可恢复的损害,所以sit/nat这种元数据有着两个副本,但是这两个副本只有一个是表示最新的数据,f2fs通过保存在cp pack中的sit/nat version bitmap来指示哪个才是最新的。本文将讲述sit和nat两个副本的放置情况,以及sit/nat version bitmap在cp pack中的放置情况,最后将描述sit/nat更新时的version bitmap的变化情况。

    下面是根据nid来获取该nid所对应的最新的f2fs_nat_entry所在的f2fs_nat_block所在的块地址。

static pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
{
	struct f2fs_nm_info *nm_i = NM_I(sbi);
	pgoff_t block_off;
	pgoff_t block_addr;
	int seg_off;

	block_off = NAT_BLOCK_OFFSET(start);
	seg_off = block_off >> sbi->log_blocks_per_seg;

	block_addr = (pgoff_t)(nm_i->nat_blkaddr + (seg_off << sbi->log_blocks_per_seg << 1) +
			(block_off & ((1 << sbi->log_blocks_per_seg) -1)));

	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
		block_addr += sbi->blocks_per_seg;
	return block_addr;
}

    根据上面的源码可以看出f2fs_nat_block是以下图的形式放置的。也就是f2fs_nat_entry为最小的单元,但是以f2fs_nat_block的组织形式组织成磁盘上最小的单位块,然后相邻的这些f2fs_nat_block形成一个segment,而相邻的这些f2fs_nat_block的副本也形成一个segment与其相邻放置。然后所有的这些segment以这样的方式重复。

    下面是根据segno来获取该segment所对应的最新的f2fs_sit_entry所在的f2fs_sit_block所在的块地址。

static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, unsigned int start)
{
	struct sit_info *sit_i = SIT_I(sbi);
	unsigned int offset = SIT_BLOCK_OFFSET(start);
	block_t blk_addr = sit_i->sit_base_addr + offset;

	check_seg_range(sbi, start);

	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
		blk_addr += sit_i->sit_blocks;

	return blk_addr;
}

    根据上面的源码可以看出f2fs_sit_block是以下图的形式放置的。也就是f2fs_sit_entry为最小的单元,但是以f2fs_sit_block的组织形式组织成磁盘上最小的单位块,然后所有的f2fs_sit_block的第一个副本相邻放置,而这些f2fs_sit_block的第二个副本叶祥林放置并排列在第一个副本的最后一个f2fs_sit_block的后面。

 

    接着是关于sit/nat version bitmap在cp pack中的放置情况,这个根据下面的函数可以看出。首先解释一下cp_payload这个字段,由于在f2fs的cp pack中的第一个块本来应该放置f2fs_checkpoint这个数据结构的,但是我们发现这个数据结构的大小不够一个block,也就是还有剩余的空间,所以当si/nat version bitmap比较大的时候,那么这两个bitmap是需要额外的空间来保存的,所以cp_payload记录的就是这个额外的空间的块的数量。

static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
{
	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
	int offset;

	if (__cp_payload(sbi) > 0) {
		if (flag == NAT_BITMAP)
			return &ckpt->sit_nat_version_bitmap;
		else
			return (unsigned char *)ckpt + F2FS_BLKSIZE;
	} else {
		offset = (flag == NAT_BITMAP) ?
			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
		return &ckpt->sit_nat_version_bitmap + offset;
	}
}

    根据源码分析一下:当cp_payload > 0时,也就是存在额外的空间来存放bitmap。如果是NAT_BITMAP,那么nat version bitmap是放置在以f2fs_checkpoint的最后一个字段开始的长度为nat_ver_bitmap_bytesize的一段空间中,而对于SIT_BITMAP,sit version bitmap就是放置以cp pack第一个块后面的第二个块开始的长度为sit_ver_bitmap_bytesize的一段空间中。当cp_paylo

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值