従来のext4環境と比べると、Btrfsの構成は分かりにくいので、ここで一旦まとめておきます。
Birtfsのディレクトリ構造
現在は、同じ1つのディスクの中に、こういう構造がある状況です(@vmはまだ作成していませんが)。
[ 物理ディスク ]
└ Btrfsファイルシステム
├ @
├ @home
├ @lxd
└ @vm
作成した時点では、まだ見えてない内部構造です。それをマウントして見せている、というわけで、ここで初めてディレクトリと見えています。
/ ← @ をマウント
/home ← @home をマウント
/lxd ← @lxd をマウント
/vm ← @vm をマウント
| サブボリューム | マウント先(見える場所) |
|---|---|
@ | / |
@home | /home |
@lxd | /lxd や /var/... |
@vm | /vm |
普通のext4だと、/ と /home は単なる同じディレクトリに見えますが、Btrfsだともう少し細かく区別出来、柔軟に扱えます。
/だけスナップショット/homeはそのまま/lxdは無視
Timeshiftとの関係
Timeshift(Btrfsモード)は @ を丸ごとスナップショット、つまり下記のようになります。
/は戻る/home(=@home)は基本戻らない/lxdも巻き込まれない
よくあるのが、/home というディレクトリが存在してるという勘違いですが、/home は「マウントポイント」で中身は @homeです。つまり、@home は /home の中にあるわけではなく、同じ階層(Btrfsのルート)にあります。
コマンドで実際に確認
Btrfsのサブボリューム一覧は、次のコマンドで見られます。
sudo btrfs subvolume list /
これを実施すれば、次のように表示されます。
ID 256 path @
ID 257 path @home
ID 258 path @lxd
ちなみに、サブボリュームを作成したあとにfstabに登録していますが、これは下記のような、サブボリュームをどこにマウントするかの設定です。
UUID=xxx / btrfs subvol=@
UUID=xxx /home btrfs subvol=@home
ここまで作成した ルート直下(top level 5)のサブボリューム
このブログで、ここまで作成した主なサブボリュームは次のようになります。
@ → ルート (/)
@home → /home
@lxd → LXD用
@data-immich → Immichデータ
@data-tv → TVデータ
Timeshiftスナップショット
Timeshiftのスナップショットは、次のような形で保存されています。
timeshift-btrfs/snapshots/
├ 2026-03-30_11-52-52/@
├ 2026-03-30_12-45-45/@
├ 2026-03-30_14-12-03/@
├ 2026-03-30_22-21-24/@
└ 2026-03-30_23-40-09/@
つまり、@(ルート)のスナップショットを保存しているという状態です。
LXD本体構造(@lxd配下)
@lxd
└ storage-pools/
└ default/
LXD イメージ
images/
└ d6c39329...(イメージキャッシュ)
LXD コンテナ本体
containers/
├ lxd-base-minimal
├ lxd-base-docker
├ linkwarden
├ vaultwarden
├ outline
├ immich
└ tv
LXD コンテナスナップショット
containers-snapshots/
├ linkwarden/
│ └ inport
├ vaultwarden/
│ └ setup
├ outline/
│ └ before-setup
├ immich/
│ ├ before-setup
│ └ after-setup
└ tv/
└ mount
構造の全体像
Btrfs
├ @
├ @home
├ @lxd
│ └ storage-pools/default/
│ ├ images/
│ ├ containers/
│ └ containers-snapshots/
├ @data-immich
├ @data-tv
└ timeshift-btrfs/
└ snapshots/
subvolid=5とは何か
Btrfsファイルシステムにおいて、subvolid=5は、ファイルシステムのルート(最上位レベル)にあるデフォルトのサブボリューム(Root Subvolume)を指します。
イメージ
subvolid=5(ルート)
├ @
├ @home
├ @lxd
├ @data-immich
└ ...
なぜ5なのかというと、これは内部的に決まってる固定IDだからであり、「変更不可」「削除不可」「常に存在」といった属性があります。
したがって、下記コマンドを実施すれば全てが見えることになります。
sudo mount -o subvolid=5 /dev/sdX /mnt
ls /mnt
subvolid=5とtop level 5
Btrfsファイルシステムにおけるsubvolid=5とtop level 5は、どちらも「ファイルシステムのルート(最上位・根幹)」を指す言葉です。
具体的には以下の意味を持ちます。
1. subvolid=5
- 意味: ID番号が5であるサブボリューム。
- 詳細: Btrfsにおいて、ID 5は「ファイルシステム全体(ルート)の親」と定義されており、物理パーティションのトップレベルを指します。
- 使われる場面:
mountコマンドで特定のサブボリュームをマウントする際、どのサブボリュームをルートとしてマウントするかを指定するオプション(subvolid=5)として使用されます。
2. top level 5
- 意味: 上位(親)のサブボリュームのIDが5である。
- 詳細: 自分が属している(ネストされている)親のサブボリュームIDです。
- 使われる場面:
btrfs subvolume listコマンドの結果などで、サブボリュームの階層構造を示す際に表示されます。top level 5とあれば、そのサブボリュームはファイルシステムの最上位直下に作成されたものであることを意味します。
・ID 5 は、Btrfsにおける特別な「デフォルトのルート」のID。
・subvolid=5 は「ID 5のサブボリュームをマウントする」こと。
・top level 5 は「ID 5(ルート)の中にいる」こと。
通常、Subvolid 5はサブボリュームのネスト(入れ子)構造をフラットに管理するための基準点として扱われます。
NOCOW(Copy-on-Writeを無効化)の設定
Btrfsではその仕組み上、大きな単一ファイルの内部を書き換えているような動作をするものに対してはパフォーマンスが大きく低下します。VMのイメージなどがそれです。そういったファイルを保存する可能性があるディレクトリに対しては、NOCOW(Copy-on-Writeを無効化)を設定しておけば、Btrfsの保護機能が無効になります。設定は、chattr コマンドで属性 +C を付与します。
sudo chattr +C /path/to/directory
注意点は下記です。
- 「空」の状態で設定する:
NOCOWは、ディレクトリが空のとき、またはファイルを作成する直前に設定する必要があります。すでにファイルが存在する場合、その既存ファイルには効果がありません(中身を一度消すか、別の場所に移動してから設定し、戻す必要があります)。 - 圧縮が無効になる:
NOCOWを設定したファイルやディレクトリでは、Btrfsの圧縮機能(zstdなど)は使えません。 - チェックサムが無効になる:
データ破損を検知するチェックサム機能も無効になるため、データベース(MySQL/PostgreSQL)や仮想マシンイメージ(LXD, Libvirt)など、独自の書き込み管理を持つデータ以外への多用はおすすめしません。
設定を確認する方法
lsattr コマンドで確認できます。C という文字が表示されれば設定済みです。
lsattr -d /path/to/directory
# 表示例: ---------------C------- /path/to/directory
注意点
スナップショットを作成する瞬間の時間については、NOCOW設定の有無で変わることはなく、一瞬(数秒以内)で終わります。Btrfsのスナップショット作成は「その瞬間のデータの配置図(メタデータ)」をコピーするだけなので、中身がNOCOW属性であっても、ファイルサイズが数TBあっても、作成自体の負荷はほぼゼロです。ただし、「その後の運用」において2つの影響が出る可能性があります。
1. 「スナップショット作成後」の書き込みが重くなる
NOCOW(Copy-on-Writeをしない)と設定していても、スナップショットが存在する間だけは、Btrfsの仕組み上強制的にCoW(コピーオンライト)が発生します。通常、NOCOWファイルは上書き保存されます。しかしスナップショット(過去のデータ)がある状態だと、元のデータを壊さないように「別の場所に書いてからリンクを張り替える(CoW)」動作になります。このため、仮想マシンやDBなど頻繁に書き換えが発生するファイルでは、スナップショットがある間だけディスクI/Oの負荷が上がります。
2. ファイルの断片化(フラグメンテーション)が進む
NOCOW設定は本来「断片化を防ぐ」ためのものですが、スナップショットがあるせいでCoWが発生すると、ファイルがバラバラのブロックに保存されるようになります。スナップショットを頻繁に撮る運用だと、NOCOWのメリット(パフォーマンス維持)が打ち消されてしまいます。
ここで重要になるのが、ルートと同じ階層に作成したサブボリュームです(@lxdや@vmなど)。これらがTimeshiftのスナップショット対象に含まれていなければ、CoW(コピーオンライト)は発生しません。NOCOW属性が設定されたファイルに対してCoWが発生する唯一の条件は、「そのファイルが含まれるサブボリュームのスナップショットが存在すること」です。独立したサブボリューム(@vmなど)の場合、たとえ/opt/vmなどにマウントしていたとしても、Btrfsのスナップショットはサブボリューム単位で作成されるので、もしTimeshiftが @(ルート)や @home のスナップショットだけを撮っており、@vm のスナップショットを撮っていなければ、@vm 内のファイルには「過去の版(参照先)」が存在しません。NOCOWの効果:スナップショットが存在しない状態であれば、NOCOW属性が有効なファイルへの書き込みは、常に同じディスク上のブロックに上書き(In-place update)されます。これにより、CoWによる断片化やオーバーヘッドを完全に回避できます。
作成したサブボリュームを削除する
作成したサブボリュームを削除するには次のようなコマンドを使用します。
sudo btrfs subvolume delete /path/to/subvolume
深い階層から順番に削除すれば、依存関係を壊さずに削除できます。
なお、ここで作成したような@lxdを削除するには一度マウントが必要になりまうs。Ubuntuなどの標準構成では、Btrfsの最上位(ID 5)は直接マウントされず、@ や @home だけがマウントされるよう設定されていることが多いため、以下の手順で最上位を一時的にマウントしてから削除する必要があります。
作業用ディレクトリを作成してマウントする
sudo mkdir /mnt/btrfs_top
sudo mount /dev/nvme0n1p2 /mnt/btrfs_top # ※デバイス名は実際の環境(/dev/sda2等)に合わせてください
マウントしたパス経由で削除する
# 深い階層から順に(一例)
sudo btrfs subvolume delete /mnt/btrfs_top/@lxd/storage-pools/default/images/d6c39329………
sudo btrfs subvolume delete /mnt/btrfs_top/@lxd/storage-pools/default/containers/calendar
sudo btrfs subvolume delete /mnt/btrfs_top/@lxd/storage-pools/default
sudo btrfs subvolume delete /mnt/btrfs_top/@lxd
マウント解除と作業フォルダの削除
sudo umount /mnt/btrfs_top
sudo rmdir /mnt/btrfs_top
Ubuntu 26.10以降の懸念点
Ubuntu 26.10では、セキュアブート時のセキュリティ強化を目的として、デジタル署名されたGRUBからBtrfs、XFS、ZFS、LVM、LUKS(暗号化)のサポートを削除する計画が提案されています。これにより、これらを利用した「/bootパーティション」からの起動ができなくなる可能性があります。
- 影響範囲: UEFIセキュアブートモード使用時。
- 理由: GRUBの脆弱性が多く、セキュリティ上のリスクがあるため。
- 対策(提案):
/bootパーティションはext4を使用する、またはUEFIセキュアブートを無効にする。
この提案が確定すれば、Ubuntu 26.10以降ではBtrfsを/(ルート)に採用している場合、ブートローダーの構成を変更する必要があるかもしれません。
UEFIセキュアブートを使用しなければ良いだけなので個人用途ですぐに大きな問題になる可能性は低いですが、将来性を考えた時に悩ましいところではあります。


