xv6 Lab: file system

Large files

在了解xv6在磁盘上的存储结构后

发现限制创建最大文件的原因就是 xv6目前有12个直接数据块和一个间接数据块

我们需要把一个直接数据块修改成二级间接数据块才能满足要求

要修改fs.h的结构体 fs.c中的bmap()函数

主要的细节在最初的bmap()中已经体现到了 照葫芦画瓢即可

要注意块号bn与连续的块的索引到底是什么关系

两层间接 怎样去访问 怎样分配新的data block

理解了这些 代码非常好写

我做这部分的时候是一气呵成的

但最后不要忘了修改一处 fs.h 的MAXFILE

否则去测试的时候跟没修改过的bmap()是一样的

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){
    // 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;
  }
  bn-=NINDIRECT;
  if(bn < NDOUIN){
    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[bn/NINDIRECT]) == 0){
      addr = a[bn/NINDIRECT] = balloc(ip->dev);
      log_write(bp);
    }
    brelse(bp);
    bp = bread(ip->dev, addr);
    a = (uint*)bp->data;
    if((addr = a[bn%NINDIRECT]) == 0){
      addr = a[bn%NINDIRECT] = balloc(ip->dev);
      log_write(bp);
    }
    brelse(bp);
    return addr;
  }

  panic("bmap: out of range");
}

itrunc()需要添加类似的代码 以释放block

void
itrunc(struct inode *ip)
{
  int i, j;
  struct buf *bp;
  uint *a;

  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(i=0;i<NINDIRECT;i++){
      if(a[i]){
        struct buf *bp2 = bread(ip->dev, a[i]);
        uint *b=(uint*)bp2->data;
        for(j = 0; j < NINDIRECT; j++){
            if(b[j])
              bfree(ip->dev, b[j]);
        }
        brelse(bp2);
        bfree(ip->dev,a[i]);
      }
    }
    brelse(bp);
    bfree(ip->dev, ip->addrs[NDIRECT+1]);
    ip->addrs[NDIRECT+1] = 0;
  }

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

Symbolic links

这一部分我认为是比较难的 如果要写的比较严谨 要考虑的地方还是很多的

但在测试的时候发现给的用例可能没有这么严谨

只要把基本逻辑写清楚即可

首先就是在xv6里添加系统调用 需要在各处添加的声明代码

一定要仔细阅读xv6book的file system部分 阅读关于file的代码

不仔细阅读会有很多的坑

里面关于事务 和 锁的部分值得去学习

比如创建新的inode的create()调用后会持有返回inode的锁

这时 如果你额外上锁就会造成死锁

个人认为hints里的要求和提示都有点模糊 事实上我添加些判断或者去掉确实不影响tests通过

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 0;
}

要求在open调用里添加关于符号链接的处理

额外写了一个递归查找符号链接所连接的原inode函数

struct inode * getip(char *path,int depth,int omode){
  if(depth > 10)
  {
    return 0;
  }
  struct inode *ip;
  ip=namei(path);
  if(ip==0)
  {
    return 0;
  }

  ilock(ip);

  if(!(omode & O_NOFOLLOW) && ip->type==T_SYMLINK)
  {
    char next[MAXPATH];
    if(readi(ip,0,(uint64)next,0,MAXPATH) == 0)
    {
      iunlockput(ip);
      return 0;
    }
    iunlockput(ip);
    return  getip(next, depth+1 ,omode);
  }
  iunlock(ip);
  return ip;
}

在open里修改

if(omode & O_CREATE){
    ip = create(path, T_FILE, 0, 0);
    if(ip == 0){
      end_op();
      return -1;
    }
  } else {
    if((ip=getip(path , 0 , omode )) == 0){
      end_op();
      return -1;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值