lab 9:Fs(file system)

lab 9:Fs(file system)

实验准备

通读第八章以及观看教学视频,理解目录与文件的组织方式,思考与阅读源码的实现方式。总的来说,本次作业难度不大,主要是对文件系统抽象的理解。

Large files

题目大意

为xv6实现一个二级间接数据块,使得文件大小为65803(原来为256+12),为此需要修改bmap和itrunc。

题目解答

这里由于有一个一级间接数据块可以参考,这里需要注意的是,bread对应一个brelse。同时,读完一个数据块需要释放,不能嵌套读取数据块。具体实现比较简单,注意一下细节即可。

static uint
bmap(struct inode *ip, uint bn)
{
  uint addr, *a;
  struct buf *bp;
// begin of DIRECT BLOCKS
  if(bn < NDIRECT){
    if((addr = ip->addrs[bn]) == 0)
      ip->addrs[bn] = addr = balloc(ip->dev);
    return addr;
  }
  // end of DIRECT BLOCKS
  bn -= NDIRECT;

  if(bn < NINDIRECT){
    // Load indirect block, allocating if necessary.
    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;
  }
  //panic("cannot reach!");
  bn-=NINDIRECT;
  uint b = bn/NINDIRECT;
  bn = bn-b*NINDIRECT;
  if(b < 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[b]) == 0){
		a[b] = addr = balloc(ip->dev);
		log_write(bp);
	}
	brelse(bp);	
	
	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;
  }

  panic("bmap: out of range");
}
void
itrunc(struct inode *ip)
{
  int i, j;
  struct buf *bp, *pt;
  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 < 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(j=0;j<NINDIRECT;j++){
		  pt = bread(ip->dev,a[j]);
		  b = (uint*)pt->data;
		  for(i=0;i<NINDIRECT;i++){
			  if(b[i])
				bfree(ip->dev,b[i]);
		  }
		  brelse(pt);
		  bfree(ip->dev,a[j]);
		  a[j] = 0;
	  }
	  brelse(bp);
	  bfree(ip->dev, ip->addrs[NDIRECT+1]);
	  ip->addrs[NDIRECT+1] = 0;
  }

  ip->size = 0;
  iupdate(ip);
}

Symbolic links

题目大意

在xv6中实现软链接,需要留意软链接的含义,首先软链接是一种文件类似于普通文件和目录文件,为此需要涉及创建这类文件和打开此类文件的实现。

题目答案

类比硬链接文件,如link,首先进行参数获取,然后是文件创建,文件写入,最后保存退出。重点是如何打开此类文件,这里需要在open函数里面稍作修改,使得能够处理这类文件,这里对于这类文件,实现了一种follow_do的处理函数,用于跟随软链接的目标路径,具体实现如下:

uint64
sys_symlink(void){
    char  target[MAXPATH], path[MAXPATH];
    struct inode *ip;
    int n =  argstr(0, target, MAXPATH);
    if(n<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, n)!=n){
        iunlockput(ip);
        end_op();
        return -1;
    }
    iunlockput(ip);
    end_op();
    return 0;
}        

这里需要注意follow_do如果正确返回的是加锁的ip,不正确的话,返回的是解锁的ip,为此这里不需要继续解锁否则出现解锁panic

    if((omode & O_NOFOLLOW) == 0&&(ip->type == T_SYMLINK)){
        if((ip = follow_do(ip))==0){                       
            //printf("cannot reach here!\n");
            //iunlockput(ip);
            end_op();
            return -1; 
        }   

struct inode*
follow_do(struct inode* ip)
{	
	static int depth =0;
	//To see the depth
	if(depth>10){
		depth = 0;
        iunlockput(ip);
		return 0;
	}
	char ps[MAXPATH];
	//Deal with symbolic files to get target path
	if(ip->type == T_SYMLINK){
		if(readi(ip, 0, (uint64)ps,0,  sizeof(ps))<=0){
			iunlockput(ip);
			return 0;
		}
		iunlockput(ip);
		if((ip = namei(ps))==0){
			//printf("follow_do: namei error!\n");
			return 0;
		}
		ilock(ip);
		depth++;
		return follow_do(ip);
	}
	else{
		depth = 0;
		return ip;
	}
}

测试结果

在主目录下面编写time.txt,然后make grade,进行评分测试

== Test running bigfile == 
$ make qemu-gdb
running bigfile: OK (98.3s) 
== Test running symlinktest == 
$ make qemu-gdb
(0.5s) 
== Test   symlinktest: symlinks == 
  symlinktest: symlinks: OK 
== Test   symlinktest: concurrent symlinks == 
  symlinktest: concurrent symlinks: OK 
== Test usertests == 
$ make qemu-gdb
usertests: OK (160.8s) 
== Test time == 
time: OK 
Score: 100/100
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值