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ノードエントリ)のアドレスです。
処理の内容
- クリティカルセクションの入口を定める
- メインメモリ上に用意されているiノードのキャッシュ領域から引数devと引数inumで指定されるiノードエントリを探す
- 引数devと引数inumで指定されるiノードエントリも未使用のiノードエントリもなかった場合
- 引数devと引数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を設定します。
iノードのアドレスを戻り値としてリターンする
return ip;