在这部分的任务中你负责扩大系统中文件的大小上限。xv6 中的文件目前最大为 268 块,即至多 $268*\text{BSIZE}$ 字节(xv6 中,BSIZE
等于 1024)。这是由于在 xv6 中一个 inode
中包含 12 个直接块指针(直接指明存放数据的物理块的序号)以及 1 个一级间接块指针(指向一个存放了 256 个块指针的物理块),共 $12+256=268$ 个块。
本题的测试程序 bigfile
会尽其可能地创建最大的文件并汇报该文件的大小:
$ bigfile
..
wrote 268 blocks
bigfile: file is too small
如上,测试失败的原因是 bigfile
的通过条件为系统允许的最大文件大小为 65803 个块,而原版的 xv6 仅支持最大为 268 个块的文件。
因此,你需要修改 xv6 以使其支持“二级间接”块指针,这个指针应指向一个存放了 256 个指向一级间接块的指针的物理块,则一个这样的“二级间接块”指针即可寻址 $256\times256$ 个物理块。修改完成后,一个文件的最大大小应为 65803 个块,即 $256\times256+256+11$ 个块(这里直接块指针数为 11 而非12 是因为我们将直接块指针的位置分一个给二级间接块指针而不改变 addrs[]
数组的大小)。
在系统中,mkfs
程序为 xv6 文件系统准备硬盘映像并决定文件系统包含的总块数,这个值由 kernel/param.h
中的 FSSIZE
指定。在本实验中该值被设置为 200000 块。你将在 make
的输出中看到以下内容:
nmeta 70 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 25) blocks 199930 total 200000
这行输出描述了 mkfs/mkfs
所创建的文件系统:它包含了 70 个元数据块(用于描述文件系统的属性)以及 199930 个数据块,共 200000 块。如果在完成本实验的过程中你有重置文件系统的需要,可以通过 make clean
指令满足。该指令会重建 fs.img
以重置文件系统。
磁盘索引节点(用于在磁盘上存储索引节点 inode
的数据结构)的定义位于 fs.h
中,由 struct dinode
所定义。你也许会对其中的 NDIRECT
, NINDIRECT
, MAXFILE
以及 dinode
结构体中的 addrs[]
字段比较感兴趣。此外,xv6 参考书中的图 8.3 描绘了标准的 xv6 索引节点的结构。
xv6 中用于索引文件内容的函数为 fs.c
中的 bmap()
函数,建议你阅读一遍它的代码以理解它在干什么。xv6 中读取文件以及修改文件都需要调用这个函数。修改文件时,bmap()
负责为文件分配所需的新块,必要时也负责为文件分配间接指针块以存放块指针。
bmap()
负责与两种块序号打交道,其中它的参数 bn
是指逻辑块序号——即数据块相对于文件开头的序号;而存放于 ip->addrs
中的块序号,以及作为 bread()
参数的块序号,则是硬盘(物理)块序号。你可以将 bmap()
视作将逻辑块序号映射至物理块序号的函数。
<aside>
在现有的直接块指针以及一级间接块指针的基础上修改 bmap()
的实现以支持二级间接块功能。这样做会导致直接块指针的数量变为 11 个(而非原先的 12 个)来为你的二级间接块指针腾出位置(你不能更改磁盘索引节点的大小)。ip->addrs[]
中的前 11 个元素应直接指向物理块,第 12 个元素指向一级间接块,最后的元素指向你所实现的二级间接块。当 bigfile
得以成功创建大小为 65803 块的文件且 usertests
测试顺利通过时你的任务才全部完成,其输出应如(第二行应为 658 个“.”):
</aside>
$ bigfile
..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
wrote 65803 blocks
done; ok
$ usertests
...
ALL TESTS PASSED
$