lab-fs
Large files
修改fs.h
中关于直接块间接块的定义,前11
块为直接快,第12
块为一级间接块,第13
块为二级间接块。
1 2 3 4
| #define NDIRECT 11 #define NINDIRECT (BSIZE / sizeof(uint)) #define NDUBINDIRECT (BSIZE / sizeof(uint)) * (BSIZE / sizeof(uint)) #define MAXFILE (NDIRECT + NINDIRECT + NDUBINDIRECT)
|
当要访问的bn(block number)
大于NDIRECT + NINDIRECT
时,访问二级间接块,仿照一级间接块的查询方式即可,注意需要查询两级地址。
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 50 51 52 53
| static uint bmap(struct inode *ip, uint bn) { uint addr, *a; struct buf *bp;
if(bn < NDIRECT){ if((addr = ip->addrs[bn]) == 0) ip->addrs[bn] = addr = balloc(ip->dev); return addr; } bn -= NDIRECT;
if(bn < NINDIRECT) { if((addr = ip->addrs[NDIRECT]) == 0) ip->addrs[NDIRECT] = addr = balloc(ip->dev); 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 < NDUBINDIRECT) { if((addr = ip->addrs[NDIRECT + 1]) == 0) { ip->addrs[NDIRECT + 1] = addr = balloc(ip->dev); } uint indirect_index = bn / (NINDIRECT); uint offset = bn % NINDIRECT; bp = bread(ip->dev, addr); a = (uint*)bp->data; if((addr = a[indirect_index]) == 0) { a[indirect_index] = addr = balloc(ip->dev); log_write(bp); } brelse(bp);
bp = bread(ip->dev,addr); a = (uint*)bp->data; if((addr = a[offset]) == 0) { a[offset] = addr = balloc(ip->dev); log_write(bp); } brelse(bp); return addr; } panic("bmap: out of range"); }
|
确保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; struct buf *indirect_bp; uint *a; uint *b; int indirect_index,offset; 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 < NINDIRECT; 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(indirect_index = 0; indirect_index < NINDIRECT; indirect_index++) { if(a[indirect_index]) { indirect_bp = bread(ip->dev,a[indirect_index]); b = (uint*)indirect_bp->data; for(offset = 0; offset < NINDIRECT; offset++) { if(b[offset]) { bfree(ip->dev,b[offset]); } } brelse(indirect_bp); bfree(ip->dev,a[indirect_index]); } } brelse(bp); } ip->size = 0; iupdate(ip); }
|
Symbolic links
在stat.h
内定义 T_SYMLINK
类型。
在fcntl.h
定于新标志O_NOFOLLOW
。
1
| #define O_NOFOLLOW 0x1000
|
仿照其他文件系统调用,实现sys_symlink
。在新创建的inode
的数据块中保存目标路径target
字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| uint64 sys_symlink(void) { char taget[MAXPATH], path[MAXPATH]; struct inode *ip; begin_op(); if(argstr(0, taget, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0) return -1; if ((ip = create(path, T_SYMLINK, 0, 0)) == 0) { end_op(); return -1; } if(writei(ip,0,(uint64)taget,0,MAXPATH) < MAXPATH) { end_op(); return -1; } iunlockput(ip); end_op(); return 0; }
|
修改sys_open
。当打开文件类型为T_SYMLINK
时,首先判断是否指定标志O_NOFOLLOW
,如果制定了,则按照打开其他类型文件一样处理。否则需要不断递归查询真实文件路径。
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
| uint64 sys_open(void) { ... if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){ iunlockput(ip); end_op(); return -1; }
if(ip->type == T_SYMLINK) { if(!(omode & O_NOFOLLOW)) { int cnt = 0; char target[MAXPATH]; while(ip->type == T_SYMLINK) { if(cnt >= 10) { iunlockput(ip); end_op(); return -1; } cnt++; readi(ip,0,(uint64)target,0,MAXPATH); iunlockput(ip); if((ip = namei(target)) == 0) { end_op(); return -1; } ilock(ip); } } } ... }
|