btrfs、LUKS、swapfile:如何在交换文件上休眠?

btrfs、LUKS、swapfile:如何在交换文件上休眠?

我在 fedora 32 silverblue 上使用由 LUKS 加密的 btrfs,内核版本 5.7.7,使用 anaconda 安装程序默认设置。

因为 fedora 安装程序自动分区没有添加交换分区或文件(或者我做错了),所以我自己添加了交换文件用于休眠,如下所示:

$ # swapfile under /var directory because the location is the only part user can modify on fedora silverblue
$ touch /var/swapfile
$ chattr +C /var/swapfile 
$ fallocate --length 10GiB /var/swapfile
$ sudo chown root /var/swapfile 
$ sudo chmod 600 /var/swapfile 
$ sudo mkswap /var/swapfile 
$ sudo swapon /var/swapfile

并且我swapfile_t为 selinux 添加了 attr:

$ ls -Z /var/swapfile
unconfined_u:object_r:swapfile_t:s0 /var/swapfile

然后我按照 arch wiki 说明进行操作(https://wiki.archlinux.org/index.php/Power_management/Sus​​pend_and_hibernate#Hibernation_into_swap_file_on_Btrfs)。

/var/swapfile的物理偏移量是19793240064,页面大小是4096,所以我用grub添加了内核参数。这是我/etc/default/grub现在的内核参数的一部分:

GRUB_CMDLINE_LINUX="rd.luks.uuid=luks-572bfd87-6fa7-4be1-8c73-4759ac9af3cd rhgb quiet resume=UUID=572bfd87-6fa7-4be1-8c73-4759ac9af3cd resume_offset=4832334"

这是我的 blkid:

$ sudo blkid
/dev/nvme0n1p1: UUID="5490-E733" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="46ecd0d1-6722-4b92-af73-9574a58eb332"
/dev/nvme0n1p2: UUID="c9294f4d-9c92-4c08-a037-715223443f2b" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="731852d5-26cd-43bb-8904-c4256247f97d"
/dev/nvme0n1p3: UUID="572bfd87-6fa7-4be1-8c73-4759ac9af3cd" TYPE="crypto_LUKS" PARTUUID="e74de89a-fe5f-402f-a3bf-e398ad069b5b"
/dev/sda: BLOCK_SIZE="512" UUID="C602B4D602B4CD25" TYPE="ntfs"
/dev/mapper/luks-572bfd87-6fa7-4be1-8c73-4759ac9af3cd: LABEL="fedora_fedora" UUID="337b2fcb-a61b-4976-89ac-2b3feee02963" UUID_SUB="932cfe1c-9713-4063-bda0-a8a792654c39" BLOCK_SIZE="4096" TYPE="btrfs"

并且休眠失败。似乎是恢复参数问题。我尝试了UUID=572bfd87-6fa7-4be1-8c73-4759ac9af3cd,但UUID=337b2fcb-a61b-4976-89ac-2b3feee02963都失败了。哪里出了问题?如何正确设置交换文件休眠?

我已检查journalctl -u systemd-logind并找到了该消息,但这没有帮助:

...
 localhost.localdomain systemd-logind[936]: Failed to open swap file /var/swapfile to determine on-disk offset: Permission denied
...

答案1

以下步骤使 Hibernate 能够在 Fedora Silverblue 33 上使用 btrfs 文件系统(可能使用 LUKS 加密)交换文件。不幸的是,这不是很简单,但它确实有效。

注意安全启动必须禁用休眠功能才能工作。检查 BIOS 设置是否已禁用。

有关更多背景信息以及为什么休眠功能无法立即使用,请参阅旧 Fedora Workstation 维基页面

  1. 创建并配置与系统内存大小相同的交换文件
sudo touch /var/swapfile
sudo chattr +C /var/swapfile
sudo fallocate --length "$(grep MemTotal /proc/meminfo | awk '{print $2 * 1024}')" /var/swapfile
sudo chmod 600 /var/swapfile
sudo mkswap /var/swapfile
sudo swapon /var/swapfile
echo '/var/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  1. 设置resume内核参数。
    首先我们需要计算抵消交换文件。以下命令使用btrfs_map_physical.cArch Linux 中描述的程序有关电源管理的 wiki 页面
sudo podman run --rm -it --privileged -v /var/swapfile:/var/swapfile -v /tmp:/tmp debian:stable sh -c '
  apt-get update &&
  apt-get install -qy gcc wget &&
  wget "https://raw.githubusercontent.com/osandov/osandov-linux/61679ecd914d653bab14d0e752595e86b9f50513/scripts/btrfs_map_physical.c" &&
  gcc -O2 -o btrfs_map_physical btrfs_map_physical.c &&
  ./btrfs_map_physical /var/swapfile | sed -n "2p" | awk "{print \$NF}" >/tmp/swap_physical_offset
  '
SWAP_PHYSICAL_OFFSET=$(cat /tmp/swap_physical_offset)
SWAP_OFFSET=$(echo "${SWAP_PHYSICAL_OFFSET} / $(getconf PAGESIZE)" | bc)

然后我们构建实际的内核参数并将其打印到屏幕上。

SWAP_UUID=$(findmnt -no UUID -T /var/swapfile)
RESUME_ARGS="resume=UUID=${SWAP_UUID} resume_offset=${SWAP_OFFSET}"
echo "${RESUME_ARGS}"

⚠ 确保输出与此类似,只是 UUID 和偏移量不同:

简历=UUID=3d2b6777-0114-4a9d-8b98-e279e7e09cda 简历偏移量=7753110

如果输出正确,请使用以下命令设置内核参数邋遢的

sudo grubby --update-kernel=ALL --args="${RESUME_ARGS}"
  1. 禁用 systemd 交换空间检查。
    如果已经存在交换目标(例如默认的 zram 设备),则为了避免有关交换大小的误报 systemd 错误。
sudo mkdir -p /etc/systemd/system/systemd-logind.service.d/
cat <<-EOF | sudo tee /etc/systemd/system/systemd-logind.service.d/override.conf
[Service]
Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1
EOF
sudo mkdir -p /etc/systemd/system/systemd-hibernate.service.d/
cat <<-EOF | sudo tee /etc/systemd/system/systemd-hibernate.service.d/override.conf
[Service]
Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1
EOF
  1. SELinux:允许 systemd 访问交换文件。
    这是 Fedora 的“selinux-policy”中缺少规则的解决方法(请参阅12),并将在未来的 3.14.7 版本中修复。
cd "$(mktemp -dt)"
cat <<-EOF | tee systemd_swapfile.te
module systemd_swapfile 1.0;

require {
    type init_t;
    type swapfile_t;
    class file { open getattr read ioctl lock };
}

allow init_t swapfile_t:file { open getattr read ioctl lock };
EOF
checkmodule -M -m -o systemd_swapfile.mod systemd_swapfile.te
semodule_package -o systemd_swapfile.pp -m systemd_swapfile.mod
sudo semodule -i systemd_swapfile.pp
cd -
  1. 重新启动并测试休眠。
    首次重启以应用所有设置:
systemctl reboot

然后尝试休眠:

systemctl hibernate

答案2

发帖者缺少的步骤是找到包含交换文件的分区的 UUID,以便选择交换文件所在的分区。可以使用以下命令检索findmnt

sudo findmnt -no SOURCE,UUID -T /path/to/swapfile

已发布了多种在交换文件上休眠的方法,每种方法在其目标环境中均有效。以下是一些参考资料,但您可以在帖子上方的评论中找到更多信息:

相关内容