警告
本文最后更新于 2023-06-22,文中内容可能已过时。
MIT 6.1810 中第九个 lab 的 solution
Modify bmap() so that it implements a doubly-indirect block, in addition to direct blocks and a singly-indirect block. You’ll have to have only 11 direct blocks, rather than 12, to make room for your new doubly-indirect block; you’re not allowed to change the size of an on-disk inode. The first 11 elements of ip->addrs[] should be direct blocks; the 12th should be a singly-indirect block (just like the current one); the 13th should be your new doubly-indirect block. You are done with this exercise when bigfile writes 65803 blocks and usertests -q runs successfully:
在kernel/fs.h文件中添加以下宏定义,并修改struct dinode
结构体:
1
2
3
4
5
6
7
8
| #define NDIRECT 11
#define INDIRECT_ONLY (BSIZE / sizeof(uint))
#define NIDIRECT_DOUBLE (BSIZE / sizeof(uint)) * (BSIZE / sizeof(uint))
#define NINDIRECT (INDIRECT_ONLY + NIDIRECT_DOUBLE)
...
uint addrs[NDIRECT+2]; // Data block addresses
|
将kernel/file.h中的struct inode
结构体保持和struct dinode
同步:
接下来都是在kernel/fs.c文件中修改:
将bn < NINDIRECT
改成bn < INDIRECT_ONLY
在这个判断下边加上:
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
26
27
28
29
30
31
32
33
| bn -= INDIRECT_ONLY;
if(bn < NIDIRECT_DOUBLE){
if((addr = ip->addrs[NDIRECT+1]) == 0){
addr = balloc(ip->dev);
if(addr == 0)
return 0;
ip->addrs[NDIRECT+1] = addr;
}
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn / INDIRECT_ONLY]) == 0){
addr = balloc(ip->dev);
if(addr){
a[bn / INDIRECT_ONLY] = addr;
log_write(bp);
}
}
brelse(bp);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn % INDIRECT_ONLY]) == 0){
addr = balloc(ip->dev);
if(addr){
a[bn % INDIRECT_ONLY] = addr;
log_write(bp);
}
}
brelse(bp);
return addr;
}
|
将itrunc()
函数修改成:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| void
itrunc(struct inode *ip)
{
int i, j;
struct buf *bp, *sbp;
uint *a, *b;
for(i = 0; i < NDIRECT; i++){
if(ip->addrs[i]){
bfree(ip->dev, ip->addrs[i]);
ip->addrs[i] = 0;
}
}
if(ip->addrs[NDIRECT]){
bp = bread(ip->dev, ip->addrs[NDIRECT]);
a = (uint*)bp->data;
for(j = 0; j < INDIRECT_ONLY; j++){
if(a[j])
bfree(ip->dev, a[j]);
}
brelse(bp);
bfree(ip->dev, ip->addrs[NDIRECT]);
ip->addrs[NDIRECT] = 0;
}
if(ip->addrs[NDIRECT+1]){
bp = bread(ip->dev, ip->addrs[NDIRECT+1]);
a = (uint*)bp->data;
for(j = 0; j < INDIRECT_ONLY; j++){
if(a[j]){
sbp = bread(ip->dev, a[j]);
b = (uint*)sbp->data;
for(i = 0; i < INDIRECT_ONLY; i++){
if(b[i])
bfree(ip->dev, b[i]);
}
brelse(sbp);
bfree(ip->dev, a[j]);
}
}
brelse(bp);
bfree(ip->dev, ip->addrs[NDIRECT+1]);
ip->addrs[NDIRECT+1] = 0;
}
ip->size = 0;
iupdate(ip);
}
|
You will implement the symlink(char *target, char *path) system call, which creates a new symbolic link at path that refers to file named by target. For further information, see the man page symlink. To test, add symlinktest to the Makefile and run it. Your solution is complete when the tests produce the following output (including usertests succeeding).
在kernel/fnctl.h文件中添加:
1
| #define O_NOFOLLOW 0x800
|
在kernel/stat.h文件中添加:
在kernel/sysfile.c中修改sys_open()
函数,在其一开始判断是否要创建文件的那个判断之后加上:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| if(ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)){
char spath[MAXPATH];
for(int i = 0; ip->type == T_SYMLINK; i++){
if(i > 9){
iunlockput(ip);
end_op();
return -1;
}
readi(ip, 0, (uint64)spath, 0, sizeof(spath));
iunlockput(ip);
ip = namei(spath);
if(!ip){
end_op();
return -1;
}
ilock(ip);
}
}
|
并在文件后添加:
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
26
27
28
29
30
| uint64
sys_symlink(void)
{
char target[MAXPATH], path[MAXPATH];
struct inode *dip = 0;
if(argstr(0, target, MAXPATH) < 0)
return -1;
if(argstr(1, path, MAXPATH) < 0)
return -1;
begin_op();
if((dip == namei((char *)path)) == 0){
end_op();
return -1;
}
dip = create(path, T_SYMLINK, 0, 0);
if(writei(dip, 0, (uint64)target, 0, strlen(target)) != strlen(target)){
end_op();
return -1;
}
iunlockput(dip);
end_op();
return 0;
}
|