F2FS源码分析-6.2 [其他重要数据结构以及函数] 逻辑地址到物理地址映射的原理以及实现-f2fs_map_blocks函数
2020-02-07 12:54
369 查看
f2fs_map_blocks的作用与源码分析
函数
f2fs_map_blocks主要作用是F2FS通过
f2fs_get_dnode_of_data函数完成逻辑地址到物理地址的映射以后,根据读写流程的不同,完成的一系列读写前的宇处理。
f2fs_map_blocks的读写流程的作用
- 对读的作用: 通过该函数根据逻辑地址找到物理地址,然后从磁盘读取出数据。
- 对写的作用: 文件在写入数据之前,会执行一个preallocate的过程,这个过程会调用
f2fs_map_blocks
函数对即将要写入数据的逻辑块进行预处理,如果是append的方式写入数据,则将物理地址初始化为NEW_ADDR; 如果是rewrite的方式写入数据,则不作改变。
f2fs_map_blocks的核心数据结构
f2fs_map_blocks函数的核心是
f2fs_map_blocks数据结构,如下所示,它保存了一系列映射信息。
struct f2fs_map_blocks { block_t m_pblk; // 保存的是物理地址,可以通过这个物理地址访问磁盘读取信息 block_t m_lblk; // 保存的逻辑地址,即文件的page->index unsigned int m_len; // 需要读取的长度 unsigned int m_flags; // flags表示获取数据状态,如F2FS_MAP_MAPPED pgoff_t *m_next_pgofs; // 指向下一个offset };
读流程下的f2fs_map_blocks的核心逻辑
一般的读流程,会进行如下的数据结构初始化:
map.m_lblk = block_in_file; // 设置逻辑地址page->index map.m_len = len; // 设置需要读取的长度 f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_READ); // 0设定非创建模式,F2FS_GET_BLOCK_READ设定搜索模式
即通过逻辑地址和读取长度找到对应的物理地址,与读流程相关的核心逻辑如下面代码所示:
int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag) { unsigned int maxblocks = map->m_len; // 设定最大搜索长度 int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA; // LOOKUP_NODE_RA模式 map->m_len = 0; // 将len重新设置为0 map->m_flags = 0; pgofs = (pgoff_t)map->m_lblk; // page->index // 第一步:先从extent找,如果在extent找到,就可以马上返回 if (!create && 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; } // 第二步:根据page->index找到对应的dn,dn是一个包含了物理地址的数据结构 set_new_dnode(&dn, inode, NULL, NULL, 0); err = get_dnode_of_data(&dn, pgofs, mode); // 第三步:从dn获取物理地址 blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node); ... map->m_pblk = blkaddr; ... return err; }
写流程下的f2fs_map_blocks的核心逻辑
一般的读流程,会进行如下的数据结构初始化:
map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos); // 计算得到页偏移 map.m_len = F2FS_BYTES_TO_BLK(iocb->ki_pos + iov_iter_count(from)); // 计算得到需要读取的页数 f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO); // 1设定创建模式,F2FS_GET_BLOCK_PRE_AIO表示用于预分配物理页
写流程下的
f2fs_map_blocks函数作用是先根据逻辑地址读取物理地址出来,如果这个物理地址没有被分配过(NULL_ADDR),则初始化为新地址(NEW_ADDR),用于下一步的写入磁盘的操作,与写流程相关的核心逻辑如下面代码所示:
int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag) { unsigned int maxblocks = map->m_len; int mode = create ? ALLOC_NODE : LOOKUP_NODE; map->m_len = 0; map->m_flags = 0; pgofs = (pgoff_t)map->m_lblk; end = pgofs + maxblocks; // 第一步:根据page->index找到对应的dn,dn是一个包含了物理地址的数据结构 set_new_dnode(&dn, inode, NULL, NULL, 0); err = f2fs_get_dnode_of_data(&dn, pgofs, mode); // 第二步:从dn获取物理地址 blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node); // 第三步:如果blkaddr == NULL_ADDR表示这个是从来未使用过的物理页,即目前运行的是append写, // 因此将其记录下来。 if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (blkaddr == NULL_ADDR) { prealloc++; // 记录需要与分配的物理页的数目 last_ofs_in_node = dn.ofs_in_node; } } if (flag == F2FS_GET_BLOCK_PRE_AIO && (pgofs == end || dn.ofs_in_node == end_offset)) { dn.ofs_in_node = ofs_in_node; // 第四步:根据prealloc记录的从未被使用过的块的数目, // 通过函数f2fs_reserve_new_blocks,将他们的值由NULL_ADDR转换为NEW_ADDR,用于下一步写入磁盘 err = f2fs_reserve_new_blocks(&dn, prealloc); if (err) goto sync_out; map->m_len += dn.ofs_in_node - ofs_in_node; if (prealloc && dn.ofs_in_node != last_ofs_in_node + 1) { err = -ENOSPC; goto sync_out; } dn.ofs_in_node = end_offset; } ... return err; }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- F2FS源码分析-5.1 [数据恢复流程] 数据恢复的原理以及方式
- Linux-0.11内核源码分析系列:关于线性地址,逻辑地址,物理地址的关系与区别
- 类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)
- PHP strtotime函数用法、实现原理和源码分析
- Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
- vmalloc中物理地址重映射函数分析
- PHP strtotime函数用法、实现原理和源码分析
- Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
- HashMap实现原理以及与其他Map实现类的区别
- BitSet数据结构以及jdk中实现源码分析
- BitSet数据结构以及jdk中实现源码分析
- spark ml 算法原理剖析以及具体的源码实现分析
- Map数据结构以及Map相关方法的底层实现原理
- wcf基础知识之ListenUri和ListenUriMode实现 逻辑地址和物理地址的分离
- MmMapIoSpace以及MmUnmapIoSpace,VirtualAlloc和VirtualCopy 函数的实现原理以及实现方法
- linux epoll模型源码分析 一 函数实现
- softirq原理以及源码分析
- jQuery源码分析系列(35) : Ajax - jsonp的实现与原理
- 凹凸映射(Bump Map)实现原理
- 深入剖析Spring Web源码(十四) - 处理器映射,处理器适配器以及处理器的实现 - 处理器的实现架构 - 注解控制器