SKYHOUSE.dev Journal

Maintaining the Cloud Fortress

The Swap That Wasn't There

Why: Damien noticed swap still looked full a day after the big Immich import and asked whether the import was somehow still filling it. It wasn't — but chasing the question turned up a 32 GB swapfile that had been silently switched off for an unknown length of time.

The original worry was unfounded, and it's worth writing down why, because "swap is full" reads as alarming and usually isn't.

1. It wasn't filling — it had filled, and never drained

vmstat showed a swap-out rate of zero; the only non-zero figure was the since-boot average. Meanwhile 50 GB of 62 GB was available, with 51 GB of that reclaimable page cache. And the processes holding swap weren't Immich at all — they were idle desktop apps (nautilus 387 MB, gnome-shell 280 MB, chrome), with Immich accounting for only ~245 MB.

What happened is that reading ~500 GB of takeout zips and writing to plex1 filled the page cache, and sustained cache pressure evicted idle anonymous pages even at swappiness=5. Linux then never pages those back proactively — they sit in swap until the owning process touches them, and a minimised file manager never does. So the 3.6 GB was residue from the import window, not evidence of ongoing pressure.

2. The real finding: the 32 GB swapfile was commented out

Checking which disk was swapping turned up the actual problem. The fstab line for the secondary swapfile was disabled:

#/media/scratch/swapfile_extra none swap sw,nofail 0 0

The 32 GB file existed, dated June 4, and /media/scratch was mounted — but the entry was commented, so the machine had been running on the 4 GB root swapfile alone rather than the 35 GB the context dump described. Uptime was 7 days, so this long predated the import; the import merely made it visible.

Best guess is collateral from the storage-fault-saga troubleshooting, when fstab entries were being commented out to get clean boots. The line carries nofail specifically so a dead scratch disk can't block boot, which makes disabling it outright look like debugging rather than policy. That's inference, not evidence.

The irony is that the arrangement had inverted its own purpose: the 32 GB was put on the disposable Kingston to keep swap wear off the good root SSD, and with it disabled, every page the import evicted went to the root SSD instead. (3.6 GB of writes is negligible wear — the concern is the arrangement, not damage.)

3. What I changed

4. A caveat worth knowing before the next reboot

Neither fstab entry specifies pri=, so priorities are auto-assigned in fstab order — meaning /swapfile on the root SSD is the preferred target and the scratch disk is overflow only. Right now the runtime state is the opposite (the drain-and-reactivate gave the root file a fresh, lower priority, so scratch is currently preferred at −2 vs −3), but that will revert on reboot.

So if the goal is genuinely to keep swap wear off the root SSD, both entries need explicit pri= values. Left alone for now, since the documented design has always been "4 GB primary on root, 32 GB overflow on scratch" and changing that is a design decision, not a repair.

The reported problem was a non-problem; the incidental finding was a 32 GB swapfile that had been switched off for at least a week.

← Back to Admin Hub