f2fs函数: current_nat_addr(linux 5.18.11)

NAT区中两个segment为一组,互为备份(第一个记作segment A,第二个记作segment B),nid对应的f2fs_nat_entry既可能在A中,也可能在B中,如果nm_i->nat_bitmap中的bit置位,那么B中的entry是有效的,否则 A中的entry有效。 

f2fs挂载时,f2fs_fill_super --> f2fs_build_node_manager --> init_node_manager将存储设备的checkpoint区中的nat位图复制到nm_i->nat_bitmap。

version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size,
					GFP_KERNEL);

nat bitmap中的bit=1,表示nat entry位于segment B中;bit=0,表示nat entry位于segment A中。

struct f2fs_nm_info->nat_blkaddr是NAT区域起始block号。

一个block中含有NAT_ENTRY_PER_BLOCK个entry(455个),根据nid可以算出nat entry在第N个block中(见NAT_BLOCK_OFFSET宏)。为了说明方便,N称为nat block offset(不考虑备份的情况下,从nat area起始block开始算,nat entry在第几个block上)。

/* node block offset on the NAT area dedicated to the given start node id */
#define	NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK)

current_nat_addr函数用于获取nid对应的nat entry所在的block的块地址。

static inline 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;

/* 这段注释会误导人理解下面的代码,请忽略 */
	/*
	 * block_off = segment_off * 512 + off_in_segment
	 * OLD = (segment_off * 512) * 2 + off_in_segment
	 * NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment
	 */

/* 
 * block_off即上文中红字部分提到的nat block offset(这是没有考虑segment备份的偏移值).
 */
	block_off = NAT_BLOCK_OFFSET(start);

/* 
 * NAT区中2个segment互为备份,第一个记作segment A,第二个记作segment B.
 *
 * 由于segment是双备份的,所以需要将block_off << 1, 得到nid=start这个nat entry所在的
 * block的真实偏移(考虑备份,从nat的起始block算).
 * nm_i->nat_blkaddr + (block_off << 1) 计算出nid=start的nat entr所属的磁盘块的块地址.
 * 
 * block_off & (sbi->blocks_per_seg - 1)表示block_off块号在所属segment中的偏移.
 *
 * block_addr表示nat entry位于segment A时,nat entry所属磁盘块的块地址.
 */
	block_addr = (pgoff_t)(nm_i->nat_blkaddr +
		(block_off << 1) -
		(block_off & (sbi->blocks_per_seg - 1)));

/* 
 * nm_i->nat_bitmap置位,表示nat entry位于segment B,
 * 将block_addr再加上一个segment中的block数,计算出nat entry所属磁盘块的块地址.*/
	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
		block_addr += sbi->blocks_per_seg;

	return block_addr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值