21

I have SSD with btrfs, I tried creating a swapfile like:

dd if=/dev/zero of=swapfile01  bs=1M count=10240
mkswap swapfile01
chmod 600 swapfile01
swapon swapfile01

In dmesg I see

[238434.731654] swapon: swapfile has holes

I understand that there are probably some holes caused by disk fragmentation, but this is SSD disk so it probably shouldn't matter? Is there a way to ignore the holes? Or how can I fix this?

Off topic - why I want this (to avoid irrelevant questions in comments): I have encrypted disk which is pain in the **** to resize, so I just decided to create a swapfile instead of resizing the swap partition (I added 14GB of ram, from 4gb to 16gb and can't hibernate now).

Petr
  • 2,481

7 Answers7

26

As mentioned above, since Linux 5.0 it is now possible to create swap files on BTRFS. But they should be non-compressed and NoCOW. Here is how do you actually create such a file:

  1. Create an empty file: touch /swap
  2. Use chattr to set NoCOW attribute to it: chattr +C /swap
  3. Verify that C attribute appeared: lsattr /swap
  4. Fill it: dd if=/dev/zero of=/swap bs=1M count=1024 # for 1 gigabyte
  5. mkswap /swap && chmod 600 /swap && swapon /swap

Alternatively, you can create a directory, set chattr +C to that directory and then create a swapfile under it.

Note that you cannot do chattr +C to already existing non-empty file. It is documented to be undefined behaviour (in fact it just doesn't change attributes). So you should either create an empty file and then chattr, or create a directory with chattr and then create a file in it (in such case all files created after chattring the directory will have the nocow attribute).

Caveat: as mentioned, this requires kernel version 5.0 or higher. Raspberry Pi for example uses 4.19.* kernels so you won't be able to use this technique on it.

MarSoft
  • 441
10

Status in 2019

The development of Btrfs and Linux kernel rendered my original answer obsolete. Please see this other answer.


Original answer from 2016

From btrfs FAQ:

Does btrfs support swap files?

Currently no. Just making a file NOCOW does not help, swap file support relies on one function that btrfs intentionally does not implement due to potential corruptions. (...) A workaround, albeit with poor performance, is to mount a swap file via a loop device.

So there is no good way to create swapfile on btrfs partition yet.

9

In Linux 5.0 or later:

file='/swapfile'
# create file
touch "$file"
# No Copy-on-Write
chattr +C "$file"
# Allocate 10 GB  (much faster than dd)
fallocate -l 10G "$file"
# Set permissions to make mkswap happy
chmod 600 "$file"
# Set swap file signature
mkswap "$file"
# change owner if not already root to make swapon happy
sudo chown root "$file"
# Activate
sudo swapon "$file"
Ole Tange
  • 5,099
8

Swap file support has been added to kernel version 5.0 as can be seen at commit https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ed46ff3d423780fa5173b38a844bf0fdb210a2a7 To activate swap file on btrfs, file must be fully allocated as NOCOW with no compression on one device.

arvati
  • 81
3

Useful thing to know about swap on btrfs is: if you are doing backup snapshots / subvolumes, you should create a dedicated subvolume that you're not snapshotting.

On snapshot subvolume, your swapfile will become COW again, and you won't be able to swapon after reboot: https://www.spinics.net/lists/linux-btrfs/msg96790.html

I made my last subvolume writeable, like sudo btrfs property set -ts /.sxbackup/sx-20210211-092159-utc/ ro false, deleted swap, and was able to swapon on main volume again - but I will make a dedicated subvolume next.

lkraav
  • 1,289
1

Here's how to setup swap via loopback on btrfs:

# dd if=/dev/zero of=/swapfile bs=1M count=1k
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.23138 s, 872 MB/s

# losetup --find --show /swapfile
/dev/loop0

# mkswap /dev/loop0
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=04b048e2-47ab-4ab0-a79e-7e1c481a10c9

# swapon /dev/loop0

Is this ideal? No. Avoid using it in production. But it works as a last resort kind of thing.

w00t
  • 829
0

This is what I did and worked for me. here is the output of lsblk:

NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    0   7.3T  0 disk 
├─sda1        8:1    0    16M  0 part 
└─sda2        8:2    0   7.3T  0 part /run/media/ef/Storage
zram0       252:0    0     8G  0 disk [SWAP]
nvme0n1     259:0    0   1.8T  0 disk 
├─nvme0n1p1 259:1    0    16M  0 part 
├─nvme0n1p2 259:2    0 834.7G  0 part 
├─nvme0n1p3 259:3    0   614M  0 part 
├─nvme0n1p4 259:4    0   100M  0 part /boot/efi
├─nvme0n1p5 259:5    0     1G  0 part /boot
└─nvme0n1p6 259:6    0     1T  0 part /home

and here is output of $ swapon -s

Filename                Type        Size        Used        Priority
/dev/zram0              partition   8388604     1935420     100

Here are the steps I followed:

$ sudo touch /swapfile
$ sudo chattr +C /swapfile 
$ sudo lsattr /swapfile
$ sudo fallocate -l 200G /swapfile
$ sudo lsattr /swapfile
$ sudo chmod 600 /swapfile
$ sudo lsattr /swapfile  # make sure you see the letter C in the results: ---------------C------ /swapfile
$ sudo mkswap /swapfile # output example: Setting up swapspace version 1, size = 200 GiB (214748360704 bytes)
$ sudo mkswap /swapfile # output example: Setting up swapspace version 1, size = 200 GiB (214748360704 bytes)
                                          no label, UUID=98a6c4a0-ec8d-4afb-90af-6162e83d30b3
$ sudo swapon /swapfile
$ vim /etc/fstab 

here I added one line at the end of /etc/fstab:

/swapfile swap swap defaults 0 0

That's it. Now you can see it shows up:

$ sudo swapon -s
NAME       TYPE      SIZE USED PRIO
/dev/zram0 partition   8G 1.8G  100
/swapfile  file      200G   0B   -2

I tested it and it works for reading huge files. resources that helped: