btrfs の練習
僕も、雰囲気でbtrfsを使ってる。
- サブボリューム
- スナップショット
- マウント
- スクラブ ( scrub )
- デフラグ
- バックアップ(send/receive)
- スパニング(LVM/raid)
- リサイズ
- 重複排除
- lxc storage
btrfsって多機能なんだぜ?でも、LVM+ext4で事足りるからあまり真剣に向き合って無いので、いい機会なので、使ったことない機能などを試して、自分にとって不明点を明らかにして調べることにした。
btrfs の作成
## パーティション作成 sudo sgdisk -Z /dev/sda sudo sgdisk -n '0::+1G' /dev/sda sudo sgdisk -n '0::+10G' /dev/sda ## btrfs 作成 sudo mkfs.btrfs /dev/sda1 sudo mkfs.btrfs /dev/sda2
作成されたことをcheckサブコマンドで確認
sudo btrfs check /dev/sda1 sudo btrfs check /dev/sda2
問題なく作成された
found 147456 bytes used, no error found
実験用に作る
実験するだけなら、適当なファイルを作って、フォーマットしてマウントすれば良い。
fallocate -l 128M sample.btrfs.img mkfs.btrfs sample.btrfs.img sudo mount -t auto sample.btrfs.img mnt
またはLoopバックデバイスを経由する
fallocate -l 128M sample.btrfs.img sudo losetup -f sample.btrfs.img DEV=$(sudo losetup | grep sample | cut -d ' ' -f 1 ) echo $DEV # /dev/loop10 mkfs.btrfs ${DEV} sudo mount ${DEV} mnt
マウント・マウント解除
btrfs をマウントしてみる。
sudo mount /dev/sda1 /mnt
マウントのチェック
findmnt /mnt
正常にマウントされている。
TARGET SOURCE FSTYPE OPTIONS /mnt /dev/sda1 btrfs rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/
中身を見てみる。ext4 みたいなlost foundはない。root権限になっている
# ls -l /mnt total 0 # ls -ld /mnt drwxr-xr-x 1 root root 0 5月 19 16:07 /mnt # touch /mnt/hello
問題なく作成された。
マウントを解除
sudo umount /mnt
サブボリュームを使う
最初にマウントする。
sudo mount /dev/sda1 /mnt
サブボリュームを一覧する
sudo btrfs subvolume list /mnt
サブボリュームを作る。
sudo btrfs subvolume create /mnt/subA
サブボリュームを一覧する
sudo btrfs subvolume list /mnt
実行結果の例
ID 256 gen 15 top level 5 path subA
サブボリューム内部にファイルを作る
sudo touch /mnt/subA/in-sub-a.txt
サブボリュームをマウントする(名前で指定)
sudo mount -o subvol=/subA /dev/sda1 /mnt
サブボリュームをマウントする(IDで指定)
sudo mount -o subvolid=256 /dev/sda1 /mnt
マウント結果の例。サブボリューム内部だけが見える。
ls /mnt in-sub-a.txt
サブボリュームを削除する
sudo btrfs subvolume delete /mnt/subA/
サブボリュームは、単なるディレクトリ?
単なるディレクトリとして考えても問題ないと思う。サブボリュームはディレクトリのすごいヤツ
ディレクトリと同名のサブボリュームは作成できない。
例:ディレクトリが存在するとサブボリュームが作れない。
# ls /mnt dirA hello # btrfs subvolume create /mnt/dirA ERROR: target path already exists: /mnt/dirA
ディレクトリと競合するのがSubvolumeである。ディレクトリの一種と考えておくといいだろう。(我々利用者から見るとディレクトリにしかみえない)
ディレクトリをサブボリュームに変換する方法
サブボリュームがディレクトリと同じように見えるとしても、サブボリュームとディレクトリの相互変換はできない。かわりに、名前をつけてrsyncでデータを抜き出すしか無いかも。
サブボリュームを移動する(名前変更)
上記で述べたように、サブボリュームは単なるディレクトリとして扱える。
サブボリュームの名前の変更(移動)は単純にmvコマンドを使う。ディレクトリとして扱うだけ
sudo mv subA/ subAA
実行結果の例。
$ sudo btrfs subv list /mnt/ ID 257 gen 24 top level 5 path subAA
上記のように、mv
コマンドでディレクトリ名変更でサブボリューム名が変更されている。ディレクトリ操作である。「我々利用者から見るとディレクトリと思っておけば良い。」という理由である。
スナップショットを使う。
スナップショットは、サブボリューム。
btrfs subvolume snapshot /mnt/src_name/ /mnt/snap_name
sudo muont /dev/sda1 /mnt sudo touch /mnt/s1/sodium.txt
動作サンプル
sudo btrfs subvolume snapshot /mnt/s1/ /mnt/s1.snap Create a snapshot of '/mnt/s1/' in '/mnt/s1.snap'
スナップショットとの差分を作る
sudo touch /mnt/s1/sodium_hydroxide.txt
スナップショットとオリジナルの差分を見てみる。
sudo ls /mnt/s1*/s*.txt
スナップショット時点と違いが出ても保持されているとわかる。
sudo ls -l /mnt/s1*/s*.txt -rw-r--r-- 1 root root 0 5月 19 21:21 /mnt/s1.snap/sodium.txt -rw-r--r-- 1 root root 0 5月 19 21:21 /mnt/s1/sodium.txt -rw-r--r-- 1 root root 0 5月 19 21:24 /mnt/s1/sodium_hydroxide.txt
スナップショットは単なるサブボリュームである。
読み取り専用モード
スナップショットをバックアップの目的で作るならread onlyで作る。
## read only sudo btrfs subvolume snapshot -r /mnt/s1/ /mnt/s1.snap.ro ## read write sudo btrfs subvolume snapshot -r /mnt/s1/ /mnt/s1.snap.rw
read only
は次で使う。send / recieveで必要
send/recieve
send はbtrfsの中身を取り出してストリームにする。
receiveは ストリームを受け取って btrfs に書き込む
send / recieive の例
sudo btrfs send /mnt/s1.snap.ro/ | sudo btrfs receive /mnt/subB
実行後のスナップショット
sudo btrfs sub list /mnt ID 256 gen 13 top level 5 path subA ID 257 gen 20 top level 5 path subB ID 258 gen 13 top level 5 path s1.snap.ro ID 260 gen 21 top level 257 path subB/s1.snap.ro
サブボリュームの内部にファイルがコピーされた
send はファイルに書き出せる
sudo btrfs send /mnt/s1.snap.ro/ | cat - > out
書き出したファイルを見てみると。ストリームである。
hexdump -C out 00000000 62 74 72 66 73 2d 73 74 72 65 61 6d 00 01 00 00 |btrfs-stream....| 00000010 00 2e 00 00 00 01 00 a8 c3 e9 a1 0f 00 0a 00 73 |...............s| 00000020 31 2e 73 6e 61 70 2e 72 6f 01 00 10 00 93 7e dc |1.snap.ro.....~.| 00000030 42 ca d0 f8 4f ae 65 e3 38 89 f1 69 9f 02 00 08 |B...O.e.8..i....| 00000040 00 0b 00 00 00 00 00 00 00 1c 00 00 00 13 00 02 |................| 00000050 37 2d 8c 0f 00 00 00 06 00 08 00 00 00 00 00 00 |7-..............| 00000060 00 00 00 07 00 08 00 00 00 00 00 00 00 00 00 10 |................| 00000070 00 00 00 12 00 59 55 75 35 0f 00 00 00 05 00 08 |.....YUu5.......| 00000080 00 ed 01 00 00 00 00 00 00 34 00 00 00 14 00 98 |.........4......|
このことから、tar などと同じく、パイプ転送ができることがわかる。
btrfs send /mnt/s1.snap.ro/ | ssh root@127.0.0.1 'btrfs receive /mnt/subC'
実行後のサブボリューム
sudo btrfs sub list /mnt ID 256 gen 13 top level 5 path subA ID 257 gen 20 top level 5 path subB ID 258 gen 13 top level 5 path s1.snap.ro ID 260 gen 23 top level 257 path subB/s1.snap.ro ID 261 gen 25 top level 5 path subC ID 262 gen 26 top level 261 path subC/s1.snap.ro
サブボリューム内部に、スナップショットが転送された。
別のパーティションでも試す。
別のディスクのパーティションへ転送してみたらどうなるのか。
sudo mount -t btrfs /dev/sdb1 /mnt2
別のパーティションへ転送する
btrfs send /mnt/s1.snap.ro/ | sudo btrfs receive /mnt2/an1/
転送結果から、無事に転送されたことがわかる。
sudo btrfs su list /mnt2/an1/ ID 256 gen 8 top level 5 path an1 ID 257 gen 11 top level 256 path s1.snap.ro
このことから、send/receiveでバックアップやdumpが取れる。
btrfs はサブボリュームをメインに使って、サブボリューム単位でスナップショットを取って使うのが良さそう。
ext4 のように、dump fs /restore fs が存在しないが、btrfs では send / reciveを使って同様っぽい
btrfs subvolume を省略する
subvolume は長いので、もう少し短くできる。
sudo btrfs su list sudo btrfs sub list sudo btrfs subv list sudo btrfs subvol list sudo btrfs subvolu list sudo btrfs subvolume list
scrub send subvolume
と3つあるので、btrfs s
のように究極の省略はできない。
メンテナンス defrag / scrub / check
デフラグ(マウント中)
sudo btrfs filesystem defragment -r /mnt
チェック(アンマウント必須)
チェックコマンドは、ディスクの修正を兼ねている.
sudo umount /dev/sdb sudo btrfs check /dev/sdb
ちょっとおかしい程度なら、 check して scan したら治ってることが多い。 repairしたこと無いし、使うことがない
スクラブ
スクラブ、時間がかかるので start -> status でfinishチェック
sudo btrfs scrub start /dev/sdb sudo btrfs scrub status /dev/sdb
空き容量の確認 ( usage )
sudo btrfs filesystem usage /mnt
使用容量の確認
sudo btrfs filesystem df /mnt sudo btrfs filesystem du /mnt
df / df より、usageをつかことが多くて詳しいことは知らない。
ssd trim
マウント時に、discardオプションを付けておくと、fstrim
コマンドが使えるようになる。
mount -o discard
discardには並列(非同期)があって、そちらのオプション( -o discard=async )も使えるらしい
LVM的に使う
btrfs では、lvmのように、複数のディスクにまたがったファイルシステムが作成可能です。
2つのディスクから1つのbtrfsを作る
2つのディスクを作る。
## 1 つめ fallocate -l 128M sample.btrfs.img sudo losetup -f sample.btrfs.img # /dev/loop10 ## 2つ目 fallocate -l 128M sample2.btrfs.img sudo losetup -f sample.btrfs.img # /dev/loop10
2つのディスクからBtrfsを作る。
mkfs.btrfs -m single /dev/loop10 /dev/loop11
マウントすると、2倍の容量になってる。
$ sudo mount /dev/loop11 /mnt $ df -h /mnt Filesystem Size Used Avail Use% Mounted on /dev/loop10 256M 3.4M 242M 2% /mnt
マウントは、2つどちらをを指定しても同じようです。
ディスクの追加
LVMの特徴といえば、ディスクを柔軟に使えることだろう。btrfsでも同じようなことができる。
1本目のディスクを作成
sudo mkfs.btrfs -f /dev/loop10 sudo mount /dev/loop10 /mnt
2本目のディスクを追加
sudo btrfs device add /dev/loop11 /mnt
追加後の結果を表示(singleになっていて、容量が増えたことがわかる。)
$ sudo btrfs filesystem df /mnt Data, single: total=8.00MiB, used=0.00B $ sudo btrfs filesystem usage /mnt Overall: Device size: 256.00MiB
2本目のディスクを削除
sudo btrfs device remove /dev/loop11 /mnt
LVMはPVをremoveするときに、pvmove で別ディスクにデータを移して削除してくれるし、それはオンラインでしかもマウント継続中のまま行えたと思う。btrfsでも同じようだ。空き容量があれば、LVMみたいに自動的に移動してくれるっぽい。
ディスクを取り外す。(あまり使わない)
sudo umount /mnt sudo btrfs device scan --forget /dev/loop11 sudo btrfs device scan sudo mount /dev/loop10 /mnt
removeと間違えそうだ。使うときは、ディスクを取り出してミラーリングの別ディスクに付け替えるときだろうか。何も考えずに forgetしたら ディスクにアクセスできなくなった。scan
をしたらディスクが再びマウント可能になった。
raid の場合
Raid1(ミラーリングで作る)
sudo mkfs.btrfs -d raid1 /dev/loop10 /dev/loop11 sudo mkfs.btrfs /dev/loop10 /dev/loop11
Raid0(ストライピング)
sudo mkfs.btrfs -m raid0 /dev/loop10 /dev/loop11
シンプル(スパニング)
sudo mkfs.btrfs -m single /dev/loop10 /dev/loop11
ギョーカイでは常識なRAIDだけど、専用カードによるRAIDはよく壊れるので私は信用してない。ソフトウェアなら信じてもいいのだけど、Btrfsではどうなのでしょうね。Raid5/6には重大なバグがあるとかだから、raid0/1も過度に信用して良いものか迷う。
raid とメタデータ
raidは、メタデータ-m
と実データ-d
について指定する。デフォルトはデータシングル
とメタデータはdup
デフォルトの確認(オプションなし
)
$ sudo mkfs.btrfs /dev/loop10 $ sudo mount /dev/loop10 /mnt $ sudo btrfs filesystem df /mnt Data, single: total=8.00MiB, used=0.00B System, DUP: total=8.00MiB, used=16.00KiB Metadata, DUP: total=32.00MiB, used=128.00KiB GlobalReserve, single: total=3.25MiB, used=0.00B
デフォルトの確認( -m single
)
$ sudo mkfs.btrfs -f -m single /dev/loop10 $ sudo btrfs filesystem df /mnt Data, single: total=8.00MiB, used=0.00B System, single: total=4.00MiB, used=16.00KiB Metadata, single: total=8.00MiB, used=128.00KiB GlobalReserve, single: total=3.25MiB, used=0.00B
デフォルトの確認-d single
$ sudo mkfs.btrfs -f -m single /dev/loop10 $ sudo mount /dev/loop10 /mnt $ sudo btrfs filesystem df /mnt Data, single: total=8.00MiB, used=0.00B System, DUP: total=8.00MiB, used=16.00KiB Metadata, DUP: total=32.00MiB, used=128.00KiB GlobalReserve, single: total=3.25MiB, used=0.00B
上記の結果からわかる通り、メタデータとデータがRaidになる。メタデータはデフォルトがDUPであり、実データは single であるとわかる。
このことは、mkfs.btrfsの実行結果にも出てくる。(たぶん最初のうちは読み飛ばしてると思う)
mkfs.btrfsの実行結果 の例
sudo mkfs.btrfs -f /dev/loop10 btrfs-progs v5.16.2 See http://btrfs.wiki.kernel.org for more information. Performing full device TRIM /dev/loop10 (128.00MiB) ... NOTE: several default settings have changed in version 5.15, please make sure this does not affect your deployments: - DUP for metadata (-m dup) - enabled no-holes (-O no-holes) - enabled free-space-tree (-R free-space-tree)
-m dup
の記述があるのがわかる。
- DUP for metadata **(-m dup)**
RAIDは上記のことを踏まえた上で、指定して使う必要がある。
私はRAIDに愛情が全く無いのでこれ以上は調べてない。
btrfs の特徴
Btrfs には従来のExt2などと違う特徴を持ってる。
- 遅延書き込み
- 自動デフラグ
- 自動圧縮
- 重複排除
自動圧縮・自動デフラグ・遅延書込についてはマウントのオプションで指定する。
重複排除
重複排除 はbtrfs の特徴である。MacのAPFSも同じ特徴を備えている。
ただし、Btrfsではコピー時重複排除がメインで、CoW ( copy on write )の機能がある。
btrfsでは重複排除だからといって、同じファイルを別名で作成した場合は重複排除はされない。(この機能は、将来の夢であり、プラグインをインストールすると使えるらしい。)
cp --reflink
明示的にCoW を有効にするなら
cp --reflink=always
上記のようにオプションをつけないとreflink が生成されない。それをしない限りに置いてはCoWはうまく動作しないと思われる。
また、重複排除はdupremove
コマンドをを用いて重複ファイルをreflink へ変更する必要があり、こちらもマニュアルで動かすので、重複排除はあまり期待してはいけない。
commit 指定(遅延書き込み)
遅延書き込みについては参考資料
これはext4 と同じ。
LABEL=my / ext4 defaults,discard,errors=remount-ro,commit=300 0 1 LABEL=s0 / btrfs defaults,discard,errors=remount-ro,commit=300 0 1
commit 間隔はデフォルト30秒なので、それ以上に間隔を開けておけば、小さなファイルの見かけ上の速度向上はみられる。
SDカードなどは600秒とかにしておけば、書き込みタイミングをずらせるので寿命に寄与するかもしれない(そもそも、書込総量を減らしたり、無駄データを捨てたほうが圧倒的に寿命を長くするのだが、commitで書き込みをズラすと、更新箇所の上書き更新といった不要な書込みを減らせて寿命に寄与するかと)
自動圧縮( compress )
btrfs ではファイルを透過的に圧縮できる。ext4 にはこの機能がない。デフォルトはOFFである。
compress=zstd
zlib, lzo, zstd
の3つから選ぶ。
何でもかんでも圧縮するわけでもなく、ファイルの先頭だけで圧縮を試して、圧縮が効果が上がると判明したときだけ、圧縮が行われる。チェックを飛ばして全ファイルを圧縮するオプションcompress-force
もある。
compress-force=zstd
の、forceを使うと、速くなることがあるらしい
NTFSはすべて圧縮するので、compress-force の動作イメージに似ているかもしれない。
SDカードの場合は、このCompressオプションで圧縮してやると、データ総量が抑えられるので、SD寿命の延命に寄与することだろう。
自動デフラグ (autodefrag)
defaults,autodefrag
ただし、自動デフラグは無限ループになる可能性があり非推奨らしい
リサイズ
XFSは、容量の縮小ができない、なので不採用です。btrfsではどうなのでしょうか。
btrfsでもリサイズはサポートされています。ext4同じように扱えます。
マウントした状態で扱います。
# 1G にする sudo btrfs filesystem resize 1G /mnt # +5M にする sudo btrfs filesystem resize +5M /mnt # -15Mする sudo btrfs filesystem resize -15M /mnt
このようにファイルシステムの実サイズを扱えるため、別途容量が必要になっても対応できます。
冒頭でXFSをDisりましたが、縮小ってあんまり使わない。容量が小さい別ディスクにコピーするときで事前に容量を揃えられない程度の問題で、実は必要ないんですよね。XFSが割り切った縮小って、なくても問題ないんですよね。縮小ができないXFSで困るのは、小さいディスクにコピーしたときにUUIDが変わっちゃうことなんですよね。同じラベルをつけ直すのが手間というか。fstab書き換えが面倒というか。その点においてbtrfsでは困りません。良かったです。
btrfsでは制限があって。/dev/loop
のリサイズができない。
$ sudo mount sample.btrfs.img /mnt $ sudo btrfs filesystem resize -5M /mnt Resize device id 1 (/dev/loop10) from 128.00MiB to 123.00MiB ERROR: unable to resize '/mnt': Invalid argument
上記のように、ループバックデバイス経由で、イメージファイルを扱ってる場合は、リサイズができない。nbdではどうなのでしょうか。試してない。
lxd で btrfs を使うと
ubuntu にはLXD/LXCのコンテナが標準で入ってる。そのLXDのストレージにbtrfs や zfs使う事ができる。これらは共通のの機能があって、スナップショットが自動的作られるそうだ。
lxd を btrfs で使うと、次の機能が使える
- snapshots.expiry 全自動で削除
- snapshots.schedule 全自動スナップショット
- snapshots.pattern 自動生成の名前規則
ふぁーすごい
ただ、scrubが必要など、btrfs のLXDでは、トラブル多かったのでメインに採用するのは避けたい。といってもzfsは扱いにくいしエラー時のリカバリが大変だったのでそれはそれで使いづらい・・・個人的にはbtrfsかなぁ
man pages
マニュアルの呼び出しに、少し癖があって
man btrfs-filesystem man btrfs-send man btrfs-scrub
btrfsのサブコマンドをハイフンにしてマニュアルを確認できる。細かいオプションが掲載されてて便利。
オンラインで見たいときは https://btrfs.readthedocs.io/en/latest/ が便利。
filesystemの場合はここを見ると読みやすい。
気づいたこと
btrfs はソコソコ完成していて、ext4 と同じように使える。
LVMの機能もあるので、ext4+lvmと同等なのが改めて理解できた。
サブボリュームは、ディレクトリってのが面白かった。
send / receive でパイプ転送できるってのが良い。でもスナップショットしか転送できないっぽいのが困る。
それなりに安定してるし、機能を見ると、btrfsで十分じゃんって思ってしまった。
次にインストールするときに、採用してみたい。
そうえいば、ファイルシステムといえば速度比較だけど。速度に興味がないので言及してない。高速nvme時代に、速度を気にする必要性に疑問です。
btrfsの速度比較とか言ってもlvm有無で変わるので信用してはいけないね。 その速度比較してるファイルシステムはスナップショット取れるんですか?圧縮できるんですか?と煽りたくなるね。