fs.c static void itrunc(struct inode *ip)
トップページ
jupiteroak.hatenablog.com
fs.c
https://github.com/mit-pdos/xv6-public/blob/master/fs.c#L407
static void itrunc(struct inode *ip) { int i, j; struct buf *bp; uint *a; for(i = 0; i < NDIRECT; i++){ if(ip->addrs[i]){ bfree(ip->dev, ip->addrs[i]); ip->addrs[i] = 0; } } if(ip->addrs[NDIRECT]){ bp = bread(ip->dev, ip->addrs[NDIRECT]); a = (uint*)bp->data; for(j = 0; j < NINDIRECT; j++){ if(a[j]) bfree(ip->dev, a[j]); } brelse(bp); bfree(ip->dev, ip->addrs[NDIRECT]); ip->addrs[NDIRECT] = 0; } ip->size = 0; iupdate(ip); }
itrunc関数は、引数で指定されたiノードを未使用状態に戻します。
引数 struct inode *ip
未使用状態となるiノード(inode構造体)を指定するアドレスです。
処理の内容
- iノードが直接的に所有している全てのデータブロックを解放する
- iノードが間接的に所有している全てのデータブロックを解放する
- iノードのサイズが0であることを記録する
- iノードの変更をハードディスクに反映させる
iノードが直接的に所有している全てのデータブロックを解放する
for(i = 0; i < NDIRECT; i++){ ... }
iノードが直接的に所有している全てのデータブロックを解放します。iノードのデータ構造を表現したinode構造体のメンバであるaddrs配列には、iノードが直接的に所有しているデータブロックのセクタ番号がそれぞれ格納されています。
addrs配列の要素を初期化する
if(ip->addrs[i]){ bfree(ip->dev, ip->addrs[i]); ip->addrs[i] = 0; }
ip->addrs[i]が真となる場合→addrs配列の要素にデータブロックのセクタ番号が格納されている場合は、bfree関数を呼び出して、ハードディスク上にあるビットマップ領域にデータブロックのセクタが未使用であることを記録します。その後、addrs配列の要素ip->addrs[i]を0で初期化します。
iノードが間接的に所有している全てのデータブロックを解放する
if(ip->addrs[NDIRECT]){ ... }
ip->addrs[NDIRECT] が真となる場合→ip->addrs[NDIRECT]にセクタ番号が格納されている場合は、iノードが間接的に所有している全てのデータブロック(インダイレクトブロック)を解放します。
addrs配列の最後尾要素addrs[NDIRECT]には、各インダイレクトブロックのセクタ番号を格納したデータブロックのセクタ番号が格納されています。
イインダイレクトブロックのセクタ番号を格納したデータブロックのセクタに対応しているバッファを取得する
bp = bread(ip->dev, ip->addrs[NDIRECT]);
bread関数を呼び出して、各インダイレクトブロックのセクタ番号を格納したデータブロックのセクタに対応しているバッファを取得します。
全てのインダイレクトブロックを解放する
a = (uint*)bp->data; for(j = 0; j < NINDIRECT; j++){ if(a[j]) bfree(ip->dev, a[j]); }
全てのインダイレクトブロックを解放するために、各インダイレクトブロックのセクタ番号を格納しているデータブロックを調べます。
各インダイレクトブロックのセクタ番号を格納しているデータブロック(セクタ)では、4バイト分のデータを使って1つのセクタ番号を記録しているので、各インダイレクトブロックのセクタ番号を格納しているデータブロックには、インダイレクトブロックのセクタ番号が128個格納されています。
配列bp->dataには、各インダイレクトブロックのセクタ番号を格納しているデータブロック(セクタ)のデータが格納されています。
各インダイレクトブロックのセクタ番号を格納しているデータブロックの先頭アドレスbp->dataをuint型へのポインタaに格納し、インデックスjを用いることで、各インダイレクトブロックのセクタ番号を格納しているデータブロックのデータに、4バイトずつアクセスできるようになります(セクタ番号(4バイトサイズ)にアクセスできるようになります)。
a[j])が真となる場合→a[j])にインダイレクトブロックのセクタ番号が格納されている場合は、bfree関数を呼び出して、ハードディスク上にあるビットマップ領域にデータブロックのセクタが未使用であることを記録します。
インダイレクトブロックのセクタを未使用状態にする
bfree(ip->dev, ip->addrs[NDIRECT]); ip->addrs[NDIRECT] = 0;
bfree関数を呼び出して、ハードディスク上にあるビットマップ領域に各インダイレクトブロックのセクタ番号を格納しているデータブロックのセクタが未使用であることを記録します。
その後、addrs配列の最後尾要素ip->addrs[NDIRECT]を0で初期化します。
iノードのサイズが0であることを記録する
ip->size = 0;
iノードが所有する全てのデータブロックを解放したので、サイズメンバの値を0にします。
iノードの変更をハードディスクに反映させる
iupdate(ip);
iupdate関数を呼び出して、引数で渡されたメインメモリ上にあるiノードipを使って、ハードディスク上にあるiノードを、更新します。