Btrfs and Swap Files - Swapon Failed: Invalid Argumnt

Troubleshooting BTRFS swap file installation

Issue Reproduction

I’ve got a btrfs filesystem without encryption:

[root@example.tld /]# lsblk -fs
nvme0n1p1 vfat   FAT32       A728-5B2F                             438.6M    14% /boot
nvme0n1p2 btrfs              262f71f8-c862-4d3f-829c-c98ce282747c   81.6G    63% /

I attempted to setup a quick swapfile as I would on CentOS with XFS or EXT, but that failed with swapon: /swap1G: swapon failed: Invalid argument:

tester@example.tld ~ $ sudo su
[sudo] password for tester:
[root@example.tld tester]# cd
[root@example.tld ~]# cd /
[root@example.tld /]# touch /swap1G
[root@example.tld /]# dd if=/dev/zero bs=1024 count=1000000 of=/swap1G
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB, 977 MiB) copied, 3.3006 s, 310 MB/s
[root@example.tld /]# swapon /swap1G
swapon: /swap1G: swapon failed: Invalid argument

How to Find Info For Resolution

A great first step to find more information when you’re not sure where to look is the system log which varies based on your distribution and/or specific configuration. A few examples:

  • journalctl
  • /var/log/messages
  • /var/log/syslog

I found my key info in journalctl:

[root@example.tld /]# journalctl -g "swap" 2>/dev/nul | tail -1
Nov 07 20:07:54 example.tld kernel: BTRFS warning (device nvme0n1p2): swapfile must not be copy-on-write

I still didn’t quite know what exactly to do to resolve that. The man pages have the answer. You can find it with man -K:

[root@example.tld /]# man -K "copy on write"
--Man-- next: perl5200delta(1perl) [ view (return) | skip (Ctrl-D) | quit (Ctrl-C) ]

That pulled up chattr and explains that the capital C flag controls copy on write:

[root@example.tld /]# man chattr | grep "copy on write"
       only (a), no atime updates (A), compressed (c), no copy on write (C), no dump  (d),


Remove the existing swap file to start fresh. Keep in mind that I’d never enabled this swap file so I did not need to use the swapoff command.

[root@example.tld /]# rm /swap1G

Create an empty file and update the permissions:

[root@example.tld /]# touch /swap1G
[root@example.tld /]# chmod 0600 /swap1G

Just looking at the current file attributes for easy comparison later:

[root@example.tld /]# lsattr /swap1G
---------------------- /swap1G

Add the no copy on write attribute:

[root@example.tld /]# chattr +C /swap1G

Verify that it was added:

[root@example.tld /]# lsattr /swap1G
---------------C------ /swap1G

Pre-Allocate 1 GB of space by filling the file with zeros until it hits that point:

[root@example.tld /]# dd if=/dev/zero bs=1024 count=1000000 of=/swap1G
1000000+0 records in
1000000+0 records out
1024000000 bytes (1.0 GB, 977 MiB) copied, 2.88929 s, 354 MB/s

Convert the file into a swap file:

[root@example.tld /]# mkswap /swap1G
Setting up swapspace version 1, size = 976.6 MiB (1023995904 bytes)
no label, UUID=3576cbde-e64f-43d5-84fd-80f6a3182ea9

Edit my fstab configuration so that the swap file is activated/mounted on boot:

[root@example.tld /]# vim /etc/fstab

This just shows the edit that I made:

[root@example.tld /]# tail -1 /etc/fstab
/swap1G none swap defaults 0 0

The moment of truth. Fortunately I did not encounter further issues when enabling the swap. This is only required this first time. The /etc/fstab file will take care of enabling swap on boot moving forward.

[root@example.tld /]# swapon -a

Double check to ensure that I have 1G of swap:

[root@example.tld /]# free -h
               total        used        free      shared  buff/cache   available
Mem:           7.6Gi       1.8Gi       1.6Gi       509Mi       4.1Gi       4.9Gi
Swap:          976Mi          0B       976Mi

NOTE: You would typically assign much more swap than 1G, but it all depends on your specific use case and kernel version. Older kernels before 4 can end up swapping too much if you add too much swap. Kernels 4 and after allow you to add large swap spaces without that concern.