それでは、dentryキャッシュがどのような処理シーケンスで有効に働くのかを説明します。
処理シーケンスとしては、ファイル名から対象ファイル(dentry)を検索する場面ですが、大きく分けて以下の2つのケースがあります。
まずは、dentryキャッシュヒットする場合から見てみましょう(図4)。
Linuxのファイル検索処理では、まずdentryのハッシュテーブルに対して、対象のdentryが存在するかどうかを問い合わせます(①)。ハッシュテーブル検索処理では、dentryの(d_parent、d_name.hash、d_name.name)から、対象ファイルのdentryを検索します(②)。検索で見つけたdentryは、その後の処理で使用している間に、バックグラウンドでメモリ解放されてしまわないように、使用中であることを明示しておきます(③)。検索対象dentryを呼び出し元に返します(④)。
②のハッシュテーブルの検索で、dentryが見つかれば、“キャッシュヒットした”ということです。これら一連の処理は、すべてメモリ上の操作だけなので非常に高速です。
それでは、次にキャッシュヒットしない場合について見てみましょう(図5)。
①②までは先ほどと同じ処理ですが、キャッシュ上には検索対象dentryが存在しませんので、呼び出し元には“NULL”を返します(③)。キャッシュ上に存在しないからといって、対象ファイルが存在しないというわけではありません。実際には、HDD(注4)にデータとして格納されているかもしれませんので、空のdentryを作成し(④)、ローカルファイルシステムに対して、実検索依頼を行います(⑤)。ローカルファイルシステム側では、メタデータの中を検索して、対象ファイルを探します(⑥)。この際、メモリではなく低速なHDDへのアクセスが発生しますので処理速度は先ほどの数百倍遅くなり得ます。そして、対象ファイルが見つかると、dentryに適切なデータを設定し(⑦)、呼び出し元にdentryを返します(⑧)。このようにキャッシュヒットしない場合、性能ネックの原因になるということを、これで理解できたと思います。
なお、ローカルファイルシステムに問い合わせをして、ファイルが存在しない場合もあります。このような場合、Linuxではあえて空のdentryをそのまま残しています。このdentryは「ネガティブdentry」と呼ばれ、同じ存在しないファイル名で検索が行われた場合、ローカルファイルシステムに対する無駄なアクセスを抑制できる効果があります。
今回は、Linuxカーネルのdentryの役割について一通り説明しました。オリジナルのファイルシステムを作る際に重要となるのは、キャッシュ検索で見つからなかったときに、検索対象のファイルをdentryとして登録してあげる点です。ぜひ覚えておきましょう。
次回は、dentryが参照しているファイルの実体である「inode」について解説していきます。お楽しみに! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.