13

This question originated with a joke between co-workers about increasing performance by moving swap files to a tmpfs. Clearly even if this is possible, it's not a good idea. All I want to know is, can it be done?

I'm currently on Ubuntu 14.04, but I'd imagine the process is similar for most Linux/Unix machines. Here's what I'm doing:

> mkdir /mnt/tmp
> mount -t tmpfs -o size=10m tmpfs /mnt/tmp
> dd if=/dev/zero of=/mnt/tmp/swapfile bs=1024 count=10240
> chmod 600 /mnt/tmp/swapfile
> mkswap /mnt/tmp/swapfile
# So far, so good!

> swapon /mnt/tmp/swapfile
swapon: /mnt/tmp/swapfile: swapon failed: Invalid argument

So, on either linux or unix (I'm interested in any solution) can you somehow set up swap on a file/partition residing in ram? Is there a way around the Invalid argument error I'm getting above?

Again, just want to emphasize that I'm not expecting this to be a solution to a real-world problem. Just a fun experiment, I guess.

4 Answers4

12

It shouldn't be possible. swapon system call requires readpage and bmap (indirectly) calls being implemented by filesystem:

http://lxr.free-electrons.com/source/mm/swapfile.c?v=4.0#L2412

if (!mapping->a_ops->readpage) {
    error = -EINVAL;
    goto bad_swap;
}   

But none of them are implemented by tmpfs, such an entry is missing from corresponding address_space_operations: http://lxr.free-electrons.com/source/mm/shmem.c?v=4.0#L3104

For the same reason, tmpfs cannot hold loop mounts, and ramfs won't work either (it doesn't have bmap call)

myaut
  • 1,411
  • 10
  • 12
3

From this Q&A https://superuser.com/questions/539287/swapon-failed-invalid-argument-on-a-linux-system-with-btrfs-filesystem (the original referenced site is not responding):

So "Invalid argument" should be read as "Your filesystem do not support swap file"

The incompatibility reason I suspect is a "circular dependency". From this article: http://www.jamescoyle.net/knowledge/951-the-difference-between-a-tmpfs-and-ramfs-ram-disk:

These two differences between ramfs and tmpfs make tmpfs much more manageable however this is one major drawback; tmpfs may use SWAP space. If your system runs out of physical RAM, files in your tmpfs partitions may be written to disk based SWAP partitions and will have to be read from disk when the file is next accessed.

Which would be pretty much impossible in your scenario.

It might work with ramfs, tho - which doesn't have this problem.

Dan Cornilescu
  • 1,286
  • 9
  • 10
  • Yes - setting a `tmpfs` partition as swap would start and endless loop when the machine starts swapping. – dr_ May 30 '16 at 08:33
2

You can easily avoid the issues with missing functions and swap to tmpfs, though a bit indirectly:

dd if=/dev/zero bs=1M of=/tmp/swapfs count=128
chmod 0600 /tmp/swapfs
mkfs.ext2 /tmp/swapfs
mount -o loop /tmp/swapfs /mnt
dd if=/dev/zero bs=1M of=/mnt/swap
mkswap /mnt/swap
swapon /mnt/swap

Combined with zswap it looked like a great "memory expander" solution till my RasPi4 froze almost completely (ssh console froze, X froze, youtube in chrome kept talking for several minutes and froze as well, but the system was replying to pings and watchdog didn't do anything useful. Launched via ssh (before that has happened) atop didn't show anything outstanding as well - there seemed to be enough free ram and swap space, In fact, similar idea with OpenSolaris (swap to a compressed zvol) lead to similar outcome.

jesse_b
  • 35,934
  • 12
  • 91
  • 140
unisol
  • 21
  • 2
  • @Jesse_b, would it make any difference to do a bind instead of a loop mount on that file? – rjt Jan 04 '20 at 22:16
  • @rjt: Not sure. I didn't write the answer I just edited it. – jesse_b Jan 04 '20 at 22:17
  • @unisol, did your swapfile grow beyond what was intended. Filling up diskspace – rjt Jan 04 '20 at 22:22
  • 1
    Where exactly does this actually use RAM? Looks like it creates a file on /tmp/ which persists across reboots on my machine. – rjt Jan 04 '20 at 22:55
  • It was intended that you have tmpfs mounted in /tmp (it's good in terms of "nothing is left after reboot" and often used in embedded setups but dangerous if you go low on RAM and unpleasant when something doesn't fit into your /tmp - like mc unpacking several gigs of archive). The topic starter failed to get swapfile using RAM-based file system - so I just create a file in it, format it into whatever FS has the necessary capabilities (i.e. ext2) and create a swap on that FS. Extra hoops&loops - but the goal is achieved. – unisol Jan 06 '20 at 00:14
  • My intention was to use zswap - to compress unused parts of RAM and store them in RAM (2GB raspberry pi4) - so that it doesn't swap to extremely slow and tender SD card (I did try runnning w/o swap - the result was not good after several hours in chromium). So I hit the same issue as the topicstarter and started googling ;). The explanation "why it doesn't work" (the unsupported syscalls) immediately lead to the solution. I've done similar thing in OpenSolaris years ago - tmpfs had a limit on number of files in it, this approach has solved that issue. – unisol Jan 06 '20 at 00:28
  • Evidently, there is a demand for setups like "part of RAM+compressed swap in another part of RAM" but without kernel hacking it seems to be impossible to achieve this effect with the described approach. In FreeBSD you can make a fixed-size memory-backed (unswappable) device and swap to it but w/o thing like zswap and "rubber" swap size support it's pointless. Using swap on compressed ZFS on ramdisk on FreeBSD doesn't work same way as on Solaris (you get the growing "total swap size" on Solaris though low-ram conditions just freeze the system). – unisol Jan 06 '20 at 00:40
1

So, on either linux or unix (I'm interested in any solution) can you somehow set up swap on a file/partition residing in ram?

Sure. On FreeBSD:

# swapinfo -h
Device          1024-blocks     Used    Avail Capacity
/dev/mirror/swap.eli     4194300       0B     4.0G     0%

That shows that currently, I have a 4G encrypted swap partition with mirrored redundancy. I'll add another 4G of non-redundant, non-encrypted swap:

First create a 4G RAM-backed "memory disk" (md) device:

# mdconfig -a -t malloc -s 4g; mdconfig -lv
md0
md0     malloc   4096M  -

Then tell swapon to add that to the pool of available swap devices, and swapinfo confirms that I now have 8G of swap:

# swapon /dev/md0; swapinfo -h
Device          1024-blocks     Used    Avail Capacity
/dev/mirror/swap.eli     4194300       0B     4.0G     0%
/dev/md0            4194304       0B     4.0G     0%
Total               8388604       0B     8.0G     0%
Jim L.
  • 7,188
  • 1
  • 13
  • 25
  • Moving the "accepted answer" checkmark after 4 years is a hard decision. This answer shows there is a way! `mdconfig(8)` includes a note that omitting the `-o reserve` option "is a very easy way to panic a system". It also notes that the type can be set to `swap` which allows the very entertaining scenario of a system moving memory pages into swap that itself resides in memory! There's even an option `-o force` for dummies like myself who want to omit "extra sanity checks". Had a good laugh reading this. – vastlysuperiorman Nov 04 '19 at 21:26