lab9 文件系统 文件系统API
inode满足以下两种条件时可以删除文件
link count == 0
open fd count == 0
Bcache
文件崩溃的安全性:系统崩溃或断电
解决方案:日志系统
使系统调用是原子
性的,例如是否发生了open
快速修复
高性能
日志系统行为(即事务
)
FILE SYSTEM ext3 write-ahead rule
: 预先声明更新在将更新写入磁盘前
freeing rule
:我们不能在写入磁盘前覆盖重用日志
log super block:保存第一个事务的偏移
…
describe block:块编号
log block:日志
commit block:提交块
….
异步ASYNC
优势
I/O CONCURRENCY:允许计算和文件写入并行
HELP BATCHING:为批处理提供支持
劣势
unix提供fsync()强制写入
避免异步写入导致的数据丢失
批处理BATCHING
one “OPEN” action:降低磁盘寻道时间等访问磁盘的开销
WRITE ABSORBTION:在内存上将多个inode写入一个块显然比一次次在磁盘写入快
DISK SCHEDUING:允许对磁盘访问进行排序,加快磁盘(特别是机械硬盘)的访问速度
并发CONCURRENCE
SYS CALLS IN PARALLEL:系统调用可以修改事务
MANY OLDER XACTIONS
ONE OPEN
COMMITING TO LOG
WRITING TO HEOME
FREED
Journaled Data 侧重于通过记录操作日志来保护数据不受系统故障的影响。
Ordered Data 侧重于数据的逻辑顺序,这有助于提高数据处理效率和保证数据的一致性。
Large files(moderate) 在fs.h修改文件
块组合为:11+512+512*512
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #define NDIRECT 11 #define NINDIRECT (BSIZE / sizeof(uint)) #define NINDIRECT2 (NINDIRECT * NINDIRECT) #define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT2) struct dinode { short type; short major; short minor; short nlink; uint size; uint addrs[NDIRECT+2 ]; };
同时修改file.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 struct inode { uint dev; uint inum; int ref; struct sleeplock lock; int valid; short type; short major; short minor; short nlink; uint size; uint addrs[NDIRECT+2 ]; };
取bn的索引和偏移,像页表那样,只为分配的inode分配块
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 static uintbmap (struct inode *ip, uint bn) { uint addr, *a; struct buf *bp; uint idx, offset; .... bn-= NINDIRECT; if (bn < NINDIRECT2){ idx = bn / NINDIRECT; offset = bn % 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 ((addr = a[idx]) == 0 ){ a[idx] = 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" ); }
释放掉所有子块后才释放上一级块。
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 void itrunc (struct inode *ip) { int i, j; struct buf *bp, *bp1; uint *a, *a1; .... if (ip->addrs[NDIRECT+1 ]){ bp = bread (ip->dev, ip->addrs[NDIRECT+1 ]); a = (uint*)bp->data; for (j = 0 ; j < NINDIRECT; j++){ if (a[j]){ bp1 = bread (ip->dev, a[j]); a1 = (uint*)bp1->data; for (i = 0 ; i < NINDIRECT; i++) { if (a1[i]) { bfree (ip->dev, a1[i]); } } brelse (bp1); } } brelse (bp); bfree (ip->dev, ip->addrs[NDIRECT+1 ]); ip->addrs[NDIRECT+1 ] = 0 ; } ip->size = 0 ; iupdate (ip); }
Symbolic links(moderate) 系统调用添加过程这里就不赘述了
1 2 3 4 5 #define O_NOFOLLOW 0x800 #define T_SYMLINK 4
在sysfile文件添加sys_symlink(),创建文件并写入T_SYMLINK 标志和指向的文件路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int64 sys_symlink (void ) { char target[MAXPATH], path[MAXPATH]; struct inode *dp; if (argstr (0 , target, MAXPATH) < 0 || argstr (1 , path, MAXPATH) < 0 ) return -1 ; begin_op (); if ((dp = create (path, T_SYMLINK, 0 , 0 )) == 0 ) { end_op (); return -1 ; } if (writei (dp, 0 , (uint64)target, 0 , MAXPATH) < MAXPATH) { iunlockput (dp); end_op (); return -1 ; } iunlockput (dp); end_op (); return 0 ; }
当文件类型为符号链接且O_NOFOLLOW未被设置访问指向的路径,同时当循环深度大于10时,返回错误,避免环状引用无法退出open。
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 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 && !(omode & O_NOFOLLOW)) { for (int i = 0 ; i < 10 ; ++i) { if (readi (ip, 0 , (uint64)path, 0 , MAXPATH) != MAXPATH) { iunlockput (ip); end_op (); return -1 ; } iunlockput (ip); ip = namei (path); if (ip == 0 ) { end_op (); return -1 ; } ilock (ip); if (ip->type != T_SYMLINK) break ; } if (ip->type == T_SYMLINK) { iunlockput (ip); end_op (); return -1 ; } } }