块分配映射表
块分配映射表用来为整个聚集跟踪分配或释放的磁盘块。由于聚集内所有的文件集共享相同的磁盘块池,在分配或释放磁盘块时,聚集内所有的文件集可使用该分配映射表。
块分配映射表本身是聚集inode2描述的文件。当初始创建聚集时,分配包括聚集空间的映射表数据块。映射表将随着聚集的扩充或紧缩而相应动态地增大或缩小。
块分配映射表跟踪是否每个个别的聚集块被分配还是释放。
映射表的每页长度为4K。映射表包含三种类型的页:bmap控制页、dmap控制页和dmap页。
每个dmap包含表示每个聚集块的一位。第i位表示第i个逻辑聚集块的分配状态。它由structdmap_t的jfs_dmap.h文件定义。每个dmap页包括8K的聚集块。
因为块分配映射表可能有许多dmap页,它们由dmap控制页组织。这些页改进了查找空闲块的大盘区的性能。聚集的大小将决定需要多少页和多少层。至多有三层,它允许的聚集块的最大尺寸是2(43)。如果不是所有层都需要,块映射表inode是每个没有使用层的第一页有“洞”的稀疏文件。
JFS使用提交策略确保控制数据可靠更新。可靠更新意味着一旦系统出错时,要维持一致的JFS结构和资源分配状态。为了保证块分配映射表是一致状态,JFS维护dmap结构中的两张映射表,工作映射表和持续映射表。工作映射表记录当前分配状态。持续映射表记录提交的分配状态,由磁盘上找到的或JFS日志或提交的JFS事务内的记录描述的分配状态组成。当释放聚集块时,首先更新永久映射表。当分配聚集块时,首先更新工作映射表。位值为0表示空闲资源,值为1表示已分配资源。
块分配映射表的dmap控制页包含与dmap结构中树相似的树,除叶层包含1024个元素外。dmap控制页由structdmapctl_t定义。可在jfs_dmap.h.文件中找到它。
要注意,dmap结构中的这一字段是一个平面数组,但它表示图中显示的树。树跟踪除最底层之外的每层上连续块的最大号。树的最底层,从树[85]到树[341],包含下面描述的工作映射表的二进制搭档表示法。树的其它层包含来自下一较低层的四个部分的最大数目相连空闲块。
二进制搭档系统用来完成每个摘要树的叶层。通过首先为位图的每个字获得空闲位的最长二进制搭档字符串而形成dmap结构的树。字符以2的幂编码,-1用来表示已分配全部。
然后,使用二进制搭档系统完成树的叶。通过取得从指定索引开始、只包括其以2的幂显示的搭档的最大数目空闲块,可形成此树。
请注意,只有完全空闲的字才与其完全空闲的搭档组合。组合时,最右搭档变成-1,以指示它由另一项所表示。
块分配映射表的dmap控制页包含与dmap结构中树相似的树,除叶层包含1024个元素外。这些元素是树[0]为紧跟下面的1024个映射表页的二进制搭档表示法。对于L0页,它是接下来的1024个dmap页,对于L1页,它是接下来的1024个L0页,而对于L2页,它是接下来1024个L1页。
在块分配映射表的顶部,有映射表控制结构structdbmap_t。该结构包含摘要信息,能加快查找比平均空闲空间多的AG。可在jfs_dmap.h中找到该结构。
块分配映射表没有记日志:它能在恢复期间由logredo修复,或者由fsck重构。在fsck或logredo后工作和持续映射表,都必需是相同状态。
扩展聚集以增大文件系统
要扩展聚集,JFS必须确保有足够的页存储块分配映射表,索引聚集新扩展的块。通常,从现有的聚集分配空间给新增的页,但是如果该聚集空间已满,那就不可能了。所以我们需要解决这种特殊情况。
要解决该问题,通常JFS为块分配映射表分配的空间多于索引聚集地址空间所需的空间。每个映射表都有额外页空间用于存放位图,如果该页指向另一层摘要树,则该映射表就需额外页存放所需的摘要信息。这种额外空间使得JFS可以在必要时将聚集分为更小的单位,以扩大聚集至所需的大小。扩展聚集,需采取以下步骤:
如果现有聚集的空间足以扩展块分配映射表,使其能索引新聚集的所有块,那么,JFS不做任何特殊处理,将聚集扩展至整个空间。仅当需要考虑聚集将来的扩展时,块分配映射表才需增加额外页。
如果没有足够空间扩展,那么JFS仅给聚集扩展块分配映射表中已有额外页所能寻址的块。
至此,JFS有一些额外的聚集块未在聚集中使用到。JFS可以用这些聚集块扩大块分配映射表,以继续将聚集扩展至所需大小。JFS必须谨记将这些额外页放入块分配映射表中。
这个处理过程完全由vfs_cntl()处理,对系统的其它部分隐藏。
另一种表示法:二进制编码搭档表示法
块分配映射表也可以用二进制编码搭档系统表示。除了树的叶结点和dmap结构不同外,这种表示法的逻辑和物理结构与前一种一样。
structdmap定义块分配映射表的最下层。每个dmap页包括8K的聚集块。
以下为引用的内容:
/*
*dmapsummarytree
*
*dmaptree_tmustbeconsistentwithdmapctl_t.
*/
typedefstruct{
int32nleafs;/*4:numberoftreeleafs*/
int32l2nleafs;/*4:l2numberoftreeleafs*/
int32leafidx;/*4:indexoffirsttreeleaf*/
int32height;/*4:heightofthetree*/
int8budmin;/*1:minl2treeleafvaluetocombine*/
int8stree[TREESIZE];/*TREESIZE:tree*/
uint8pad[2];/*2:padtowordboundary*/
}dmaptree_t;/*-360-*/
/*
*dmappageper8Kblocksbitmap
*/
typedefstruct{
int32nblocks;/*4:numblkscoveredbythisdmap*/
int32nfree;/*4:numoffreeblksinthisdmap*/
int64start;/*8:startingblknoforthisdmap*/
dmaptree_ttree;/*360:dmaptree*/
uint8pad[1672];/*1672:padto2048bytes*/
uint32wmap[LPERDMAP];/*1024:bitsoftheworkingmap*/
uint32pmap[LPERDMAP];/*1024:bitsofthepersistentmap*/
}dmap_t;/*-4096-*/
二进制编码搭档系统的每一项都有三个字段:type,size和bitmap。type字段表示块空闲、已分配、用位图表示或不由该字段表示(don'tcare)。如果类型是"don'tcare"则这些块由左搭档表示,size字段忽略。如果type是位图,则位图字段的32位和32块一一对应,表示其空闲或已分配。位值0表示空闲块,1表示块已分配。size是2的幂次方,表示该项描述的聚集块的个数。