mpage_writepages()
Rev.6を表示中。最新版はこちら。
1. 概要
WriteBack処理の中で呼び出されるmpage_writepages()のメモ。呼出元のWriteBack処理については「WriteBack処理」参照。
mpage_writepages()はページキャッシュからDirtyPageを取り出し、Write I/Oを開始する。
2. 処理の流れ
2.1 mpage_writepages()
mpage_writepages()はmappingで渡されたページキャッシュからDirtyページを取り出し、Write I/Oを発行していく。mpage_writepags()のプロトタイプは以下のとおり。
struct writeback_control *wbc, get_block_t get_block)
mapping: WriteBack対象のページキャッシュ(mapping)
wbc: WriteBack処理管理情報
get_block: get_blockハンドラ
処理の流れは以下のとおり。
:
while (!done && (index <= end) &&
(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
PAGECACHE_TAG_DIRTY,
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
/*
* ページキャッシュ(mapping)からDirtyページを少しずつ取得して処理していく
*/
/* 取得したDirtyPageを順番にWriteBackしていく */
for (i = 0; i < nr_pages; i++) {
:
if (writepage) {
/* generic_writepages()マクロ経由で呼び出された場合
*(writepagesハンドラが未定義のファイルシステムの場合)
*
* ファイルシステムのwritepageハンドラを呼び出して
* Write I/O発行
*/
ret = (*writepage)(page, wbc);
} else {
/* 連続ブロックをbioに格納。非連続ブロックなら内部でI/O発行 */
bio = __mpage_writepage(bio, page, get_block,
&last_block_in_bio, &ret, wbc,
page->mapping->a_ops->writepage);
}
:
}
}
/* __mpage_writepage()で作成した連続ブロックのI/Oを発行 */
if (bio)
mpage_bio_submit(WRITE, bio)
mpage_writepages()はpagevec_lookup_tag()でページキャッシュ(mapping)からDirtyページを取得して、1ページずつ処理していく。
各ページの処理にはファイルシステムのwritepageハンドラ(mapping->a_ops->writepage)が呼び出される場合と、__mpage_writepage()が呼び出される場合がある。通常は、__mpage_writepage()が使用されるが、get_block引数がNULLで呼び出されていた場合(*1)はwritepageハンドラが呼び出されて、DirtyページのWrite I/Oが発行される。
__mpage_writepage()はWrite I/O用のbio(*2)を作成する。__mpage_writepage()は対象Dirtyページが図1のようにディスク上で連続ブロックになっていた場合は、これらのブロックに対するI/Oをbioに格納して返す。作成したbioは__mpage_writepage()の次回呼出し時にも引数として渡され、連続ブロックであれば次々とbioにWrite I/Oマージされていくことになる。作成されたbioは__mpage_writepage()の最後でまとめてI/O発行(mpage_bio_submit())される。このようにWriteBack対象のディスクブロックが連続していた場合はI/O処理が効率化される。

(*1) get_block引数がNULLで呼び出されるのは、__mpage_writepage()がgeneric_writepages()マクロ経由で呼び出される時で、これはwritepagesハンドラが未定義のファイルシステムにおけるWriteBack処理の場合となる。(「WriteBack処理」参照)
(*2)「ブロックI/O」参照
