lab9 file system

lab9 file system

实验结果

我电脑性能不好,且安装的虚拟机性能也不太行。跑bigfile会timeout,网上查找可以通过修改gradelib.py来避免timeout,但我目的是验证我做的对不对,又不是让make grade通过,所以结果变成如下。

bigfile结果

Symbolic links结果

实验

large files

思路

上图就是inode的结果,理解上图就会做了。当然这是别的操作系统inode的结构,题目中block size是1024,inode直接块要求为11个,1个间接块,1个二级间接块。

代码

在./kernel/fs.h 中修改NDIRECT, 修改MAXFILE,修改dnidode。

#define NDIRECT 11
#define NINDIRECT (BSIZE / sizeof(uint))
#define DOUBLE_NINDIRECT ((NINDIRECT) * (NINDIRECT))
#define MAXFILE (NDIRECT + NINDIRECT + DOUBLE_NINDIRECT)

// On-disk inode structure
struct dinode {
  short type;           // File type
  short major;          // Major device number (T_DEVICE only)
  short minor;          // Minor device number (T_DEVICE only)
  short nlink;          // Number of links to inode in file system
  uint size;            // Size of file (bytes)
  uint addrs[NDIRECT+2];   // Data block addresses
};

在./kernel/file.h 中修改idode。

// in-memory copy of an inode
struct inode {
  uint dev;           // Device number
  uint inum;          // Inode number
  int ref;            // Reference count
  struct sleeplock lock; // protects everything below here
  int valid;          // inode has been read from disk?

  short type;         // copy of disk inode
  short major;
  short minor;
  short nlink;
  uint size;
  uint addrs[NDIRECT+2];
};

在./kernel/fs.c 中修改bmap和itrunc

static uint
bmap(struct inode *ip, uint bn)
{
  uint addr, *a, DoubleIndex;
  struct buf *bp;
  struct buf* bp2;

  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 = bn - NINDIRECT;

  if (bn < DOUBLE_NINDIRECT)
  {
    addr = ip->addrs[NDIRECT + 1];
    if (addr == 0)//没有一级索引块
    {
      addr = balloc(ip->dev);//balloc 不分配出block,在里面就会panic了,分配的块set 0
      ip->addrs[NDIRECT + 1] = addr;
    }

    bp = bread(ip->dev, addr);
    a = (uint*)bp->data;
    DoubleIndex = (uint)(bn / NINDIRECT);
    addr = a[DoubleIndex];
    if (addr == 0)//没有索引块
    {
      addr = balloc(ip->dev);
      a[DoubleIndex] = addr;
      log_write(bp);
    }
    bp2 = bread(ip->dev, addr);
    a = (uint*)bp2->data;
    DoubleIndex = bn - NINDIRECT * DoubleIndex;
    addr = a[DoubleIndex];
    if (addr == 0)//没有数据块
    {
      addr = balloc(ip->dev);
      a[DoubleIndex] = addr;
      log_write(bp2);
    }    
    brelse(bp2);
    brelse(bp);

    return addr;
  }


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

// Truncate inode (discard contents).
// Caller must hold ip->lock.
void
itrunc(struct inode *ip)
{
  int i, j;
  struct buf *bp, *bp2;
  uint *a, *b;
  uint addr;

  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++)//扫描一级索引块
    {
      addr = a[i];
      if (addr != 0)//有索引块
      {
        bp2 = bread(ip->dev, addr);
        for (j = 0; j < NINDIRECT; j++)//扫描索引块
        {
          b = (uint*)bp2->data;
          if (b[j] != 0)//有的话释放
          {
            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);
}

做该实验,要想清楚如下问题

1:一个pathname,例如/xxxx/ttt/ccc/abc,如果在里面存在软链接,那么只会是abc。因为在ccc时软链接,那么跳走别的文件(目录),目录文件中没有cc,你要怎么办,事实上会有个逻辑bug。

2:soft link保存在那里?比如soft在一个dirct中,我要从哪里去寻找soft link所指向的那个字符串呢?放在direct的结构体,那么假设14个文件都是soft link呢?而且namei,nameparent是给定一个path,返回一定的parent,我现在要返回一个字符串,与底层提供的接口都不符,难道我要重写很多接口??你会发现,direct也是一个inode,然后它的文件数据被存储到inode所对应block中。硬链接里,新产生的pathname还是指向原本的那个inode;软链接通过新产生的pathname,可以得到文件原本的pathname,但并没有说soft link的pathname不用inode,所以soft link的原文件的pathname存储到soft link的inode的data block中,而且如果soft link不是一个inode,“Other system calls (e.g., link and unlink) must not follow symbolic links; these system calls operate on the symbolic link itself.”这句话怎么解决,link unlink open write等我都要重新修改?而sfot link用inode就可以符合xv6的设计,为啥要自讨苦吃

3:对错误情况的处理。target只要存在,不管怎么样的形式,都可以保存在data block中,而path,例如出现aas/sss/的情况要怎么处理?xv6 对于path name的处理主要用namei,nameparent这两个api,观察namex函数。知道如果nameparent为0,输入/as/ae,返回的是ae所对应的inode,输入/as/ae/,返回的也是ae说对应的inode

4:systemlink输入的path是包括了文件名还是放在哪个path下呢?还是两种情况都要考虑,我觉得是放在哪个现实下的应该不靠谱,参考linux 命令ln

5: 如果该文件已存在,是要修改file data还是返回-1,选择返回-1吧,偷偷修改可能会产生很严重的bug

问题

首先确定哪里出现问题ilock, no type。

就是在ilock中ip-type等于0才会导致,但是我记得ialloc中已经对inode的type赋值了?

// Allocate an inode on device dev.
// Mark it as allocated by  giving it type type.
// Returns an unlocked but allocated and referenced inode.
struct inode*
ialloc(uint dev, short type)
{
  int inum;
  struct buf *bp;
  struct dinode *dip;

  for(inum = 1; inum < sb.ninodes; inum++){
    bp = bread(dev, IBLOCK(inum, sb));
    dip = (struct dinode*)bp->data + inum%IPB;
    if(dip->type == 0){  // a free inode
      memset(dip, 0, sizeof(*dip));
      dip->type = type;
      log_write(bp);   // mark it allocated on the disk
      brelse(bp);
      return iget(dev, inum);
    }
    brelse(bp);
  }
  panic("ialloc: no inodes");
}

观察ialloc函数,是有个dip->type赋值type,为啥没有呢?因为最初是观察create制造一个inode,
发现create函数中,ialloc后,是有对 major,minor,nlink这3个属性赋值的,major,minor看create可能是0,而且似乎跟device文件有关,先不管。
nlink特别重要,要是nlink0,ref0,那么这个inode就是存储文件,也没程序正在使用了,所以nlink应该赋值**,查看iget中,也没对nlink进行操作,于是参考cretae, nlink=1,iupdate,成功解决。

xv6文件系统相关知识后面再叙述吧!

posted @ 2025-02-05 22:18  我们的歌谣  阅读(15)  评论(0)    收藏  举报