SDB:BTRFS

移動先: 案内, 検索

テンプレート:SDB navbar

このページでは、 openSUSE Leap, openSUSE Tumbleweed, openSUSE Kubic の各プロジェクトで既定のファイルシステムになっている btrfs について、その主要な調査方法と修復方法を説明しています。

既定のサブボリューム

既定では、 openSUSE は btrfs とルートパーティションに対するスナップショットを設定します。スナップショットは、何らかの更新を適用した後で元の状態に戻したり、ファイルをバックアップしたりする目的で使用します。スナップショットは Snapper を利用することで、簡単に管理することができます。

スナップショットをシステムのロールバック (巻き戻し) として使用する場合、ユーザのホームディレクトリや Web サーバ, FTP サーバのコンテンツ、各種のログファイルなどが巻き戻ってしまわないようにするため、配慮が必要です。この配慮はルートファイルシステム内で個別の btrfs サブボリュームを設定することで実現しています。既定では、サブボリュームはスナップショットから除外されるようになっています。 openSUSE では、 YaST を利用してインストールする際、下記のサブボリュームをルートファイルシステムに対して提案します。これらはそれぞれ下記に示す理由によって、スナップショットから除外されます。

   /boot/grub2/i386-pc, /boot/grub2/x86_64-efi, /boot/grub2/powerpc-ieee1275, /boot/grub2/s390x-emu

ブートローダ設定のロールバックには対応していないためです。上記のディレクトリはアーキテクチャごとにそれぞれ用意されているもので、はじめの 2 つは AMD64/Intel 64 マシン用、残りの 2 つは IBM POWER, IBM z システム用に用意されるものです。

   /home

/home に個別のパーティションを指定しない場合、ロールバックでデータが戻ってしまったりしないようにするため、個別のサブボリュームを設定します。

   /opt

サードパーティ製の製品は、通常 /opt 以下にインストールされます。ロールバックでこれらの製品が消えてしまわないようにするため、除外を設定します。

   /root

root ユーザのホームディレクトリについても、ロールバックでデータが戻ってしまわないようにしています。

   /srv

Web/FTP サーバのデータが含まれています。これらもロールバックでデータが戻ってしまわないようにしています。

   /tmp

一時ファイルやキャッシュについても、スナップショットからは除外しています。

   /usr/local

このディレクトリは、手作業でソフトウエアをインストールする際に使用するディレクトリです。このディレクトリについても、ロールバックでアンインストールされてしまわないように除外されます。

   /var

このディレクトリ以下には様々な目的でファイルが作成されます。ログファイルや一時的なキャッシュのほか、サードパーティ製の製品は /var/opt 内に何かを書き込むことがあります。また、多数の仮想マシンソフトウエアのイメージやデータベースなども、このディレクトリが既定の配置場所になっています。そのため、このディレクトリは様々なデータ損失を防ぐため、スナップショットから除外されるほか、 Copy-On-Write 機能も無効化されます。

古い /var/* サブボリュームの配置 (2018/01以前)

古い SUSE/openSUSE ディストリビューション (SLE 12/Leap 42.x/2018年1月以前の Tumbleweed) では、 /var をルートファイルシステムの一部となるよう btrfs のサブボリュームを構成していました。その代わり、それぞれ下記のディレクトリに対して別途のサブボリュームを作成していました:

   /var/opt

サードパーティ製の製品は通常、 /opt 以下にインストールされます。これらの製品に属するアプリケーションの情報は、このディレクトリ内に配置されるのが一般的であるため、このディレクトリを除外しています。

   /var/tmp, /var/cache, /var/crash

一時ファイルやキャッシュを含む全てのディレクトリを、スナップショットから除外しています。

   /var/lib/libvirt/images

libvirt で管理される仮想マシンのイメージは、既定でこのディレクトリに配置されます。ロールバックの際、仮想マシンのイメージが古いものに戻ってしまわないようにするため、このような除外を設定しています。また、既定ではこのサブボリュームを copy on write 無しで作成します。

   /var/lib/mailman, /var/spool

メールファイルやメールキューなどについても、ロールバック時にメールを喪失してしまわないようにするため、除外しています。

   /var/lib/named

DNS サーバのゾーンデータが含まれるディレクトリです。ロールバック時にネームサーバがスナップショットから除外されるようにするため、このサブボリュームを作成しています。

   /var/lib/mariadb, /var/lib/mysql, /var/lib/pgqsl

これらのディレクトリにはデータベースのデータが含まれます。既定では、これらのサブボリュームは copy on write 無しで作成されます。

   /var/log

ログファイルの配置場所です。システムを壊してしまったような場合に、ロールバックでログファイルが元に戻ってしまわないようにするため、このように除外を設定しています。


圧縮型 btrfs ファイルシステム

Leap と Tumbleweed では、 btrfs ファイルシステムの圧縮に対応しています。オプションとして compress または compress-force を指定し、圧縮アルゴリズム (lzo もしくは zlib (既定値)) を選択してください。 zlib 圧縮は圧縮率に優れ、 lzo は処理の高速性と CPU 負荷の少なさに優れています。 例:

   mount -o compress /dev/sdx /mnt

ファイルを作成して内容を書き込んだ際、圧縮結果が圧縮前より大きいか同じであった場合、 btrfs はそのファイルに対して恒久的に圧縮を行なわないように設定します。このような動作をしたくない場合は、 compress-force オプションを指定してください。このオプションは、最初に圧縮しにくいデータを書き込むような場合に有効です。

なお、圧縮は新しく作成するファイルに対してのみ実施されます。圧縮せずに書き込まれたファイルは、ファイルシステムを compress や compress-force オプションを指定してマウントし直しても、圧縮されることはありません。これに加えて、 nodatacow 属性が指定されたファイルは、圧縮から除外されます:

   chattr +C FILE
   mount -o nodatacow  /dev/sdx /mnt

暗号化は圧縮と全く独立して動作する仕組みです。暗号化と圧縮を指定したパーティションにデータを書き込むと、たとえば下記のようになります:

   btrfs filesystem show /mnt
   btrfs filesystem show /mnt
   Label: 'Test-Btrfs'  uuid: 62f0c378-e93e-4aa1-9532-93c6b780749d
           Total devices 1 FS bytes used 3.22MiB
         devid    1 size 2.00GiB used 240.62MiB path /dev/sdb1

このような動作を恒久的に実施したい場合は、 /etc/fstab 設定ファイル内に compress もしくは compress-force オプションを追加してください。たとえば下記のようになります:

   UUID=1a2b3c4d /home btrfs subvol=@/home,compress 0 0

空き容量の確認

ファイルシステムの使用率は、通常 df コマンドを利用して確認します。 btrfs ファイルシステムでは、実際のデータ領域に加えてメタデータに対しても領域を割り当てるため、 df の出力が正確には表示できません。

また、 btrfs ファイルシステムでは、まだそれなりに容量が残っているにもかかわらず、容量不足になってしまう場合もあります。これはメタデータ向けの領域がいっぱいになっているために発生する現象で、それぞれ下記のコマンドを実行することで空き容量と使用量を確認することができます:

btrfs filesystem show

   sudo btrfs filesystem show /
   Label: 'ROOT'  uuid: 52011c5e-5711-42d8-8c50-718a005ec4b3
           Total devices 1 FS bytes used 10.02GiB
           devid    1 size 20.02GiB used 13.78GiB path /dev/sda3

ファイルシステムの全体サイズとその使用率を表示するコマンドです。最後の行には 2 つの値が示されていますが、この値が一致した時点でファイルシステムが満杯になったことを示します。

btrfs filesystem df

   sudo btrfs filesystem df /
   Data, single: total=13.00GiB, used=9.61GiB
   System, single: total=32.00MiB, used=16.00KiB
   Metadata, single: total=768.00MiB, used=421.36MiB
   GlobalReserve, single: total=144.00MiB, used=0.00B

ファイルシステムに対して、割り当て済みの (total) サイズと使用済みの (used) サイズをそれぞれ表示します。 total と used の値がほぼ等しくなると、メタデータ用の領域が満杯になったことを示します。

btrfs filesystem usage

   sudo btrfs filesystem usage /
   Overall:
       Device size:                  20.02GiB
       Device allocated:             13.78GiB
       Device unallocated:            6.24GiB
       Device missing:                  0.00B
       Used:                         10.02GiB
       Free (estimated):              9.63GiB      (min: 9.63GiB)
       Data ratio:                       1.00
       Metadata ratio:                   1.00
       Global reserve:              144.00MiB      (used: 0.00B)
                Data     Metadata  System
   Id Path      single   single    single   Unallocated
   -- --------- -------- --------- -------- -----------
    1 /dev/sda3 13.00GiB 768.00MiB 32.00MiB     6.24GiB
   -- --------- -------- --------- -------- -----------
      Total     13.00GiB 768.00MiB 32.00MiB     6.24GiB
      Used       9.61GiB 421.36MiB 16.00KiB

上記 2 つのコマンドの出力を両方組み合わせて表示するコマンドです。

詳しくは man 8 btrfs-filesystem および https://btrfs.wiki.kernel.org/index.php/FAQ をお読みください。


snapper を利用することによって disk full が発生する問題について

btrfs ファイルシステムに対して snapper を動作させた際、お使いのシステムのスナップショット内に大量のデータが保存されていることによって、 "No space left on device" (空き容量が不足している) という問題がよく発生します。 snapper を利用することでスナップショットを削除することもできますが、スナップ氏ヨットは即時に削除できるものではありませんし、場合によっては必要な容量を空けられない場合もあります。 snapper を利用してファイルを削除するには:

  • 端末 (ターミナルエミュレータ/コンソール) を開きます。
  • コマンドプロンプトから "btrfs filesystem show" と入力してコマンドを実行します:
sudo btrfs filesystem show
Label: none uuid: 40123456-cb2c-4678-8b3d-d014d1c78c78
 Total devices 1 FS bytes used 20.00GB
 devid 1 size 20.00GB used 20.00GB path /dev/sda3
  • 下記のように入力して実行します:
sudo btrfs fi balance start </mountpoint> -dusage=5

上記のコマンドは、空いているチャンクやほぼ空きのチャンクを再配置するコマンドで、メタデータの再生や再配置を行なうためのものです。指定したファイルシステムはそのまま使い続けられますが、処理に際しては長い時間 (1 TB あたり 10 時間以上) を要します。

  • snapper でスナップショットの一覧を表示します:
sudo snapper -c root list
  • snapper でスナップショットを削除します:
sudo snapper -c root delete (スナップショット番号)

なお、古いスナップショットから順に削除してください。古いスナップショットほど大きなディスク領域を占有しているためです。


壊れた/マウントできない btrfs の修復方法について

下記は btrfs ファイルシステムで重大な問題が発生した場合、特にマウントできなくなってしまった場合などに実施しておくべき手順を説明しています。 dmesg や syslog で記録されるログを読むことで、問題を修復するにあたって飛ばしても良い手順が分かる場合もありますが、 btrfs scrub は非常に安全な修復ツールとして利用できますので、下記の手順の冒頭部については、特に必ず実施しておくことをお勧めします。

  • まずは適切な代替システムを起動します。 Rescue システムを起動してもかまいませんし、 openSUSE を別途インストールしてある環境があれば、そこにディスクを接続してもかまいません。また、ライブメディアや openSUSE のインストール DVD 内にあるレスキューシステムでもよいでしょう。なお、インストール DVD にあるレスキューシステムは、同梱されインストールできる openSUSE と同じバージョンのカーネルや btrfs バージョンが利用できますので、こちらをお勧めします。また、 Tumbleweed のディスクには新しいバージョンのカーネルや btrfs が提供されていますので、こちらでもかまいません。
  • それぞれのシステムでコンソールを表示し、 root になります。
  • まずは /mnt 以下にパーティションをマウントしてみます。これはファイルシステムが本当に壊れているかどうかを確認する手段でもあります:
mount /dev/sda1 /mnt
  • マウントできる場合は、大きな破壊は起こっていないものと思われます。下記を実行して修復を実行します:
btrfs scrub start /mnt

下記を実行すると状況を確認することができます:

btrfs scrub status /mnt
  • マウントできない場合は、デバイスを直接指定して scrub を実行します:
btrfs scrub start /dev/sda1

同様に、下記を実行すると状況を確認することができます:

btrfs scrub status /dev/sda1

完了したらマウントをお試しください。マウントできれば完了となります。

  • scrub を実施したくない場合や、 scrub でも解決しない場合は、 -o usebackuproot を指定してマウントしてみてください:
mount -o usebackuproot /dev/sda1 /mnt
Process-stop.png
警告!
上述の手順は全てが安全な処理であり、ディスクに破壊的な変更を行なわないはずのものです。上記の手順でも問題が解決しない場合は、状況は深刻でバグ報告を実施すべきものである可能性があります。


  • "btrfs check <デバイス>" を実行します:
btrfs check /dev/sda1

これでも解決しない場合は、表示されたログをどこかに保存して、バグ報告に添付してください。

  • "btrfs restore <デバイス> <コピー先ディレクトリ>" を実行して、データを待避させることをご検討ください:
btrfs restore /dev/sda1 /mnt/usbdrive

この処理では問題を解決することはできませんが、ファイルシステム内を検索して、見つかったデータを全て特定のディレクトリに復元することができます。この処理は、たとえばハードウエア障害が発生していて、 btrfs 側の問題ではないような場合に特に有用です。

  • "btrfs rescue super-recover <デバイス>" を実行します:
btrfs rescue super-recover /dev/sda1

終わりましたら、再度通常の手順でマウントできないかどうかをご確認ください。マウントできた場合は、これ以降の手順を実施してはなりません。

  • さらに "btrfs rescue zero-log <デバイス>" を実行します:
btrfs rescue zero-log /dev/sda1

終わりましたら、再度通常の手順でマウントできないかどうかをご確認ください。マウントできた場合は、これ以降の手順を実施してはなりません。

  • さらに "btrfs rescue chunk-recover <デバイス>" を実行します:
btrfs rescue chunk-recover /dev/sda1"

上記の処理は非常に長い時間がかかります。終わりましたら、再度通常の手順でマウントできないかどうかをご確認ください。マウントできた場合は、これ以降の手順を実施してはなりません。

  • これまでの手順で実施していなかった場合は、 "btrfs restore <デバイス> <コピー先ディレクトリ>" を実行します:
btrfs restore /dev/sda1 /mnt/usbdrive
  • btrfs restore の実行に失敗した場合、ここから先に進むとデータ喪失の可能性が非常に高くなります。あらかじめ btrfs restore でできる限りのデータ救出を実施して進めてください。
Process-stop.png
警告!
上記の手順を実行すると、予期しない変更が加えられてしまう場合が、少しではありますが存在します。また、ここから先の手順は、さらに障害を引き起こしてしまう可能性が高いものです。実行にあたっては、データのほとんど (場合によっては全て) が失われる危険性をご承知おきください。


  • 最後の手段として、 "btrfs check --repair <デバイス>" を実行します:
btrfs check --repair /dev/sda1

参考情報

関連記事

外部リンク