f2fs二三事 block map 1

本文详细解析了f2fs文件系统中的f2fs_map_blocks函数,该函数用于为inode的数据分配内存空间,包括nodeblock和datablock。文章深入介绍了函数的参数和返回值,以及内部结构f2fs_map_blocks的细节。特别关注了create参数为true的情况,描述了如何从extent cache查找信息,以及在找不到相应block时如何创建新block。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

f2fs_map_blocks函数主要作用是为写入inode的数据分配内存空间(包括node block,data block),四个参数:

1) struct inode * inode: 操作的inode结构

2) struct f2fs_map_blocks * map: 要写入的block相关信息的参数

3) int create: 如果为true, 表示如果内中不存在相应的block, 则创建

4) int flag: map block 场景

f2fs_map_block结构:

struct f2fs_map_blocks {
    block_t m_pblk;
    block_t m_lblk;                     //block起始索引值
    unsigned int m_len;              //最大block个数
    unsigned int m_flags;
    pgoff_t *m_next_pgofs;        /* point next possible non-hole pgofs */
    pgoff_t *m_next_extent;        /* point to next possible extent */
    int m_seg_type;
};

对于create参数为true来说,主要关注m_lblk与m_len两个参数,如果create不为true,会从extent cache里面查找。

static int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
						int create, int flag)
{
	unsigned int maxblocks = map->m_len; //map中包含的block总数,一共要map多少个blocks
	struct dnode_of_data dn;
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA;//ALLOC_NODE mode如果不存在,直接创建
	pgoff_t pgofs, end_offset;
	int err = 0, ofs = 1;
	struct extent_info ei;
	bool allocated = false;

	map->m_len = 0;//后面每map一个block, m_len会加1
	map->m_flags = 0;

	/* it only supports block size == page size */
	pgofs =	(pgoff_t)map->m_lblk;//map的第一个block index,最小的block

	if (f2fs_lookup_extent_cache(inode, pgofs, &ei)) {
		map->m_pblk = ei.blk + pgofs - ei.fofs;
		map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs);
		map->m_flags = F2FS_MAP_MAPPED;
		goto out;
	}

        //如果create为true, 表示需要lock住f2fs相关操作
	if (create)
		f2fs_lock_op(F2FS_I_SB(inode));

	/* When reading holes, we need its node page */
	set_new_dnode(&dn, inode, NULL, NULL, 0);
        /*
         * 得到pgofs起始的map block对应的直接node block,它得到的是pgofs(data block index)对 
         * 应的data block的直 
         * 属的(上一层的)direct node_block, 返回的参数包含其在上一层的node page对应的偏移
	 */
	err = get_dnode_of_data(&dn, pgofs, mode);
	
	if (err) {
		if (err == -ENOENT)
			err = 0;
		goto unlock_out;
	}


    /*
     * 若create为true,如果得到的direct node block,在其ofs_in_node偏移处的data block地址为空,则新申请一个data block作为map block
    */
	if (dn.data_blkaddr == NEW_ADDR || dn.data_blkaddr == NULL_ADDR) {
		if (create) {
			if (unlikely(f2fs_cp_error(sbi))) {
				err = -EIO;
				goto put_out;
			}
			err = __allocate_data_block(&dn);//新申请一个data block
			if (err)
				goto put_out;
			allocated = true;
			map->m_flags = F2FS_MAP_NEW;
		} else {
			if (flag != F2FS_GET_BLOCK_FIEMAP ||
						dn.data_blkaddr != NEW_ADDR) {
				if (flag == F2FS_GET_BLOCK_BMAP)
					err = -ENOENT;
				goto put_out;
			}

			/*
			 * preallocated unwritten block should be mapped
			 * for fiemap.
			 */
			if (dn.data_blkaddr == NEW_ADDR)
				map->m_flags = F2FS_MAP_UNWRITTEN;
		}
	}

	map->m_flags |= F2FS_MAP_MAPPED;
	map->m_pblk = dn.data_blkaddr;//刚刚申请的block address
	map->m_len = 1;//已Map block length

    //node_page能表示的最大地址个数, 如果inode,则end_offset为873,表示最多873个data block地 
    //址,是inode去掉meta信息剩余的能表示地址的空间,如果是direct node,则为1018,表示最多能指向
    //1018个data block
	end_offset = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
	dn.ofs_in_node++; //在此node_page 中的下一个block address的offset
	pgofs++;//需要map的下一个地址

get_next://下一个block
	if (dn.ofs_in_node >= end_offset) {//如果node block的下一个地址已经超过了end_offset, 
                                       //node_block中的最大地址,即此node_block的地址已用 
                                       //完,则需要重新查找分配node data block
		if (allocated)
			sync_inode_page(&dn);
		allocated = false;
		f2fs_put_dnode(&dn);

		set_new_dnode(&dn, inode, NULL, NULL, 0);
		err = get_dnode_of_data(&dn, pgofs, mode);
		if (err) {
			if (err == -ENOENT)
				err = 0;
			goto unlock_out;
		}

		end_offset = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
	}

	if (maxblocks > map->m_len) {//如果已经map了的长度没有达到maxblocks,即还没有map完
		block_t blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node);

		if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR) {//如果下一个data block为new或者 
                                                          //null,重新申请一个
			if (create) {
				if (unlikely(f2fs_cp_error(sbi))) {
					err = -EIO;
					goto sync_out;
				}
				err = __allocate_data_block(&dn);
				if (err)
					goto sync_out;
				allocated = true;
				map->m_flags |= F2FS_MAP_NEW;
				blkaddr = dn.data_blkaddr;
			} else {
				/*
				 * we only merge preallocated unwritten blocks
				 * for fiemap.
				 */
				if (flag != F2FS_GET_BLOCK_FIEMAP ||
						blkaddr != NEW_ADDR)
					goto sync_out;
			}
		}

		/* Give more consecutive addresses for the readahead */
		if ((map->m_pblk != NEW_ADDR &&  //如果新分配的block地址连续,则继续
				blkaddr == (map->m_pblk + ofs)) ||
				(map->m_pblk == NEW_ADDR &&
				blkaddr == NEW_ADDR)) {
			ofs++;
			dn.ofs_in_node++;
			pgofs++;
			map->m_len++;
			goto get_next;
		}
	}
sync_out:
	if (allocated)
		sync_inode_page(&dn);
put_out:
	f2fs_put_dnode(&dn);
unlock_out:
	if (create)
		f2fs_unlock_op(F2FS_I_SB(inode));
out:
	trace_f2fs_map_blocks(inode, map, err);
	return err;
}

 

 

 

### RT-DETRv3 网络结构分析 RT-DETRv3 是一种基于 Transformer 的实时端到端目标检测算法,其核心在于通过引入分层密集正监督方法以及一系列创新性的训练策略,解决了传统 DETR 模型收敛慢和解码器训练不足的问题。以下是 RT-DETRv3 的主要网络结构特点: #### 1. **基于 CNN 的辅助分支** 为了增强编码器的特征表示能力,RT-DETRv3 引入了一个基于卷积神经网络 (CNN) 的辅助分支[^3]。这一分支提供了密集的监督信号,能够与原始解码器协同工作,从而提升整体性能。 ```python class AuxiliaryBranch(nn.Module): def __init__(self, in_channels, out_channels): super(AuxiliaryBranch, self).__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) def forward(self, x): return F.relu(self.bn(self.conv(x))) ``` 此部分的设计灵感来源于传统的 CNN 架构,例如 YOLO 系列中的 CSPNet 和 PAN 结构[^2],这些技术被用来优化特征提取效率并减少计算开销。 --- #### 2. **自注意力扰动学习策略** 为解决解码器训练不足的问题,RT-DETRv3 提出了一种名为 *self-att 扰动* 的新学习策略。这种策略通过对多个查询组中阳性样本的标签分配进行多样化处理,有效增加了阳例的数量,进而提高了模型的学习能力和泛化性能。 具体实现方式是在训练过程中动态调整注意力权重分布,确保更多的高质量查询可以与真实标注 (Ground Truth) 进行匹配。 --- #### 3. **共享权重解编码器分支** 除了上述改进外,RT-DETRv3 还引入了一个共享权重的解编码器分支,专门用于提供密集的正向监督信号。这一设计不仅简化了模型架构,还显著降低了参数量和推理时间,使其更适合实时应用需求。 ```python class SharedDecoderEncoder(nn.Module): def __init__(self, d_model, nhead, num_layers): super(SharedDecoderEncoder, self).__init__() decoder_layer = nn.TransformerDecoderLayer(d_model=d_model, nhead=nhead) self.decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_layers) def forward(self, tgt, memory): return self.decoder(tgt=tgt, memory=memory) ``` 通过这种方式,RT-DETRv3 实现了高效的目标检测流程,在保持高精度的同时大幅缩短了推理延迟。 --- #### 4. **与其他模型的关系** 值得一提的是,RT-DETRv3 并未完全抛弃经典的 CNN 技术,而是将其与 Transformer 结合起来形成混合架构[^4]。例如,它采用了 YOLO 系列中的 RepNCSP 模块替代冗余的多尺度自注意力层,从而减少了不必要的计算负担。 此外,RT-DETRv3 还借鉴了 DETR 的一对一匹配策略,并在此基础上进行了优化,进一步提升了小目标检测的能力。 --- ### 总结 综上所述,RT-DETRv3 的网络结构主要包括以下几个关键组件:基于 CNN 的辅助分支、自注意力扰动学习策略、共享权重解编码器分支以及混合编码器设计。这些技术创新共同推动了实时目标检测领域的发展,使其在复杂场景下的表现更加出色。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值