[ext4]空间管理 - 查找块

时间:2022-09-06 08:37:15


在文件系统中,当需要执行写操作时,肯定是需要查找需要写入的块。那么如何查找块哪?

 

Ext4系统中,有两个函数是可能执行查找操作的:ext4_getblk()ext4_get_block()

其中ext4_getblk(),原型如下:

structbuffer_head *ext4_getblk(handle_t *handle, struct inode *inode,

                                    ext4_lblk_tblock, int create, int *errp)

该函数的主要功能:基于给定的inode,查找或创建block,并返回与其映射的buffercreate标识用于表示当查找不到时,是否执行分配块操作。

本节我们不关注块分配操作;因此create0

ext4_get_block()函数原型如下:

intext4_get_block(struct inode *inode, sector_t iblock,

                    struct buffer_head *bh, int create)

该函数的主要功能:基于给定的inode,查找文件的逻辑块iblock,并将其与bh进行映射,如果没有查找到,若create1,则执行块分配操作为文件申请新的block,然后再与bh建立映射。这个函数用于适配VFS层接口。

 

无论ext4_getblk()还是ext4_get_block(),都是先初始化structext4_map_blocks map,然后调用函数ext4_map_blocks(),实现块查找功能。

先来看一下ext4_map_blocks这个结构体:

struct ext4_map_blocks{

        ext4_fsblk_t m_pblk;

        ext4_lblk_t m_lblk;

        unsigned int m_len;

        unsigned int m_flags;

};

在分析ext4_map_blocks结构体之前,我们先来熟悉两个概念:物理块号、逻辑块号。对于一个存储设备(这个设备是可以是存储分区)格式化为某个文件系统的过程中,一般,都会给予给定的block值对整个存储分区划分很多个大小为block size的单元,每个单元,我们都称之为块,每一个块都有一个块号,是以存储分区起始位置为偏移计算的,我们一般称之为物理块号。当某一个块被分配给某一个文件用来存放Data后,那么这个块给予文件起始位置又被赋予了一个块号,这个块号只对于该文件有效,这个块号我们一般称之为逻辑块号。

ext4_map_blocks结构体主要用来描述需要映射的空间信息,包含映射空间的物理块号,逻辑块号,空间大小,属性标识。在查找之前,一般都是知道逻辑块号和空间大小的。

 

ext4_map_blocks()的原型如下:

intext4_map_blocks(handle_t *handle, struct inode *inode,

                     struct ext4_map_blocks *map, int flags)

1.首先调用ext4_es_lookup_extent()查找extent status treeextent status tree是描述extent在内存中信息与状态的树,可以理解为extent tree在内存的中组织。在查找extent status tree的过程中,先检查cache extents是否满足条件,否则遍历整个extent status tree

2.如果在缓存中没有查找到,那么我们就需要从磁盘上读出extent tree数据,然后查找。实现函数为ext4_ext_find_extent()。那么是如何实现的哪?

说起来,也十分的简单。

由前述[磁盘布局extent tree]可知,extent tree在磁盘上都是以extent block为单位存储的。

首先从inode中找出根节点,在根节点中的四个entry中通过二分法查找包含指定blockentry,然后通过该entry信息读取下一级extent blockbuffer中。该buffer中包含很多entry,继续通过二分法查找包含指定blockenrty,然后再读取下一级entry,依次类推;直至到叶子节点或无下级的节点。

从而我们得到与制定block最相近的extent(若查找不到,则返回小于block的最大的extent,即左侧的extent).

假如寻找到合适的包含block块号的extent,则计算出对应的物理block和在这个extent中以block为起始点到extent终点的长度(如果这个长度大约所要求的长度,则取所要求的长度)

out:

        if (allocated > map->m_len)

                  allocated = map->m_len;

        ext4_ext_show_leaf(inode, path);

        map->m_flags |= EXT4_MAP_MAPPED;

        map->m_pblk = newblock;

        map->m_len = allocated;

 

如果没有找到块,因为之前的Create标识已经说明即使没有找到,也不需要创建,所以直接返回0.

 

OK,块查找操作分析结束。


作者:Younger Liu,

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。