As seen on https://twitter.com/nabijaczleweli/status/1378679960408371207 boot/vmlinuz-5.10.0-5-amd64 and boot/initrd.img-5.10.0-5-amd64-dracut are clean, from Debian boot/bzImage has a Long Sleep in swap_writer_finish(), boot/initrd.img-5.10.0-5-amd64 logs each txg it commits Boot the latter with 'verbose debug no_console_suspend boot=zfs', with a ZFS-on-root pool attached, make big enough zvol, mkswap and swapon it, run systemctl hibernate or equivalent, let 'er rip You should get "S0|0!" instead of the usual "S|", then "bdm"/"bdm done" during the waits. Sometimes an NMI happens thereduring and a backtrace is printed; you should get at least one (but likely a few) "4txg=..."s after "S0|0!" -- that's good Now boot with 'verbose debug no_console_suspend', you should get dropped down to an i-t shell prompt Now: modprobe zfs zpool import -aN -o readonly=on zfs load-key -a should get you the device node and a read-only pool. If at any point you write to the pool (like by importing it R/W), i.e. you see "4txg=..."s, stop trying to resume and boot normally, or you risk uncorrectable pool errors. Great, if you now resume /dev/zvol/pool/swap you should get a big load of shit that starts with "can't write to read-only device" and ends with "errno -5" or summat. This is good. If, instead, you get "no image found", this means there's no image header, 'hexdump -C /dev/zvol/pool/swap | head' should have S1SUSPEND in it; stop, boot normally. To actually resume this, you can modprobe zram zfs get -Hpo value disksize pool/swap > /sys/block/zram0/disksize dd if=/dev/zvol/pool/swap of=/dev/zram0 resume /dev/zram0 No need to export the pool since it's unchanged by a read-only import and every live page is being replaced anyway. These arguments might or might not make it faster/slower to hibernate, but aren't by any means needed cd /sys/module/zfs/parameters/ echo 0 > zfs_arc_max echo 1 > zvol_request_sync echo 1 > zfs_txg_timeout echo 230:0 > /sys/power/resume echo 0 > /sys/power/image_size