From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id qF9pNJO1ImFz3AAAgWs5BA (envelope-from ) for ; Sun, 22 Aug 2021 22:37:39 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id sHQjMJO1ImH5GwAA1q6Kng (envelope-from ) for ; Sun, 22 Aug 2021 20:37:39 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 74F9A1AB42 for ; Sun, 22 Aug 2021 22:37:39 +0200 (CEST) Received: from localhost ([::1]:56736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mHuDq-0006Ag-0u for larch@yhetil.org; Sun, 22 Aug 2021 16:37:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46444) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mHuDQ-0005sk-P4 for guix-devel@gnu.org; Sun, 22 Aug 2021 16:37:12 -0400 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:52341) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mHuDO-00039w-1x for guix-devel@gnu.org; Sun, 22 Aug 2021 16:37:12 -0400 Received: (Authenticated sender: brice@waegenei.re) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 640E01C0003 for ; Sun, 22 Aug 2021 20:37:03 +0000 (UTC) From: Brice Waegeneire To: guix-devel@gnu.org Subject: Using a swapfile on btrfs for hibernation Date: Sun, 22 Aug 2021 22:36:55 +0200 Message-ID: <87zgt9nrmg.fsf@waegenei.re> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Received-SPF: pass client-ip=217.70.183.197; envelope-from=brice@waegenei.re; helo=relay5-d.mail.gandi.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guix-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+larch=yhetil.org@gnu.org Sender: "Guix-devel" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1629664659; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=sbgLStL/+clLJcRC66ONNYrhXkOlnJsrJLp+fxlGW4A=; b=WkeTktex33F/6glcwZMVdRaH6BSzqRp2QzQNpWbUGZomm5/o/DIn3dtYnYbHOib7ARlAui +PgVLBvh6+irGgh/igoSRI7e9QEI9LISDkJpd4qJeZU+m8ZMnchOpJ0Rpf3hhPLqdzXj79 EQaVQFQdPGfrx/5gAe7Er4EEqEP7GN3dkXH6qNlMGZsiTVmsegxc+fCK6p/MRBY2PRo0pL TUPwoUallxYbJ3TTtBbjt/BfJJu2eJmE8XVlHWaoKFOEdGEtmM5DoxzUvlfP6oag+txIML ymYV5oNEoQaNr10e/NpTXkXhP+a13y9VSTGEr1TLytQaDian33Xr241svutVfg== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1629664659; a=rsa-sha256; cv=none; b=BJxBR3B9P9CsDXOn8kgfTArzJaSSLtaoEhaSoODDp7T9CCeG6xAIgf2BFjY0rB1Po2J+vJ 8AH59a5zVhehY5oNz5UmSDDW+1NmJGZH2vgWbCT810lQ1UbeR+vFZbqGEi3O7udLKssKo9 NIO8ggyDROQfQBPCn+wUKCfmT4Xk61pu1T1YDwta30Z1mBrCDw9Ze0/3MrN9StnKM44Sx9 9gZhBdIP2saoAVJHJmX6TqwPcdG/XfanYpgS9/NAVUjZ/TkjDoAichAiBeGxqSX7nJtYrr 8VrdAhAgM9f1BYPhPFNtt8p5fqTOQANi4NtpKEKYjVxN2HSsNpoQuJTf7ZZstQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; spf=pass (aspmx1.migadu.com: domain of guix-devel-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-devel-bounces@gnu.org X-Migadu-Spam-Score: -2.43 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of guix-devel-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-devel-bounces@gnu.org X-Migadu-Queue-Id: 74F9A1AB42 X-Spam-Score: -2.43 X-Migadu-Scanner: scn0.migadu.com X-TUID: qJ95xtdoSahA Hello Guix! Here is a feedback on enabling hibernation using a swapfile stored on btrfs filesystem. It wasn 't straight forward as it's not documented and I had to read the code do make it work. Note that even tho swpafile on btrfs filesystem are supported, therea are some limitations=E2=81=B5: - the filesystem must be an a single device, ie. no btrfs RAID, - the swapfile shouldn't be copy-on-write, - the swapfile shouldn't be compressed. Let's start with the btrfs specific part first. The following instructions was compiled from tutorials=C2=B9 =C2=B2 =C2=B3 for other Linux distributio= ns. First we gather the tools we'll need for the job, especially btrfs_map_physical=E2= =81=B4to find the offset from the start of the btrfs partition where the swapfile is located, this tool isn't packaged (I don't know if it should) so we'll build it in the old fashion way. --8<---------------cut here---------------start------------->8--- guix environment --ad-hoc gcc-toolchain curl gawk e2fsprogs btrfs-progs curl -OL https://github.com/osandov/osandov-linux/raw/master/scripts/btrfs_= map_physical.c gcc -O2 -o ./btrfs_map_physical ./btrfs_map_physical.c --8<---------------cut here---------------end--------------->8--- Next we create our swapfile in its own subvolume named =E2=80=9Cswap=E2=80= =9D on the btrfs filesystem of device =E2=80=9C/dev/sda2=E2=80=9D (mounted at =E2=80=9C/mnt/= rootfs=E2=80=9D) and we make sure our new swapfile isn't COWable nor compressed. To be able to hibernate in all cironstancese the swapfile need to be at least as big as the total RAM available. --8<---------------cut here---------------start------------->8--- swappath=3D/mnt/rootfs/swap swapfile=3D"$swappath/swapfile" cd "$path" btrfs subvolume create swap mount -o subvol=3Dswap /dev/sda2 ./swap truncate -s 0 "$swapfile" chattr +C "$swapfile" btrfs property set "$swapfile" compression none swap_size=3D"$(grep MemTotal /proc/meminfo | awk '{print $2 * 1024}')" fallocate --length "$swap_size" "$swapfile" chmod 600 "$swapfile" mkswap "$swapfile" --8<---------------cut here---------------end--------------->8--- As we have a working swapfile, we'll genereate the kernel arguments to pass to the kernel. The less obvious being the offset of the swapfile from the start of the filesystem, to do so we are using the previously compiled =E2=80=9Cbtrfs_map_physical=E2=80=9D binary and few shell utilities. --8<---------------cut here---------------start------------->8--- swapon "$swapfile" swap_physical_offset=3D$(btrfs_map_physical "$swapfile" | sed -n "2p" | awk= "{print \$NF}") swap_offset=3D$(echo "${swap_physical_offset} / $(getconf PAGESIZE)" | bc) swap_uuid=3D$(findmnt -no UUID -T "$swapfile") resume_args=3D"resume=3D${swap_uuid} resume_offset=3D${swap_offset}" echo "${resume_args}" --8<---------------cut here---------------end--------------->8--- What's left is just to tweak our =E2=80=9Coperating-system=E2=80=9D to make= use of ourr new swapfile. --8<---------------cut here---------------start------------->8--- (operating-system (file-systems (cons* ... (file-system (mount-point "/") (device (uuid "12345678-1234-1234-1234-123456789abc" 'btrfs)) (type "btrfs") (options "compress=3Dzstd,subvol=3Dguix-system")) (file-system (mount-point "/swap") (device (uuid "12345678-1234-1234-1234-123456789abc" 'btrfs)) (type "btrfs") ;; Needed to access the swapfile? (not sure) (needed-for-boot? #t) (options "subvol=3Dswap")) %base-file-systems)) (swap-devices (list "/swap/swapfile")) (kernel-arguments (cons* "resume=3D"12345678-1234-1234-1234-123456789abc" "resume_offset=3D16400" %default-kernel-arguments)) ...) --8<---------------cut here---------------end--------------->8--- Now we can reconfigure our system and reboot it. At that point we are able to use =E2=80=9Cloginctl hibernate=E2=80=9D or =E2=80=9Cloginctl hybrid-sle= ep=E2=80=9D to save our current system state to the swapfile and recover it at the next reboot. As a keen reader may have noticed, enabling hibernation in Guix in this case has a quirk. The most the most inconvenient is the Guix's =E2=80=9Cre= sume=E2=80=9D kernel argument format being different from Linux's=E2=81=B6 =C2=AB {/dev/<= dev> | PARTUUID=3D | : | } =C2=BB and other distributions all= owing =C2=AB UUID=3D =C2=BB; in Guix the uuid isn't prefixed with =E2=80=9CUUID=3D= =E2=80=9D or =E2=80=9CPARTUUID=3D=E2=80=9D and this isn't documented anywhere, you are forced to read the code. Also, having swap related configuration spread between =E2=80=9Cswap-device= s=E2=80=9D and =E2=80=9Ckernel-arguments=E2=80=9D fields make me think having specific rec= ords for that first field would make sense. And that would make the =E2=80=9Cresume=E2=80= =9C format issue irrelevant. WDYT about adding the following records to be used in =E2=80=9Cswap-devices=E2=80=9D record in addition to the current types? --8<---------------cut here---------------start------------->8--- (swap-file (file "/swap/swapfile") (offset 16400) (device (uuid "12345678-1234-1234-1234-123456789abc")) (resume? #t) ; default #f (priority 21)) ; swapflags argument passed to swapon(2), default 0 (swap-device (device "/dev/sda3") ; any of the usual types allowed in 'swap-devices' (resume? #t) ; default #f (priority 42)) ; swapflags argument passed to swapon(2), default 0 --8<---------------cut here---------------end--------------->8--- I wasn't sure were this documentation should go in Guix, except for the btrfs instrructions which will probably end up in the cookbook. =C2=B9 https://wiki.archlinux.org/title/btrfs#Swap_file =C2=B2 https://superuser.com/a/1613639 =C2=B3 https://wiki.archlinux.org/title/Power_management/Suspend_and_hibern= ate#Hibernation_into_swap_file_on_Btrfs =E2=81=B4https://github.com/osandov/osandov-linux/blob/master/scripts/btrfs= _map_physical.c =E2=81=B5 https://btrfs.wiki.kernel.org/index.php/FAQ#Does_Btrfs_support_sw= ap_files.3F =E2=81=B6 https://www.kernel.org/doc/html/latest/admin-guide/kernel-paramet= ers.html Cheers, - Brice