Large files

这个lab的任务是增加xv6文件的最大大小,目前一个Inode里有12个直接块号和1个间接块号,总共12 + 256 = 268个块,我们需要修改Inode(将一个直接块变为二级索引块)使得一个文件能够变得更大,具体的步骤是先修改fs.h中NDIRECT的定义,然后再去修改bmap使得操作系统能够访问到我们增加的块

具体实现

修改宏定义

1
2
3
4
5
// fs.h
#define NDIRECT 11
uint addrs[NDIRECT+2]; // Data block addresses
//file.h
uint addrs[NDIRECT+2];

修改bmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bn -= NINDIRECT;
if (bn < NINDIRECT * NINDIRECT)
{
if ((addr = ip->addrs[NDIRECT + 1]) == 0)
{
ip->addrs[NDIRECT + 1] = addr = balloc(ip->dev);
}
bp = bread(ip->dev, addr);
a = (uint *)bp->data;
if (a[bn / NINDIRECT] == 0)
{
a[bn / NINDIRECT] = balloc(ip->dev);
log_write(bp);
}
struct buf *bp2 = bread(ip->dev, a[bn / NINDIRECT]);
uint *a2 = (uint *)bp2->data;
if ((addr = a2[bn % NINDIRECT]) == 0)
{
a2[bn % NINDIRECT] = addr = balloc(ip->dev);
log_write(bp2);
}
brelse(bp2);
brelse(bp);
return addr;
}

在panic之前加上对二级索引块的分配和访问即可。

给xv6添加上符号链接,也就是软链接
这里我们先解释什么叫做链接,假设有一个文件路径path/a1,我们希望有另一个路径指向它,有一个path2/a2,这里我们就创建了一个链接,如果是硬链接,我们会在path2这个目录下放一个路径和它对应的索引块,但这个对应的索引块就直接是path/a1对应的索引块,并不会创建新的索引块,我们只需要把索引块的nlink+1,软链接则是我们创建一个新的索引块(文件),不过这个索引块(文件)里面不存放索引,而是存放path/a1这个路径,也就是说硬链接和软链接的区别主要是在于映射的不同,访问硬链接时主要是path->inode,软链接则是path->path->inode,值得一提的是软链接因为映射的是路径,所以它可以映射别的设备的文件,而不只是同一设备上的Inode。

下面来看具体实现

创建系统调用

1
2
3
4
5
6
entry("symlink"); //user/usys.pl
int symlink(const char*, const char*); //user/user.h
#define SYS_symlink 22 //kernel/syscall.h
extern uint64 sys_symlink(void); // kernel/syscall.c
uint64
sys_symlink(void){} //kernel/sysfile.c

读取参数之后,我们先查看我们要指向的path是否存在,不存在创建索引块,也就是创建文件即可,直接调用create,然后我们直接将target写进这个索引块即可,要提醒的是create返回的inode是已经锁定好的,我们不需要重复ilock,不然会造成死锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
uint64
sys_symlink(void)
{
char path[MAXPATH], target[MAXPATH];
struct inode *ip;
if (argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0)
{
return -1;
}
begin_op();
if ((ip = create(path, T_SYMLINK, 0, 0)) == 0)
{
end_op();
return -1;
}
if (writei(ip, 0, (uint64)target, 0, MAXPATH) < MAXPATH)
{
iunlockput(ip);
end_op();
return -1;
}
iunlockput(ip);
end_op();
return -1;
}

修改索引的访问

因为我们现在出现了存放路径的软连接索引块,所以也要修改索引块的读取,因此先修改stat.h,增加T_SYMLINK的定义

1
#define T_SYMLINK 4 // Symlink

修改open系统调用以能正确打开软链接的文件,如果一个ip的type是软链接,我们只需要递归一直打开即可,但是如果出现环路就会死循环,因此我们设置一个递归的最大深度,超过这个深度直接返回-1,如果有O_NOFOLLOW标记,我们就不开源文件,而是直接把当前索引文件给返回即可。