code:ialloc - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki

Table of Contents

Source

  • 分配一个空闲的INODE结构,并返回指向该INODE的指针
    • 该INODE 由 7078 iget 置锁
  • 若已无空闲INODE可分配,则再搜索100个空闲的INODE
  • 传入一个参数 dev,为指定设备的设备号

7055

7056 /*

7057  * Allocate an unused I node

7058  * on the specified device.

7059  * Used with file creation.

7060  * The algorithm keeps up to

7061  * 100 spare I node in the

7062  * super block. When this runs out,

7063  * a linear search through the

7064  * I list is instituted to pick

7065  * up 100 more.

7066  */

7067 ialloc(dev)

7068 {

7069     register *fp, *bp, *ip;

7070     int i, j, k, ino;

7071

7072     fp = getfs(dev);

7073     while(fp->s_ilock)

7074          sleep(&fp->s_ilock, PINDO);

  • 获取该设备的超级块
  • 若该设备的INODE 队列被锁,在s_ilock上以优先级PINDO睡眠,参看睡眠原因
7075 loop:

7076     if(fp->s_ninode > 0) {

  • 若INODE 队列不为空
7077          ino = fp->s_inode[--fp->s_ninode];

7078          ip = iget(dev, ino);

  • 从INODE 队列中取出队尾的INODE号
  • 从设备上读取指向该INODE的指针
7079          if (ip==NULL)

7080           return(NULL);

  • 如果该INODE指针为空,则返回空值
7081          if(ip->i_mode == 0) {

7082           for(bp = &ip->i_mode; bp < &ip->i_addr[8];)

7083                 *bp++ = 0;

7084           fp->s_fmod = 1;

7085           return(ip);

7086          }

  • 若i_mode == 0 ,清空该INODE内容(除与时间相关的参数)
    • 置超级块 s_fmod标志
    • 返回该INODE指针
7087          /*

7088          * Inode was allocated after all.

7089          * Look some more.

7090          */

7091          iput(ip);

7092          goto loop;

  • 若i_mode != 0
    • 调用iput函数尝试释放该inode
    • 回到7075行 ,重新搜索空闲INODE
7093     }

7094     fp->s_ilock++;

  • 若INODE 队列为空,置INODE 队列锁标志
7095     ino = 0;

7096     for(i=0; i<fp->s_isize; i++) {

7097          bp = bread(dev, i+2);

7098          ip = bp->b_addr;

7099          for(j=0; j<256; j=+16) {

  • 从设备INODE区首部开始读入INODE块到缓存块bp
  • 将ip指向块首
  • j用为当前块中偏移
  • 由于j为16的倍数,所以ip[j]指向块中某一具体INODE
7100           ino++;

7101           if(ip[j] != 0)

7102                continue;

  • 判断当前INODE是否为空,若不为空,则直接寻找块中下一个INODE
7103           for(k=0; k<NINODE; k++)

7104           if(dev == inode[k].i_dev &&

7105                     ino == inode[k].i_number)

7106                goto cont;

  • 遍历内存INODE数组,将内存INODE逐一与当前INODE比较
  • 若当前INODE在内存中有一份副本,表明该INODE不是真的为空,直接寻找块中下一个INODE
7107           fp->s_inode[fp] = ino;
  • 若当前所找到的INODE在内存中没有副本,则表明其真的为空,插入INODE队列尾部
7108           if(fp->s_ninode >= 100)

7109                break;

7110          cont:;

7111          }

7112          brelse(bp);

  • 若当前磁盘块被遍历完时或者INODE队列中的元素已经突破100时
  • 释放bp
7113          if(fp->s_ninode >= 100)

7114           break;

  • 若INODE队列元素尚未突破100,则回到循环(7096)头,继续读取下一个INODE区磁盘块
  • 否则退出循环(7096)
7115     }

7116     fp->s_ilock = 0;

7117     wakeup(&fp->s_ilock);

  • 去除INODE队列锁标志
  • 唤醒一切在s_ilock上睡眠的进程,见睡眠原因
7118     if (fp->s_ninode > 0)

7119          goto loop;

  • 若INODE队列不为空,则返回到loop(7075),从当前不为空的INODE队列中分配空闲INODE
7120     prdev("Out of inodes", dev);

7121     u.u_error = ENOSPC;

  • 若未能搜索到INODE,即所有空闲INODE已用完,抛出错误,见错误代码
7122     return(NULL);

7123 }

7124 /* -------------------------*/

7125 /* -------------------------*/

Extend

附图

Ref

Caller

⚠️ **GitHub.com Fallback** ⚠️