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 withFailed 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.
Best Answer
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...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.
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/ directoryOn Debian it looks like this:
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:
Now we should modify our system's systemd-hibernate.service:
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:
Next step is to modify service file called systemd-hibernate-resume@.service located in the same /usr/lib/systemd/system directory:
We need to modify Before field now. Add swap-off.service next to the local-fs-pre.target:
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