9

My laptop has plenty of RAM and a SSD. To not wear out the SSD, I do not want to have swap be used ever. If a process ever uses so much RAM that it has to start using swap, then it clearly is misbehaving and should be killed by the kernel. But I also want to be able to hibernate or hybrid-sleep my laptop. It currently seems to be very hard to get such a setup working. Here are some caveats:

  • even setting swappiness to 0 will let swap be used if an application requests too much memory. There seems to be no way to have swap enabled but stop the kernel from using it as swap space (and thus reduce its utility to space for the hibernation image)
  • disabling the swap (temporarily) will lead to commands like systemctl hibernate error out with Failed to hibernate system via logind: Sleep verb not supported
  • I want upower to be able to put my system into hibernation/hybrid-sleep (so writing a wrapper script which enables swap and then launches systemctl hibernate is not sufficient)

I am now looking for the right way to achieve this. One way to do it would probably be to generally disable my swap partition and then to swapon at the right point via systemd (and swapoff after the system woke up). But I'm at a loss how to achieve this.

Another way would be to use a swap file but that seems to add extra complication compared to using a swap partition. Not the least because I'm using full disk encryption and uswsusp seems to be just another layer on top of what I can already have with my existing swap partition. But maybe I'm missing something and using a swap file is indeed overall easier for this purpose.

5
  • did you find a solution? – Turgs Apr 18 '18 at 22:09
  • @Turgs unfortunately not. – josch Apr 19 '18 at 13:22
  • 1
    The answer is to simply use swap. Use a swapfile if you don't want to bother with a partition. But this won't kill your SSD. I mean I never cared about my SSD, I used them without TRIM, and they have 99% life left. With heavy virtualization, daily heavy use, power use, gaming, everything. The only ways to kill an SSD IMO is: 1) Buy one from the very early days. Those things died. 2) Buy an SSD with a bad firmware - this was again an old thing, got fixed with fw updates. 3) Buy one of those super cheap TLC SSDs from China. If you just buy any remotely affordable SSD, it won't die. – Apache Jun 22 '19 at 21:18
  • swap is there for a reason, and the (your) OS understands how to use it most effectively. If you aren't using an SSD from 5 or more years ago, or some "bargain basement" brand. You have noting to fear. This isn't a USB stick/flash drive. Use it to the fullest. That's why you got an SSD. Right? :) – somebody Jun 23 '19 at 9:33
  • Did the accepted answer work for you? Did it cause any problems? It's funny how people are posting comments saying "don't do it because you can always buy a new ssd" because without swap you may run out of memory - as if swap was infinite.. I used to run a Linux laptop without swap and it was the most responsive system I used. Back then I used to tell people: "Can I run Ubuntu with 4GB of RAM and 8GB of swap? If so then obviously I can run it with 16GB or RAM and no swap - many times faster. I'm looking into a new Linux laptop setup so I'd like to know your experience with this answer. Thanks. – rsp Jul 7 '20 at 17:51
5
  1. Disabling swap when you already know that your system can get to the point when it won't have enough memory is a bad idea. Right at the moment when kernel doesn't have any memory to allocate your system will probably be very-very unresponsive or just hang so you'll have to reboot it. Hangs may cause data losses, sometimes filesystem corruption. Depends on filesystem it can be fixed automatically (ext* family, fat family, btrfs and some others), but not every FS support this feature. I bet you probably won't like to run fsck in single user mode every time you have a corruption...

  2. Kernel is not that stupid to just write everything it wants to your SSD, it behaves differently compared to HDDs and tries to make the least possible writes using things such as TRIM. There's not that much harm to your drive as you may think.

  3. Hibernation is a built-in kernel subsystem that operates on a low level. It still has to have a separate partition with size ≥ RAM size allowing it to just make a full snapshot of you memory. Here you can read how linux manages hibernation. If there's no place to permanently store memory image there's no way hibernation works. You can't store data in the air. No permanent physical storage = no hibernation. So that's also the answer to your question: you can't use hibernation without swap on linux.

So, my point is that you of course can live without swap and enable it only for hibernation, but only if you're sure that 99.9% of the time system is on it has enough memory for everything. If that's not your case you must use swap.

Now to the possible solution:

When you run systemctl hibernate systemd starts a service called systemd-hibernate.service. Unit file of which is usually located it /usr/lib/systemd/system/ directory

On Debian it looks like this:

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Hibernate
Documentation=man:systemd-suspend.service(8)
DefaultDependencies=no
Requires=sleep.target
After=sleep.target

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-sleep hibernate

As you can see there are Requires and After options. We can write another unit that will enable swap and add it's name to these fields. We'll call it swap-on.service and place it in /etc/systemd/system/ directory

Our file will look something like this:

# Unit filed is not required in our case so you can skip it
[Unit]
Description=Enable swap partition

[Service]
# This line means that service will be executed just once and immediately stop when
# swapon enables swap on /dev/sda3
Type=oneshot

# Change /dev/sda3 with device named after your swap partition 
# like /dev/sdb3 or /dev/nvme0n1p3
# Use lsblk to determine your swap partition (partition with [SWAP] as mountpoint)
# Of course you can think of a more complex solution like running external script
# that determines your swap partition automatically every time service is executed
# but for now I'll go with simple /dev/sda3
ExecStart=/sbin/swapon /dev/sda3

Now we should modify our system's systemd-hibernate.service:

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Hibernate
Documentation=man:systemd-suspend.service(8)
DefaultDependencies=no
Requires=sleep.target swap-on.service <--
After=sleep.target swap-on.service <--

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-sleep hibernate

We're duplicating swap-on.service in After to make sure that systemd starts hibernation after the swap is on and not vice versa and in Required to make sure that systemd will not try to hibernate if swap-on.service failed.

Now when we run systemctl hibernate systemd runs our modified systemd-hibernate.service which runs swap-on.service that enables swap. When the swap is enabled and both Required and After fields are satisfied systemd can finally make our system hibernate.

To make systemd disable swap after resuming from hibernation we'll need no make another service file called swap-off.service which will do the same thing as our swap-on.service, place it in the same directory as the "on" service (/etc/systemd/system/). The only difference is that this service will run swapoff instead of swapon:

[Unit]
Description=Disable swap partition

[Service]
Type=oneshot

#  again, change /dev/sda3 to your swap partition /dev file
ExecStart=/sbin/swapoff /dev/sda3 <--

Next step is to modify service file called systemd-hibernate-resume@.service located in the same /usr/lib/systemd/system directory:

[Unit]
Description=Resume from hibernation using device %f
Documentation=man:systemd-hibernate-resume@.service(8)
DefaultDependencies=no
BindsTo=%i.device
Wants=local-fs-pre.target
After=%i.device
Before=local-fs-pre.target
ConditionPathExists=/etc/initrd-release

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-hibernate-resume %f

We need to modify Before field now. Add swap-off.service next to the local-fs-pre.target:

...
After=%i.device
Before=local-fs-pre.target swap-off.service <--
ConditionPathExists=/etc/initrd-release
...

Now when you resume from hibernation systemd will run swap-off.service after the swap image is loaded in memory (in fact a bit later, but that doesn't matter for us)

Keep in mind that this is a fully theoretical solution, I didn't try it yet, but based on what I know about systemd this should work. Since UPower asks systemd to hibernate which as I explained runs systemd-hibernate.service this is probably what you're looking for

1

Firstly you shouldn't worry about SSD nowadays. Their wear-leveling algorithm is good enough that SSDs in the last few years have a 5-year warranty, which means that manufacturers are so confident that the drive can still function properly if you write lots of data to it every day for 5 years. The larger the SSD the better lifetime it provides, because there are more free blocks for the firmware to move dead clusters around. But even older SSDs can sustain such conditions. I have an old workstation produced around 2012-2014 and its SSD has just reached 50% total data writes

As others said, disabling swap is a bad idea even if you have plenty of RAM. So you still need some kind of swap, but you should forget about normal swap and use zram instead. It's much faster than HDD, SD, eMMC or older SSDs and causes no wear on the flash memory. With the default lzo compression algorithm it's even faster than many new SSDs based to the benchmark results here. You can change to lzo-rle, lz4 (which is nearly 5 times faster than lzo) or zstd for a far better performance with a little bit less compression ratio

Many modern OSes like ChromeOS, Android and various Linux distros (Lubuntu, Fedora) have already enabled zram by default for years, especially for systems with less RAM. Windows 10 and macOS also use similar pagefile compression techniques by default

Once you enabled zram you still need a small swap partition or swap file for hibernating, but there should be almost no writes to it. But you must ensure that it has a lower priority than zram. If you're on Ubuntu just run sudo apt-get install zram-config and you're good to go. There are also zswap and zcache. I haven't tried them but they're probably worth a try

Further reading

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.