BTRFS とカーネル 5.0.16-gentoo でスワップファイルを使用してハイバネーションを行う

BTRFS とカーネル 5.0.16-gentoo でスワップファイルを使用してハイバネーションを行う

ここで説明されているようにスワップ ファイルを作成しました:https://wiki.archlinux.org/index.php/Swap#スワップファイル作成

休止状態にしようとすると、次のエラーが発生します。

$ echo disk > /sys/power/state
echo: write error: no such device

また、dmesg では次のようになります:

[30721.352822] [drm] Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.
[30721.454735] acpi LNXPOWER:07: Turning OFF
[30721.454987] acpi LNXPOWER:02: Turning OFF
[30721.455365] acpi LNXPOWER:01: Turning OFF
[30721.455563] PM: Cannot find swap device, try swapon -a
[30721.455563] PM: Cannot get swap writer
[30721.553943] OOM killer enabled.
[30721.553944] Restarting tasks ... done.

記載の通りhttps://wiki.archlinux.org/index.php/Power_management/Sus​​pend_and_hibernate#Hibernation_into_swap_file、次のカーネルパラメータを設定しました。

resume=UUID=2bfb4ccd-6b80-4806-8a08-4f1e67ef035f
resume_offset=148378880

resume_offset と resume パラメータの値を取得する方法は次のとおりです。

$ filefrag -v /swapfile
Filesystem type is: 9123683e
File size of /swapfile is 536870912 (131072 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:  148378880.. 148378880:      1:            
   1:        1..  131071:  148378881.. 148509951: 131071:             last,unwritten,eof
$ findmnt -no SOURCE,UUID -T /swapfile
/dev/mapper/nvme0n1p2[/root] 2bfb4ccd-6b80-4806-8a08-4f1e67ef035f

を使用しようとするとswap_offset、次の問題が発生します。

$ swap-offset /swapfile 
ioctl(FIBMAP) failed: Invalid argument

では、BTRFS を使用している場合、休止状態にスワップファイルを使用することは可能ですか? カーネルはスワップ ファイルの修正場所を認識していないようです。

答え1

u/hジョーク (https://www.reddit.com/user/kjoke/) が私の一日を素晴らしいものにしてくれました:

filefrag は BTRFS のオフセットを誤って計算しますが、正しいオフセットを計算するスクリプトがあります。https://github.com/osandov/osandov-linux/blob/master/scripts/btrfs_map_physical.c

gcc btrfs_map_physical.c -o btrfs_map_physicalスワップ ファイルの最初の物理オフセットをダウンロードして取得します。

$ sudo ./btrfs-map-physical /swap | head -n2
FILE OFFSET EXTENT TYPE LOGICAL SIZE    LOGICAL OFFSET  PHYSICAL SIZE   DEVID   PHYSICAL OFFSET
0   regular 4096    607759892480    268435456   1   608833634304

ここでは608833634304: このオフセットをページ サイズで割ります:

$ getconf PAGESIZE
4096

つまり、resume_offsetです608833634304 / 4096 = 148641024。この値をresumeパラメータとともにカーネルパラメータとして追加し、再起動します。systemdsystemd hibernateはカーネルパラメータを無視し、オフセットを誤って計算するため、その後も失敗しますが、echo disk > /sys/power/state動作します。

関連情報