ファイルシステム小噺(仮)


:smile: この記事は[Recruit Engineers Advent Calendar 2016](http://www.adventar.org/calendars/1617) の18日目の記事となります。:smile:

RyoMa_0923です。

Advent Calendarは人生初参戦なので、ずれてたらごめんなさい。

普段はインフラエンジニアとしてDockerやらなんやらを中心に最近は取り組んでます。

素直になるとDockerとかその周辺ツールのお話をするのが筋だと思いますが、
ひねくれものなのであえてみんながあまり興味をもてなさそうな話をします。

ちなみに業務には**役に立たない**ので注意してください。

# ファイルシステムとは

[ファイルシステム(wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)

ここでは上記URLのうち、ディスクファイルシステムについて説明します。

# 具体的に何を説明する？

今回は、今も昔もLinuxではよく使われているext系のファイルシステムについて
ざっくりと説明していきます。
そのうえで極々簡単な特性の比較をやってみています。

なぜext系なのかというと、

1. ext2, ext3, ext4とある程度最近のファイルシステムの進歩とともに進化している。
2. Linuxで過去から現在に至るまで主要ファイルシステムとしてよく使われている。

といった観点から選んでいます。

# ext2
初期のLinuxカーネルで標準的に用いられたファイルシステムです。

ジャーナリングなどがなく、ファイルシステムの一貫性を確保する仕組みが弱いので、
OSが異常終了した場合に、fsckによる管理領域とディスク上の全データの照らし合わせが必要です。
この結果、ディスクの大容量化に伴い利用が厳しくなってきました。

# ext3
ext3とext2の最大の違いはジャーナリング機能の有無です。
ext3ではext2で最大の弱点だった異常終了後のfsckからある程度解放されました。

また、ファイルシステムの大容量化にともなう
多数のファイルに対応するための仕組みも追加されています。

ext3ではジャーナリングには3つのモードが存在します。

- journal
- order (デフォルト)
- writeback

上のものほど信頼性は高く、下のものほどパフォーマンスは高くなります。

# ext4
ext4はext3でもファイルシステムの大容量化に対応できなくなってきた
タイミングで現れたファイルシステムで、Ubuntuなどで標準的に用いられている
ファイルシステムです。(RHEL 7.x系はXFS)

特に現在において重要なのは以下の2つです
- Htreeアルゴリズムによるディレクトリ検索の改善
- スパースファイルへの対応

前者はディレクトリ内のファイル検索効率をO(n)からO(logN)に改善、
後者は仮想化におけるシンプロビジョニングを実現しました。

他にも多数の機能の追加・補強が行われています。

個人的には、ext3が古臭く感じれられる状況になっていた中、
一気にext系のファイルシステムを他の先進的なファイルシステムに
近づける大きな役割を果たしたと考えています。

# 比較

ファイルシステムで最も重要なのは読み込みおよび書き込みの性能と信頼性です。
ここでは、書き込みの性能について比較して見ます。

どれだけext2 ~ ext4で変化があったのかを確認してみます。
以下のようなディレクトリ構成で実験しています。

|マウントポイント|ファイルシステム|
|---|---|
|/mnt/ext2|ext2|
|/mnt/ext3|ext3|
|/mnt/ext4|ext4|

## ファイルへの書込性能
各ディレクトリ直下に10万個のファイルを作成し、
そのファイルに書き込みを行います。

### 試した内容
#### パターン1(file_write.sh)

下記スクリプトによる、10万個のファイルに書き込み処理を行います。
(ファイルは事前に作成済み)

```bash:file＿write.sh
#!/bin/bash
i=0
while [ $i -lt 100000 ]
do
        echo "Write test" >> ./$i
        i=$(( i + 1 ))
done
```

なお、上記スクリプトの実行前に、下記コマンドでファイルキャッシュを無効化しています。
```bash:キャッシュ無効化
echo 3 > /proc/sys/vm/drop_caches
```

#### パターン2(ddによるファイル作成)
ddで20GBのファイルを作成してみます。

```bash:20GBのファイル作成 
time dd if=/dev/zero of=./test bs=4096 count=5000000
```

### 比較結果

timeコマンドのrealの値をファイルシステム別に比較してみました。

|パターン|ext2|ext3|ext4|
|---|---|---|---|
|パターン1(sec)|19.0±2.0|32.0±2.23|19.8±1.3|
|パターン2(sec)|286|294|293|

シーケンシャルに大容量のファイルを作成するという観点では
ファイルシステム間ではあまり差が出ないという結果が出ました。

一方でext3は多数のファイルに少しづつ書き込みを行うのは苦手という結果が得られました。
これはext3が基本的にext2にジャーナリングの仕組みを導入したものだということによります。

このことが原因で、ext4が一般的になる前には
**ext3が遅いのでext2を使って痛い目を見たなんていう笑い話**
があったりしました。

# ほんの少しだけ実用的な話

これだけだとあんまりなので、最後に実用的な話をひとつだけ。

## ext系ファイルシステムの互換性
ext系のファイルシステムは下位互換性を持っているので、
ext4はext2, ext3のファイルシステムをマウントすることができます。
ここではext2ファイルシステムで作成された/dev/sdbをext4ファイルシステムとしてマウントしてみます。

```bash:ext2ファイルシステムをext4ファイルシステムとしてマウントする
$ sudo mount -t ext2 /dev/sdb /mnt/ext2
$ echo "ext2だよ～" >> /mnt/ext2ext2_filesystem
$ sudo umount /mnt/ext2
$ sudo mount -t ext4 /dev/sdb /mnt/ext2
$ ls /mnt/ext2
ext2_filesystem
$ cat /mnt/ext2/ext2_filesystem
ext2だよ～
```

ext2をext4としてマウントでき、ファイルの読込・書き込みも可能です。
(ext3をext4としても同様)

よって、古いLinux環境で利用していたファイルシステムを最新のLinux環境でマウントし
利用するといったことも可能です。

なお、**ext2,3をext4としてマウントしてもすべての機能を利用できるわけではない**ので要注意。
(一部の機能は利用できるようですが...)
ext4の機能をフルに活用するには、tune2fsを利用したファイルシステムの変換が必要です。


# 最後に

ファイルシステムは昔からずっとOSやハードウェアの進歩と並行して、
ユーザの要求する機能・非機能要件を充足するために進化を遂げてきました。

ファイルシステムによって同系列のものであっても、特性が異なることも
書込みの性能比較の結果からわかっていただけたかもしれません。

普段コードを書いたりしているだけでは意識することは多くないファイルシステムですが、
私たちが作ったコードから生成されるデータを守るという観点では
間違いなくファイルシステムが大きな役割を果たしています。

たまの休みには思いを馳せてみてもよいのでは？と思いこのような記事を書いてみました。