fs.c void ilock(struct inode *ip)
トップページ
jupiteroak.hatenablog.com
fs.c
https://github.com/mit-pdos/xv6-public/blob/master/fs.c#L287
void ilock(struct inode *ip) { struct buf *bp; struct dinode *dip; if(ip == 0 || ip->ref < 1) panic("ilock"); acquiresleep(&ip->lock); if(ip->valid == 0){ bp = bread(ip->dev, IBLOCK(ip->inum, sb)); dip = (struct dinode*)bp->data + ip->inum%IPB; ip->type = dip->type; ip->major = dip->major; ip->minor = dip->minor; ip->nlink = dip->nlink; ip->size = dip->size; memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); brelse(bp); ip->valid = 1; if(ip->type == 0) panic("ilock: no type"); } }
ilock関数は、引数で渡されたiノードをスリープロックします。必要であれば、ハードディスクからiノードの読み込みを行います。
引数 struct inode *ip
スリープロックの対象となるiノード(inode構造体)のアドレスです。
処理の内容
iノードが不正な状態ではないことを確認する
if(ip == 0 || ip->ref < 1) panic("ilock");
ip == 0 || ip->ref < 1 が真となる場合→引数ipにiノードが指定されていない、または、iノードの参照回数が0となる場合は、panic関数を呼び出してメッセージを出力します。
iノードに含まれる内容が無効状態の場合
if(ip->valid == 0){ .... }
ip->valid == 0 が真となる場合→iノードの内容が無効状態として記録されている場合は、ハードディスクからiノードの読み込みを行います。
ハードディスクから該当するiノードを含んだセクタに対応しているバッファを取得する
bp = bread(ip->dev, IBLOCK(ip->inum, sb));
bread関数を呼び出して、ハードディスク上にあるiノードの読み込みを行います(あるいは、ハードディスクからiノード番号がinumであるiノードを含んだセクタに対応しているバッファを取得します)。
第二引数に設定されているIBLOCKマクロは、iノード番号がinumであるiノードを含んだセクタのセクタ番号を算出します。
bread関数は、第二引数で指定されたセクタ番号を持つセクタのデータ512バイト(32個のiノード= 512÷dinodeのデータサイズ)を取得します。
取得したバッファのデータから該当するiノードを取り出す
dip = (struct dinode*)bp->data + ip->inum%IPB;
iノード番号inumのiノードを取得するために、取得したバッファに格納されているデータの先頭アドレスbp->dataをdinode構造体へのポインタに格納し、そのポインタにinum%IPBを加算します。dinode型へのポインタに加算する操作により、sizeof(struct dinode)バイト境界のアドレス(dinode構造体のデータサイズの倍数値となるアドレス)で、取得したバッファに格納されているデータにアクセスすることができます。これは、取得したバッファに格納されているデータがdinode構造体の配列として、ポインタに加算する値inum%IPBが配列のインデックスとして、機能していることと実質的に同じです。
IPBは、ブロック1個当たりのiノード数を算出するマクロです。inumをIPBで剰余演算した値であるinum%IPBは、dinode構造体の配列(取得したバッファに格納されているデータ→セクタ内のデータ)において、iノード番号inumのiノードを指定するインデックスとなります。
ハードディスク上にあるiノードの内容を取得する①
ip->type = dip->type; ip->major = dip->major; ip->minor = dip->minor; ip->nlink = dip->nlink; ip->size = dip->size;
dinode構造体(ハードディスク上にあるiノードを表現したデータ構造)の各メンバの値で、inode構造体(メインメモリ上にあるiノードを表現したデータ構造)の各メンバの値を、更新します。
ハードディスク上にあるiノードの内容を取得する②
memmove(ip->addrs, dip->addrs, sizeof(ip->addrs));
memmove関数を呼び出して、dinode構造体が持つaddrs配列からinode構造体が持つaddrs配列へ、データブロックの参照をコピーします。
addrs配列には、iノードが直接的に所有しているデータブロックのセクタ番号がそれぞれ格納されています。
iノードの内容が有効であることを記録する
ip->valid = 1;
validメンバに1を設定して、iノードの内容が有効であることを記録します。