fs.c static struct inode* iget(uint dev, uint inum)

トップページ
jupiteroak.hatenablog.com


fs.c
https://github.com/mit-pdos/xv6-public/blob/master/fs.c#L241

static struct inode* iget(uint dev, uint inum)
{
  struct inode *ip, *empty;

  acquire(&icache.lock);

  // Is the inode already cached?
  empty = 0;
  for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){
    if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
      ip->ref++;
      release(&icache.lock);
      return ip;
    }
    if(empty == 0 && ip->ref == 0)    // Remember empty slot.
      empty = ip;
  }

  // Recycle an inode cache entry.
  if(empty == 0)
    panic("iget: no inodes");

  ip = empty;
  ip->dev = dev;
  ip->inum = inum;
  ip->ref = 1;
  ip->valid = 0;
  release(&icache.lock);

  return ip;
}

iget関数は、メインメモリ上に用意されているiノードのキャッシュ領域から、引数devと引数inumで指定されるiノード取得します(配列inode[NINODE]から、引数devと引数inumで指定されるiノードエントリを取り出します)。

引数 uint dev
iノードが属しているハードディスクドライブを指定します。
引数devが1の値の時は、マスタードライブを指定しています。
引数devが0の値の時は、スレイブドライブを指定しています。

引数 uint inum
取得対象となる iノードを識別する iノード番号を指定します。

戻り値 inode構造体のアドレス
iノード番号がinumであるiノード(iノードエントリ)のアドレスです。


処理の内容

クリティカルセクションの入口を定める

acquire(&icache.lock);

メインメモリ上に用意されているiノードのキャッシュ領域(icache)を排他制御するために、acquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。

メインメモリ上に用意されているiノードのキャッシュ領域から引数devと引数inumで指定されるiノードエントリを探す

empty = 0;
  for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){
    ...
  }

メインメモリ上に用意されているiノードのキャッシュ領域の中から、引数devと引数inumで指定されるiノードを探します(配列inode[NINODE]の各エントリを走査し、引数devと引数inumで指定されるiノードエントリを探します)。

クリティカルセクションの出口を定める(引数devと引数inumで指定されるiノードエントリがみつかった場合)

if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
  ip->ref++;
  release(&icache.lock);
  return ip;
}

引数devと引数inumで指定されるiノードがみつかったら、そのiノードの参照回数をインクリメントして記録します( ip->ref++;)
その後、release関数を呼び出して取得していたロックを解放し、クリティカルセクションの出口とします。
最後に、iノードのアドレスを戻り値としてリターンします。

1番最初に見つけた未使用のiノードエントリを記憶する

if(empty == 0 && ip->ref == 0)
   empty = ip;
}

iノードを探す際は、1番最初に見つけた未使用のiノードエントリのアドレスを記憶しておきます。

引数devと引数inumで指定されるiノードエントリも未使用のiノードエントリもなかった場合

if(empty == 0)
   panic("iget: no inodes");

メインメモリ上に用意されているiノードのキャッシュ領域(配列inode[NINODE])に、引数devと引数inumで指定されるiノードエントリも未使用のiノードエントリもない場合は、panic関数を呼び出してメッセージを出力します。

引数devと引数inumで指定されるiノードエントリが見つからなかった場合

ip = empty;
ip->dev = dev;
ip->inum = inum;
ip->ref = 1;
ip->valid = 0;

メインメモリ上に用意されているiノードのキャッシュ領域(配列inode[NINODE])から、引数devと引数inumで指定されるiノードエントリがみつからなかった場合は、最初に見つけた未使用のiノードエントリに引数devと引数inumで指定されるiノードを登録します。
エントリには、ハードディスクから読み取ったiノードの値がまだ格納されてないので、validメンバの値には不正確であることを示す0を設定します。

クリティカルセクションの出口を定める

release(&icache.lock);

release関数を呼び出して、取得していたロックを解放し、クリティカルセクションの出口とします。

iノードのアドレスを戻り値としてリターンする

return ip;