*nixで過ごす日々

PCでの作業に役立つ情報を提供するブログ

BtrfsルートのLinuxでスワップファイルを作成しハイブリッドスリープを設定する

タイトル通り
やることは2つ

  1. Btrfs上にスワップファイルを作成する
  2. ハイブリッドスリープ(=suspend to both)ができるよう設定する

内容的にはArchWikiの
Btrfs - ArchWiki
スワップ - ArchWiki
電源管理/サスペンドとハイバネート - ArchWiki
電源管理 - ArchWiki
をまとめただけ

スワップファイルの作成

まずはスワップファイルを作成する。
インストールしたシステムのfstabが次のようになっているとする。(一部簡略化している)

UUID=5F87-F434                            /boot/efi  vfat  umask=0077  0 2
UUID=26fe3206-88fa-4b31-8ef8-5a71ebad7054 /  btrfs subvol=/@,defaults  0 0

Btrfs上にスワップファイルを作るにはいくつか条件がある。
カーネル5.0以上、非圧縮、非スナップショット等。
非圧縮等の設定をするにはサブボリュームを作成するのが手っ取り早い。
その中にスワップファイルを作成する。
/のあるディスクが/dev/sda2とする。
スワップのサイズはメモリの1.5倍が良いとかあったりするが、ハイバネートするだけならメモリと同じサイズで良いんじゃないかって思う。
今回メモリは16GB。

# btrfs subvolume create /@swap
# mkdir /swap
# mount -o subvol=/@swap /dev/sda2 /swap
# cd /swap
# truncate -s 0 ./swapfile
# chattr +C ./swapfile
# btrfs property set ./swapfile compression none
# dd if=/dev/zero of=/swap/swapfile bs=1M count=16384
# chmod 600 /swap/swapfile
# mkswap /swap/swapfile
# swapon /swap/swapfile

fstabを編集してスワップファイルの設定は終わり

$ sudoedit /etc/fstab
UUID=5F87-F434                            /boot/efi vfat    umask=0077         0 2
UUID=26fe3206-88fa-4b31-8ef8-5a71ebad7054 /         btrfs   subvol=/@,defaults 0 0
UUID=26fe3206-88fa-4b31-8ef8-5a71ebad7054 /swap     btrfs   subvol=/@swap,defaults,noatime,noautodefrag,nodiscard 0 0
/swap/swapfile                            none      swap    defaults 0 0

ハイブリッドスリープの設定

次にハイブリッドスリープの設定をする。
ハイブリッドスリープはwindowsとかmacosとかのスリープの挙動と同じ感じのやつ。
いわゆるsuspend to both (ramとdiskの両方に書き込んでスリープする)。

ハイバネートの設定

ハイバネート(suspend to disk)の設定が必要だが、Btrfsは他のファイルシステムとは別の方法が必要。
btrfs_map_physical.cを使って物理オフセットを調べる。
適当な場所にDLしてビルドする。

$ gcc -O2 -o btrfs_map_physical btrfs_map_physical.c

実行する時はルートの権限が必要。

# ./btrfs_map_physical /swap/swapfile

以下のような出力が得られる。(実際は各値の区切りがタブ文字1つなので見辛い。)

FILE OFFSET   FILE SIZE   EXTENT OFFSET   EXTENT TYPE   LOGICAL SIZE   LOGICAL OFFSET   PHYSICAL SIZE   DEVID   PHYSICAL OFFSET
0             100663296   0               regular       100663296      9772998656       100663296       1       10855129088
100663296     134217728   0               regular       134217728      9873661952       134217728       1       10955792384
234881024     134217728   0               regular       134217728      10007879680      134217728       1       11090010112
369098752     134217728   0               regular       134217728      10142097408      134217728       1       11224227840
.
.
.

必要な値は1行目の右端の値のみ。ここでは10855129088
この値をページサイズの値で割る。
10855129088 / 4096 = 2650178
この2650178カーネルパラメータresume_offsetに設定する。
カーネルパラメータには他にもresumeスワップファイルがあるディスクを設定する必要があるので一緒に設定する。
以下はブートローダgrubの場合。

$ sudoedit /etc/default/grub
.
.
GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=UUID=26fe3206-88fa-4b31-8ef8-5a71ebad7054 resume_offset=2650178"
.
.

grubを使っている場合は設定を再生成する。

$ sudo grub-mkconfig -o /boot/grub/grub.cfg

サスペンドとハイバネートでハイブリッドスリープするようにする

スリープっぽいことをしようとしたらハイブリッドスリープをしてほしい場合は以下の設定をする。

$ sudoedit /etc/systemd/sleep.conf
[Sleep]
SuspendMode=suspend
SuspendState=disk
HibernateMode=suspend
HibernateState=disk

initramfsの設定

initramfsのフックでsystemdを使っていない時にresumeがないとサスペンドさせてもシャットダウンになってしまう。
/etc/mkinitcpio.confを確認し、なければ追加する。
filesystemsより前にないといけないらしい。

・
・
HOOKS="base udev autodetect modconf block resume filesystems keyboard fsck"
・
・

編集がおわったらinitramfsを再生成する。

$ sudo mkinitcpio -p linux

番外 (復帰後bluetoothがオフになるんだけど?)

bluetoothの設定のせい。

$ sudoedit /etc/bluetooth/main.conf
[Policy]
AutoEnable=true