fs.c void iupdate(struct inode *ip)

トップページ
jupiteroak.hatenablog.com


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

void iupdate(struct inode *ip)
{
  struct buf *bp;
  struct dinode *dip;

  bp = bread(ip->dev, IBLOCK(ip->inum, sb));
  dip = (struct dinode*)bp->data + ip->inum%IPB;
  dip->type = ip->type;
  dip->major = ip->major;
  dip->minor = ip->minor;
  dip->nlink = ip->nlink;
  dip->size = ip->size;
  memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));
  log_write(bp);
  brelse(bp);
}

iupdate関数は、メインメモリ上にあるiノードipを使って、ハードディスク上にあるiノードdipを更新します。

引数 struct inode *ip
ハードディスク上にあるiノードを更新するために使用するメインメモリ上にあるiノードのアドレスです。


処理の内容

ハードディスクから該当するiノードを含んだセクタに対応しているバッファを取得する

bp = bread(ip->dev, IBLOCK(ip->inum, sb));

bread関数を呼び出して、ハードディスク上にあるiノードの読み込みを行います(あるいは、ハードディスクからiノード番号がinumであるiノードを含んだセクタに対応しているバッファを取得します)。
第二引数に設定されているIBLOCKマクロは、iノード番号がinumであるiノードを含んだセクタのセクタ番号を算出します。
bread関数は、第二引数で指定されたセクタ番号を持つセクタのデータ512バイト(= dinodeのデータサイズ × 32個のiノード)を取得します。

取得したバッファのデータから該当する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ノードの内容を更新する①

dip->type = ip->type;
dip->major = ip->major;
dip->minor = ip->minor;
dip->nlink = ip->nlink;
dip->size = ip->size;

inode構造体(メインメモリ上にあるiノードを表現したデータ構造)の各メンバの値で、dinode構造体(ハードディスク上にあるiノードを表現したデータ構造)の各メンバの値を、更新します。

ハードディスク上にあるiノードの内容を更新する②

memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));

memmove関数を呼び出して、inode構造体が持つaddrs配列からdinode構造体が持つaddrs配列へ、データブロックの参照をコピーします。
addrs配列には、iノードが直接的に所有しているデータブロックのセクタ番号がそれぞれ格納されています。

ブロック(セクタ)をロギングにおけるトランザクションの管理対象として登録する

log_write(bp);

log_write関数を呼び出して、バッファbpに対応しているブロック(セクタ)を、ロギングにおけるトランザクションの管理対象として登録します。

バッファのスリープロックを解放する

brelse(bp);

brelse関数を呼び出して、バッファbpに関連しているスリープロックを解放し、他のプロセスがこのバッファを利用できるようにします。