Btrfsとは何か

Btrfsを完全に理解する

投稿日: 2024年5月11日

最終更新日: 2024年5月14日

発音はbetter FS、butter FS、b-tree FSのどれかだそうです。私はbutter FS派です。

Btrfsは、Linuxの主要なファイルシステムにおいて、プール、スナップショット、チェックサムがサポートされていない問題に対処するために開発されました。フォールトトレランス、修復、簡単な管理に重点を置いて開発が進んでいます。

構造

B木を採用している

B木は木構造の一種で、O (log n) で値を探索したり挿入したり削除したりできるものです。ルートからそれぞれの葉までの深さができるだけ同じになるように調整された木構造であるバランス木であり、それぞれのノードが子ノードを持てるのが特徴です。特定のノードに、子ノードとして値を挿入しようとした際に、そのノードが持てる子ノードの数を超えてしまう場合はノードが分割され、新たなノードが作られます。Btrfsはデータを組織的に管理し、データを操作する際のパフォーマンスを向上させるためにB木を利用しています。

Btrfsは以下のような木構造を保持しています。

Tree of Tree roots

あらゆる種類の木構造のルートを検索します。

Chunk Tree

ファイルシステムの論理ブロックアドレスを物理ブロックアドレスにマッピングします。

Device Allocation Tree

ファイルシステムに割り当てられている物理デバイスを管理します。

Extent Allocation Tree

現在使われているバイト範囲を記録します。それぞれのバイト範囲がどのファイルから参照されているかを表すデータも記録されます。

FS Tree

ファイルとディレクトリを保存します。ファイルシステムが扱うメタデータも保存されます。それぞれのFS Treeには1つのサブボリュームやスナップショットを表すルートノードがあります。

Checksum Tree

データブロックのチェックサムを保存します。それぞれのデータブロックはチェックサムを持っています。

Copy On Writeを採用している

Copy On Write (COW) は、コピーを効率的に実装するために使われるリソース管理の方法です。通常のコピーでは、コピーする際に新たな空き領域を確保し、その領域にデータをコピーします。しかし、COWの場合はデータをコピーしただけでは新たな空き領域を確保しません。すなわち、データをコピーした際はコピー元のデータとコピー先のデータが同じなので、コピー元のデータ領域を参照します。そして、コピー元あるいはコピー先のデータを書き換えようとしたときに初めて新たな空き領域を確保します。

COWは、主にOSにおけるforkシステムコールで使われます。特定のプロセスがフォークされた状況で、そのプロセスが利用しているページが一切書き換えられないことが分かっている場合は、親プロセスと子プロセスがそのページを共用します。どちらかのプロセスがメモリ内のデータを更新しようとした場合に、初めてフォーク元のページのコピーが作成されます。

特徴

サイズが小さいファイルを効率良く保存できる

B木のノードにある、inlineと呼ばれるメタデータの領域に、一定のサイズまでのファイルを格納できます。inlineにファイル全体が格納される場合は別のブロックが不要になるので、サイズが小さいファイルの保存効率が高くなります。inlineのデフォルトの大きさは2048バイトです。

inodeを動的に作成する

inode番号を追跡するための固定された領域がありません。作成できるinodeの数はメタデータの領域とその使用率によって決められます。

サブボリュームを持てる

サブボリュームはBtrfsというファイルシステムの一部です。それぞれのサブボリュームはファイルやディレクトリの階層とinode番号の名前空間を持っており、他のサブボリュームから独立しています。サブボリュームのinode番号は常に256です。それぞれのサブボリュームは数値のIDを持っており、このIDはsubvolidやrootidと呼ばれます。IDによってサブボリュームを識別することで、サブボリュームを通常のディレクトリのように扱えるだけでなく、ファイルシステムに別々にマウントされたボリュームのようにも扱えます。

スナップショット

サブボリュームの一種にスナップショットがあります。スナップショットはサブボリュームのコピーです。デフォルトでは読み取りと書き込みができる状態で作成されます。スナップショットにあるファイルを変更しても、元のサブボリュームにあるファイルには影響しません。

使用率の管理

パーティション分割されたディレクトリのように、それぞれのサブボリュームのサイズを管理できます。パーティション分割されたディレクトリは通常、そのサイズを自由に拡大したり縮小したりできませんが、サブボリュームクォータを使用することでディレクトリのサイズを柔軟に変更できます。

データの破損を自動的に検出する

デフォルトでは、データが書き込まれる前にチェックサムが計算され、デバイスからブロックを読み込んだ後にチェックサムが検証されます。メタデータ全体が、B木のノードのヘッダーにあるinlineに格納されたチェックサムを持っています。チェックサムはチェックサムツリーに格納されているため、それぞれのデータブロックから分離されています。

複数のデバイスを管理しやすい

Btrfsは1つ以上のブロックデバイス上に作成できます。デバイスを後から追加したり、削除したり、交換したりすることもできます。これにより、簡単にRAIDを構築できます。BtrfsはRAID0, RAID1, RAID10, RAID5, RAID6に対応しています。それぞれのRAIDの特徴は以下の通りです。

  • RAID0: データを複数のストレージに分散して書き込む
  • RAID1: 同じデータを複数のストレージに書き込む
  • RAID10: データを複数のストレージに分散して書き込み、さらに同じデータを複数のストレージに書き込む
  • RAID5, RAID:6: データのパリティビットを複数のストレージに書き込む

TRIM/Discardに対応している

TRIM/Discardは、不要な消去と書き込みを回避することでストレージの信頼性が低下するのを抑える仕組みです。OSが、削除できるデータブロックをストレージに通知することで、ガベージコレクションの実行時にそのデータブロックが整理されます。その結果、ストレージへのデータの書き込み処理が短くなり、ストレージの消耗を防げます。

Scrubに対応している

Scrubはすべてのファイルシステムのデータのチェックサムを検証する機能です。あるデータが破損している場合に、そのデータの破損前のデータがコピーとして存在する場合は、破損しているデータが修復されます。

デフラグに対応している

デフラグ (デフラグメンテーション) はストレージの使用済みの領域と空き領域をまとめることで読み取りと書き込みを高速化することです。データを連続的に読み書きできるようになるため、シークに時間がかかるストレージであるHDDを使用する場合のパフォーマンスが大きく向上します。

増分バックアップを取得できる

send/receiveを使うことで増分バックアップを作成できます。例えば、異なるサブボリューム間の差分を増分バックアップとして送受信できます。

データの重複を排除できる

重複しているデータブロックを検索し、もしそれが見つかった場合はデータブロックのコピーを削除して共有論理リンクを作成します。共有論理リンクを作成するため、メタデータのサイズが増加しますが、重複していたデータブロックのサイズだけデータ領域を節約できます。

参考