MIT 6.828 Homework: biggers files for xv6
任务概述
在这个作业中,需要增加 xv6 系统允许的文件大小。当前的 xv6 文件大小被限制为 140 扇区 (sectors),因为 xv6 的索引节点 (innode) 包含了 12 个 “直接的” 块 (block) 的序号和一个 “单独间接 (singly-indirect)” 块序号,这个序号指向一个最多可以存储 128 个块号的块。为了增加允许的文件大小,需要修改 xv6 代码在每个索引节点中支持 “双间接 (doubly-indirect)” 块,包含 128 个单间接块的地址,每个块又包含最多 128 个数据块的地址。最终一个文件将会能够包含 11 + 128 + 128 * 128 = 16523 个扇区。
准备工作
- 修改 Makefile,将 CPUS 设置为:
CPUS := 1
- 在 QEMUOPTS 前添加:
QEMUEXTRA = -snapshot
上述两个步骤会极大的增加 xv6 创建大文件的速度。
- 修改
param.h
将 FSSIZE 设置为:
#define FSSIZE 20000 // size of file system in blocks
将 big.c
添加到 xv6 目录下,将它添加到 UPROGS 列表中,启动 xv6,执行 big 命令,将会在 xv6 中创建一个 xv6 允许情况下最大的文件并报告大小,运行结果应该是 140 sectors。
big.c
:
#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"
int
main()
{
char buf[512];
int fd, i, sectors;
fd = open("big.file", O_CREATE | O_WRONLY);
if(fd < 0){
printf(2, "big: cannot open big.file for writing\n");
exit();
}
sectors = 0;
while(1){
*(int*)buf = sectors;
int cc = write(fd, buf, sizeof(buf));
if(cc <= 0)
break;
sectors++;
if (sectors % 100 == 0)
printf(2, ".");
}
printf(1, "\nwrote %d sectors\n", sectors);
close(fd);
fd = open("big.file", O_RDONLY);
if(fd < 0){
printf(2, "big: cannot re-open big.file for reading\n");
exit();
}
for(i = 0; i < sectors; i++){
int cc = read(fd, buf, sizeof(buf));
if(cc <= 0){
printf(2, "big: read error at sector %d\n", i);
exit();
}
if(*(int*)buf != i){
printf(2, "big: read the wrong data (%d) for sector %d\n",
*(int*)buf, i);
exit();
}
}
printf(1, "done; ok\n");
exit();
}
运行 big 命令结果如下:
$ big
.
wrote 140 sectors
done; ok
一些说明
- innode 定义在
fs.h
的 struct dinnode 中,关注其中的 NDIRECT, NINDIRECT, MAXFILE, addrs[]。 - 在磁盘上查找文件数据的代码在
fs.c
的 bmap() 中,在读取和写入文件时,bmap() 都会被调用。 - bmap() 处理两种块序号,bn 是 “逻辑块号 (logic numbers)”,一个与文件开头部分相关的块号,在 ip->addrs[] 中的块号是 “磁盘块号 (disk block numbers)”
任务要求
修改 bmap(),使它除了实现单间接块和直接块之外还实现了双间接块。单间接块的数目将会由 12 变为 11,多出的一个块将会成为双间接块。ip->addrs[] 的起始 11 个元素应该是直接块,第 12 个元素应该是单间接块,第 13 个元素应该为新的双间接块。
任务实现
- 修改
fs.h
struct dinnode 结构体。
#define NDIRECT 11
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT * 129)
// On-disk inode structure
struct dinode {
short type; // File type
short major; // Major device number (T_DEV only)
short minor; // Minor device number (T_DEV only)
short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes)
uint addrs[NDIRECT+2]; // Data block addresses
};
- 修改
file.h
struct innode 结构体。
// in-memory copy of an inode
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
struct sleeplock lock; // protects everything below here
int valid; // inode has been read from disk?
short type; // copy of disk inode
short major;
short minor;
short nlink;
uint size;
uint addrs[NDIRECT+2];
};
- 修改
fs.c
的 bamp() 函数。
static uint
bmap(struct inode *ip, uint bn)
{
uint addr, *a;
struct buf *bp,*dp;
if(bn < NDIRECT){
if((addr = ip->addrs[bn]) == 0)
ip->addrs[bn] = addr = balloc(ip->dev);
return addr;
}
bn -= NDIRECT;
if(bn < NINDIRECT){
// Load indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT]) == 0)
ip->addrs[NDIRECT] = addr = balloc(ip->dev);//Allocate a zeroed disk block.
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn]) == 0){
a[bn] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}
bn -= NINDIRECT;
if(bn < MAXFILE-NINDIRECT-NDIRECT){
// Load indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT+1]) == 0)
ip->addrs[NDIRECT+1] = addr = balloc(ip->dev);//Allocate a zeroed disk block.
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn/NINDIRECT]) == 0){
a[bn/NINDIRECT] = addr = balloc(ip->dev);
log_write(bp);
}
dp=bread(ip->dev, addr);
a = (uint*)dp->data;
if((addr = a[bn%NINDIRECT]) == 0){
a[bn%NINDIRECT] = addr = balloc(ip->dev);
log_write(dp);
}
brelse(dp);
brelse(bp);
return addr;
}
panic("bmap: out of range");
}
对 xv6 的源代码修改完成
测试结果:
$ big
.....................................................................................................................................................................
wrote 16523 sectors
done; ok