经过进一步的阅读代码,现昨天的一些观点似乎有些问题,把我的一些结论贴出来,请师兄指正。
1.在函数 exfs_blocklayout_get()中,有如下代码
Exfs_alloc_blocks()定义如下:
这里面涉及到三个概念
Blocks;segment blocks; alloc_bits;
这三个概念在代码中如下注释
Blocks是物理磁盘块,大小为4K
Segment是三级间址的粒度(和郭博交流后得出的结论,不是非常确定),默认大小是64k
Alloc bits 是描述每次layout分配的粒度参照值为1M
则 segment_length ==1 << allocbits << segment bits << 12(即为block bits)
造成之前的误解,主要是segment_length命名导致将其理解为 1 << segment bits << 12(即为blockbits);
最好改为alloc_length;
2在函数exfs_blocklayout_get()中,把要分配的长度截取为一个一个的segment_length之后,调用下面这个函数;
Exfs_get_blocknr_offset()入口参数是经过处理的被分配线性地址尾部的逻辑块的块号。
在 Exfs_get_blocknr_offset()中,
Segno是通过把iblock(逻辑块号)转换为以segment为粒度的偏移(如果把segment称为段,则为段号)
Exfs_block_to_path()函数是把此段号转换为三级间址编码,将每一级的偏移量放到offset[4]数组中。
其代码如下:
其中,各变量含义如下
ptrs:一个物理块上可以存放多少个物理地址。
ptrs_bits :ptrs有多少位 相等于sizeof(ptrs)
direct_blocks:三级间址的数组中,表示直接地址的数量
indirect和double分别代表二级和三级的数量。
若一个地址需要三级索引来表示。
offset[0]= EXFS_TIND_BLOCK;在i_data[]数组中的偏移量,即为三间址的一级地址
offset[1] 表示的是在第一级中的偏移量
offset[2]表示 第二级中的偏移量
offset[3]表示的是第三级中的偏移量
回到Exfs_get_blocknr_offset()函数,
此函数中,根据offset[] 和depth,解析三级间址,并把物理地址存到一个chain[]中,chain[]的类型为
typedef struct {
u32 *p;
u32 key;
struct buffer_head *bh;
} Indirect
其中,bh 指向间接索引块的内存缓存,p 指向此索引块中的某一个entry(一个entry对应一个物理块地址),而KEY的值为物理块(或者应该叫物理segment)的地址。
若exfs_get_branch()发现当前的逻辑地址已经在三级间址中,则返回NULL;否则返回查找过程的断点(即为现在文件的末尾),然后由后面的代码完成真正的分配。