12月 042015
 

この記事はVarnish Cache Advent Calendar 2015の3日目の記事になります。

Varnishは4.0まではfile-storageを使用する場合は特にpre-allocateをしないため、フラグメントによるパフォーマンス低下を防ぐためにdd(1)を使って先に確保してしまうのを推奨していました。
4.1でも事前確保するのを推奨しているのですが、実はbetaまではfallocateを利用してpre-allocateするようになっていました。
正式版ではこの機能はext4限定になってしまい他のファイルシステムではdisableになりました。
何故かxfsだと既に領域を確保しているにもかかわらずfallocateを使おうとするとENOSPCがでるケースがあったためです。
このバグの報告をしたのは自分なのですが、その際にfallocateについて調べてたら割と興味深い動きだったので今回書きます。

fallocateとは
すごく簡単にいうとめっちゃ高速にディスク領域の割当ができます。
どれぐらい速いかというと
[code=’shell’]
# time fallocate -l 10GB varnish_storage.bin

real 0m0.001s
user 0m0.000s
sys 0m0.001s

[/code]
と気にならないレベルです。
割と便利だと思います。

fallocateの不思議な動き
xfsとext4でfallocateの動きを確認した際に以下のような動きをしました。

xfs-fallocate
[code=’shell’]
root@varnish-trunk:/mnt/xfs# df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/xvdh xfs 15718400 32928 15685472 1% /mnt/xfs
root@varnish-trunk:/mnt/xfs# fallocate -l 10GB varnish_storage.bin
root@varnish-trunk:/mnt/xfs# df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/xvdh xfs 15718400 9798556 5919844 63% /mnt/xfs
root@varnish-trunk:/mnt/xfs# fallocate -l 10GB varnish_storage.bin
fallocate: varnish_storage.bin: fallocate が失敗: デバイスに空き領域がありません
root@varnish-trunk:/mnt/xfs# ls -ltah varnish_storage.bin
-rw-r–r– 1 root root 9.4G 12月 3 23:55 varnish_storage.bin
[/code]

ext4-fallocate
[code=’shell’]
root@varnish-trunk:/mnt/ext4# df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/xvdi ext4 15350768 38384 14509568 1% /mnt/ext4
root@varnish-trunk:/mnt/ext4# fallocate -l 10GB varnish_storage.bin
root@varnish-trunk:/mnt/ext4# df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/xvdi ext4 15350768 9804016 4743936 68% /mnt/ext4
root@varnish-trunk:/mnt/ext4# fallocate -l 10GB varnish_storage.bin
root@varnish-trunk:/mnt/ext4# ls -ltah varnish_storage.bin
-rw-r–r– 1 root root 9.4G 12月 3 23:56 varnish_storage.bin
[/code]
なぜかxfsは同じ容量を確保しようとしてるのに失敗する。

xfs-stat
[code=’shell’]
root@varnish-trunk:/mnt/xfs# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/xfs# stat varnish_storage.bin
File: `varnish_storage.bin’
Size: 1000000000 Blocks: 1953128 IO Block: 4096 通常ファイル
Device: ca70h/51824d Inode: 131 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-12-03 23:58:42.851567000 +0900
Modify: 2015-12-03 23:58:47.475567000 +0900
Change: 2015-12-03 23:58:47.475567000 +0900
Birth: –
root@varnish-trunk:/mnt/xfs# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/xfs# stat varnish_storage.bin
File: `varnish_storage.bin’
Size: 1000000000 Blocks: 1953128 IO Block: 4096 通常ファイル
Device: ca70h/51824d Inode: 131 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-12-03 23:58:42.851567000 +0900
Modify: 2015-12-03 23:59:15.123567000 +0900★変わった
Change: 2015-12-03 23:59:15.123567000 +0900★変わった
Birth: –
[/code]

ext4-stat
[code=’shell’]
root@varnish-trunk:/mnt/ext4# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/ext4# stat varnish_storage.bin
File: `varnish_storage.bin’
Size: 1000000000 Blocks: 1953136 IO Block: 4096 通常ファイル
Device: ca80h/51840d Inode: 12 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-12-03 23:59:35.871567000 +0900
Modify: 2015-12-03 23:59:35.871567000 +0900
Change: 2015-12-03 23:59:35.871567000 +0900
Birth: –
root@varnish-trunk:/mnt/ext4# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/ext4# stat varnish_storage.bin
File: `varnish_storage.bin’
Size: 1000000000 Blocks: 1953136 IO Block: 4096 通常ファイル
Device: ca80h/51840d Inode: 12 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-12-03 23:59:35.871567000 +0900
Modify: 2015-12-03 23:59:35.871567000 +0900★変わってない
Change: 2015-12-03 23:59:35.871567000 +0900
Birth: –
[/code]
xfsは同じサイズでfallocateを叩くとタイムスタンプが変わる。

xfs-filefrag
[code=’shell’]
root@varnish-trunk:/mnt/xfs# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/xfs# filefrag -v varnish_storage.bin |md5sum
8a5e67e82aa00af5af01c6d825bd8142 –
root@varnish-trunk:/mnt/xfs# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/xfs# filefrag -v varnish_storage.bin |md5sum
8a5e67e82aa00af5af01c6d825bd8142 –
[/code]

ext4-filefrag
[code=’shell’]
root@varnish-trunk:/mnt/ext4# filefrag -v varnish_storage.bin |md5sum
9785097e3ce0e6eb3dd703fbd54e5d69 –
root@varnish-trunk:/mnt/ext4# fallocate -l 1GB varnish_storage.bin
root@varnish-trunk:/mnt/ext4# filefrag -v varnish_storage.bin |md5sum
9785097e3ce0e6eb3dd703fbd54e5d69 –
[/code]
両方共、physical_offsetに変化なし
ちなみにext4の場合は割とフラグメントしますがxfsの場合はあまりしませんでした。
(10GB確保時にext4=12~50extents xfs=3~5extents)

これらを見てみると恐らくxfsは毎回空き容量と確保したい容量を付きあわせていて(既にallocateされてる容量は無視?)
ext4は最初にコマンド実施が必要かどうかをチェックしてるように見えます。
なんでこうなるのかxfsのコードを少し追ったのですが流石にキツかったので途中で諦めました。

まとめとか
fallocateは速くて便利なんでdd使ってpre-allocateしてる人はfallocate使うと幸せになれると思います(とは言えext3とかはサポートしてませんが)
そしてvarnish4.1をext4で動かす場合は内部でfallocateするので、今まで手動でやっていたpre-allocateは不要です。
もし、自分でfallocateを使ったコードを書く場合は実行前にfstat等で実際に使用している容量を調べるなどして使うと良いと思います。

 Posted by at 12:43 AM

  2 Responses to “file-storageのpre-allocateについて(fallocate)”

  1. そのまま利用してたら謎のIO Waitが発生し悩まされてましたが、こちらで解決しました。
    これはどのバージョンを利用したとしても、XFSの場合はDDで全領域割り当てをしないといけないということでしょうか?

  2. いいえddである必要はなくfallocateで問題無いです。
    ただxfsの場合は既に容量が確保されているケースでも確保するための残容量がない(ENOSPC)が返されるので注意しましょうぐらいです。
    また、なおpre-allocate自体は特に必須ではないのと(パフォーマンスを考える時は推奨)
    やる場合はファイルシステムにかかわらずにやって置くとよいでしょう。
    記事でも触れたとおり4.1.xでext4で動く場合はVarnish側でやるので特に必要はありません。
    なお、他のfsでやる場合でも起動の度にやる必要はなく、一度やればOKです。

    また4.0.xではpre-allocate関連ではないですが容量計算に問題があって
    指定ストレージサイズが空き容量を超えるサイズを指定していると
    既にサイズが確保されている場合(pre-allocate)に起動失敗するバグがありますのでご注意ください。(4.0.3でも起きるはず)
    https://www.varnish-cache.org/trac/ticket/1682

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。