Linux Kernel(2.6)の実装に関するメモ書き

ext2_get_block()


Rev.6を表示中。最新版はこちら

1. 概要

ext2fsのget_blockハンドラである。ext2_get_block()の実装まとめ。

編集中

2. 処理概要

2.1 ext2_get_block()


ext2_get_block()の処理概要
/*
 * iblock番目のブロックのXXXXXXXXXをoffsetに格納して返す。
 * 例えば、iblockが14の時は
 * offset[0] = 12
 * offset[1] = 2
 * となる。(図xx参照)
 */
int depth = ext2_block_to_path(inode, iblock, offsets, &boundary);
/*
* offsetで指定されたパスを辿って
*/
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から取得したブロック番号のブロック

結果はchainに格納

割り当てられていればNULLが返る。

割り当てられていなければ、未割り当ての場所を返す


3. 関連ページ



最終更新 2007/08/21 22:00:27 - kztomita
(2007/08/21 21:14:09 作成)
添付ファイル
indirect.png - kztomita
offset_chain.png - kztomita


リンク
最近更新したページ
検索