ext2_get_block()
Rev.7を表示中。最新版はこちら。
1. 概要
ext2fsのget_blockハンドラである。ext2_get_block()の実装まとめ。
編集中
2. 処理概要
2.1 ext2_get_block()
/* * 2.2節参照 */ int depth = ext2_block_to_path(inode, iblock, offsets, &boundary); /* * 2.3節参照 */ partial = ext2_get_branch(inode, depth, offsets, chain, &err); if (!partial) { got_it: /* 判明したディスクブロックをbh_resultに設定する */ map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); if (boundary) set_buffer_boundary(bh_result); /* Clean up and exit */ partial = chain+depth-1; /* the whole chain */ goto cleanup; } if (!create || err == -EIO) { /* create = 0なら新規割り当てはせず終了 */ cleanup: while (partial > chain) { brelse(partial->bh); partial--; } out: return err; } if (err == -EAGAIN) goto changed; /* 割り当て場所を決める? */ goal = 0; if (ext2_find_goal(inode, iblock, chain, partial, &goal) < 0) goto changed; /* ブロックを割り当てる partialで指定した位置からIndirectが格納される*/ left = (chain + depth) - partial; err = ext2_alloc_branch(inode, left, goal, offsets+(partial-chain), partial); if (err) goto cleanup; if (ext2_use_xip(inode->i_sb)) { /* * we need to clear the block */ err = ext2_clear_xip_target (inode, le32_to_cpu(chain[depth-1].key)); if (err) goto cleanup; } /* ei->i_next_alloc_block = block このファイルに直近で割り当てたブロック番号(ファイル内のブロック番号) linearly ascending allocation requestsを検出するのに使われる。 ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key); このファイルに対して直近で割り当てた物理ブロック番号 連続Request(linearly ascending)を検出した時の次の割り当て位置 */ if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0) goto changed; set_buffer_new(bh_result); goto got_it; changed: while (partial > chain) { brelse(partial->bh); partial--; } goto reread;
2.2 ext2_block_to_path()
int ext2_block_to_path(*inode, i_block, offsets[4], *boundary)ext2fsではi-node内にファイル内のブロックがディスク上のどこに存在しているのかブロック番号を格納したテーブルがある。ただしこのテーブルはファイル内の#0〜11番目のブロックのみしか格納しておらず、それ以降のブロックについてブロック番号を取得しようとすると、間接参照用のテーブルをたどっていく必要がある(「Ext2 FS」参照)。
ext2_block_to_path()はinodeで指定されたファイル内のi_block番目のブロックのブロック番号を取得するにあたって、間接参照用のテーブルのどのエントリを参照していけばよいのかをoffsetsに格納して返す。
例えばi_block=14のブロック番号を取得しようとした場合は、offsetsは図2.1のようになる。これは、まずi-node内の#12エントリから間接参照用テーブルのディスクブロック番号を読み出して、2段間接参照用テーブルを読み込んだ後、2段間接参照用テーブルの#2のエントリからi_block=14のブロックのブロック番号を取得できることを意味する(図2.2)。
図2.1 offsetとchain
図2.2 ブロックの間接アクセス
2.3 ext2_get_branch()
Indirect *ext2_get_branch(*inode, depth, *offsets, chain[4], *err)ext2_get_branch()はext2_block_to_path()によって返されたoffsetsを受け取り、offsetsで指定されたパスのブロックがディスク上に割り当てられているか調べていく。
図2.1のケースだと、i-node内のブロックテーブルの#12エントリからブロック番号を取得して、そのブロックを読み込む(このブロックには間接参照テーブルが格納されている)。次に読み込んだ間接参照テーブルの#2エントリからi_block=14ブロックのブロック番号を取得する。最後までブロック番号を取得できれば、offsetsで指定されたパスのブロックは全てディスク上に存在していることになる。この場合、NULLが返る。
一方、エントリからブロック番号を取得した結果、0だった場合、そのブロックはまだディスク上には存在していないことになる。
offsetsをたどってブロック番号を取得した結果は、図2.1に示すようにchainに格納して返されるが、ブロック番号が未割り当てだった場合は.key=0となり、そのchain要素のアドレスが返される。この値は呼出し元で未割り当てのブロックを割り当てていくのに使われる。