MIT Operating Systems Lab: file system


Large files

your job:
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 runs successfully:


//fs.h
#define NDIRECT 11
#define DNDIRECT 12
#define NINDIRECT (BSIZE / sizeof(uint))
#define DNINDIRECT (NINDIRECT * NINDIRECT)
#define MAXFILE (NDIRECT + NINDIRECT + DNINDIRECT)

struct dinode {
  /* ....
   * ....
   */
  uint addrs[DNDIRECT+1];   // Data block addresses
};

// bmap of fs.c 
bmap(struct inode *ip, uint bn)
{
/* ...
 * ...
 */
  bn -= NINDIRECT;
  if(bn < DNINDIRECT){
    if((addr = ip->addrs[DNDIRECT]) == 0)
      ip->addrs[DNDIRECT] = addr = balloc(ip->dev);
    for(int i = 0; i < 2; i++){
      bp = bread(ip->dev, addr);
      a = (uint*)bp->data;
      int num = (i == 0 ? bn / NINDIRECT : bn % NINDIRECT);
      if((addr = a[num]) == 0){
        a[num] = addr = balloc(ip->dev);
        log_write(bp);
      }
      brelse(bp);
    }
    return addr;
  }

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

// itrunc of fs.c
void
itrunc(struct inode *ip)
{
  int i, j;
  struct buf *bp, *bp1;
  uint *a, *a1;
  /* ...
   * ...
   */

  if(ip->addrs[DNDIRECT]){
    bp = bread(ip->dev, ip->addrs[DNDIRECT]);
    a = (uint*)bp->data;
    for(j = 0; j < NINDIRECT; j++){
      if(!a[j])
        continue;
      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);
      bfree(ip->dev, a[j]);
    }
    brelse(bp);
    bfree(ip->dev, ip->addrs[DNDIRECT]);
    ip->addrs[DNDIRECT] = 0;
  }

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

Symbolic links

your job:
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).


system call, modify system call in user/user.h and user/usys.pl:

// symlink for system call in sysfile.c
uint64
sys_symlink(void)
{
  char new[MAXPATH], target[MAXPATH];
  struct inode *tp;

  if(argstr(0, target, MAXPATH) == -1 || argstr(1, new, MAXPATH) == -1)
    return -1;
  
  begin_op();

  if((tp = namei(new)) != 0){
      iput(tp);
      end_op();
      return -1;
  }

  if((tp = create(new, T_SYMLINK, 0, 0)) == 0){
    end_op();
    return -1;
  }

  if(writei(tp, 0, (uint64)target, 0, MAXPATH) < 0){
    iunlockput(tp);
    end_op();
    return -1;
  }

  iunlockput(tp);
  end_op();

  return 0;
}

open symbolic link file:

// sys_open in sysfile.c
struct inode * looksymlink(struct inode *);
int maxtime = 0;
uint64
sys_open(void)
{
  char path[MAXPATH];
  int fd, omode;
  struct file *f;
  struct inode *ip, *tp;
  int n;

  if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)
    return -1;

  if(omode & O_NOFOLLOW){
    if(omode & ~(O_NOFOLLOW | O_RDONLY))
      return -1;
  }

  begin_op();

  if(omode & O_CREATE){
    ip = create(path, T_FILE, 0, 0);
    if(ip == 0){
      end_op();
      return -1;
    }
  } else {
    if((ip = namei(path)) == 0){
      end_op();
      return -1;
    }
    ilock(ip);
    if(ip->type == T_DIR && omode != O_RDONLY){
      iunlockput(ip);
      end_op();
      return -1;
    }
    if(ip->type == T_SYMLINK && omode != (O_RDONLY | O_NOFOLLOW)){
      tp = looksymlink(ip);
      if(tp){
        ilock(tp);
        ip = tp;
      } else {
        end_op();
        return -1;
      }
    }
  }
  /* ...
   * ...
   */
  maxtime = 0;
  return fd;
}

// Caller must hold ip->lock.
struct inode *looksymlink(struct inode * ip){
  char path[MAXPATH];
  struct inode *tp, *dp;
  if(maxtime > 10){
    return 0;
  }
  if(ip->type == T_SYMLINK){
    maxtime++;
    if(readi(ip, 0, (uint64)path, 0, MAXPATH) == 0){
      return 0;
    }
    if((tp = namei(path)) == 0 || tp == ip){
      iunlockput(ip);
      return 0;
    }
    ilock(tp);
    iunlockput(ip);
    dp = looksymlink(tp);
    return dp;
  } else if(ip->type == T_FILE){
    iunlock(ip);
    return ip;
  }
  return 0;
}

static struct inode*
create(char *path, short type, short major, short minor)
{
  /* ...
   * ...
   */

  if((ip = dirlookup(dp, name, 0)) != 0){
    iunlockput(dp);
    ilock(ip);
    if((type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE)) || (type == T_SYMLINK && ip->type == T_SYMLINK))
      return ip;
    iunlockput(ip);
    return 0;
  }
  /* ...
   * ...
   */
  return ip;
}

#define T_SYMLINK 4 in file stat.h and #define O_NOFOLLOW 0x010 in fcntl.h


总结

honestly, this lab is simple, nothing to summary.

Please find complete code here github

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值