Creating swapfile on btrfs subvolume: chattr +C fails

Hello,
after a fresh install I’m trying to create a swapfile on a btrfs subvolume which is on a luks-partition.
Creating the 0-sized swapfile with truncate is simple, but chattr +C swapfile keeps failing as soon as I place the swapfile on a subvolume other than ‘@’ (‘/’) in my case.

truncate -s 0 swapfile
chattr +C swapfile    
chattr: Invalid argument while setting flags on swapfile

I also tried this directly via the mounted mapper-device on /@swap without any success.

The devices and subvolumes in question look like this:

nvme0n1                                       259:0    0   1,8T  0 disk  
|-nvme0n1p1                                   259:1    0   300M  0 part  /boot/efi
|-nvme0n1p2                                   259:2    0 931,4G  0 part  
`-nvme0n1p3                                   259:3    0 931,4G  0 part  
  `-luks-a8178f4e-a47a-469c-97d7-88a7c8f5f06a 254:0    0 931,4G  0 crypt /var/log
                                                                         /swap
                                                                         /var/cache
                                                                         /home
                                                                         /

@
	Name: 			@
	UUID: 			a07e1b19-8fa0-ce4b-a1bf-b2430258b0cb
	Parent UUID: 	-
	Received UUID: 	-
	Creation time: 	2022-09-10 22:40:15 +0200
	Subvolume ID: 	256
	Generation: 		850
	Gen at creation: 	9
	Parent ID: 		5
	Top level ID: 		5
	Flags: 			-
	Send transid: 		0
	Send time: 		2022-09-10 22:40:15 +0200
	Receive transid: 	0
	Receive time: 		-
	Snapshot(s):

@swap
	Name: 			@swap
	UUID: 			857936bb-8585-bf44-8ecb-50f86fb774a7
	Parent UUID: 		-
	Received UUID: 	-
	Creation time: 	2022-09-11 17:09:20 +0200
	Subvolume ID: 	263
	Generation: 		810
	Gen at creation: 	794
	Parent ID: 		5
	Top level ID: 		5
	Flags: 			-
	Send transid: 		0
	Send time: 		2022-09-11 17:09:20 +0200
	Receive transid: 	0
	Receive time: 		-
	Snapshot(s):

IMHO I doubt that the encryption or partition scheme is part of the problem.
And of course without disabling CoW the swapfile can’t be activated.

I’ll place the the swapfile in /swap for the time being, but then I can’t create snapshots of /.
What am I overlooking?
Thanks a lot,
Michael.

From the Arch-Wiki:

Note: Since Linux kernel 5.0, Btrfs has native swap file support with some limitations:

  • The swap file cannot be on a snapshotted subvolume. The proper procedure is to create a new subvolume to place the swap file in.
  • It does not support swap files on file systems that span multiple devices. See btrfs(5) § SWAPFILE SUPPORT and Arch forums discussion.

Just re-read your post… apparently you have no snapshots, but. :point_up:

No, I don’t think so.
IOW, a btrfs subvolume with a swapfile on it (which must have CoW disabled) can’t have snapshots. So it’s explicitly recommended (read that on various places here and on the Net) to have it on a dedicated subvolume. And this can’t be root.
But actually, I’m not getting this far.
All I’m doing (by the book) is creating an empty file on a subvolume and trying to switch off Copy-On-Write.

(ok, this is a very dynamic posting-style :upside_down_face:)
You were quicker than me, I just replied saying about the same…

Sorry for the confusion… :upside_down_face:
Also, sorry to say I don’t know as I can’t reproduce it here.
Perhaps someone will come soon to help you out.
All the best…

i tell what EndeavourOS does per default story hope not a nightmare?

[joe@joe-virtualbox ~]$ lsblk -f
NAME   FSTYPE   FSVER     LABEL      UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda                                                                                      
├─sda1 vfat     FAT32                C52E-5A07                             298,7M     0% /boot/efi
└─sda2 crypto_L 1                    46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8                
  └─luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8
       btrfs                         31dfc292-9aa4-4d3f-9a55-fb041f72673c   27,4G     9% /var/log
                                                                                         /var/cache
                                                                                         /home
                                                                                         /swap
                                                                                         /
[joe@joe-virtualbox ~]$ sudo btrfs subvolume list -p /
ID 256 gen 32 parent 5 top level 5 path @
ID 257 gen 32 parent 5 top level 5 path @home
ID 258 gen 31 parent 5 top level 5 path @cache
ID 259 gen 32 parent 5 top level 5 path @log
ID 260 gen 26 parent 5 top level 5 path @swap

2022-09-11_22-02

[joe@joe-virtualbox ~]$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a device; this may
# be used with UUID= as a more robust way to name devices that works even if
# disks are added and removed. See fstab(5).
#
# <file system>             <mount point>  <type>  <options>  <dump>  <pass>
UUID=C52E-5A07                            /boot/efi      vfat    defaults,noatime 0 2
/dev/mapper/luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8 /              btrfs   subvol=/@,defaults,noatime,compress=zstd 0 0
/dev/mapper/luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8 /home          btrfs   subvol=/@home,defaults,noatime,compress=zstd 0 0
/dev/mapper/luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8 /var/cache     btrfs   subvol=/@cache,defaults,noatime,compress=zstd 0 0
/dev/mapper/luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8 /var/log       btrfs   subvol=/@log,defaults,noatime,compress=zstd 0 0
/dev/mapper/luks-46d62a8f-ed37-4ce4-b4fc-dd0b162ac4c8 /swap          btrfs   subvol=/@swap,defaults,noatime 0 0
/swap/swapfile                            swap           swap    defaults   0 

so a regular subvol mounted … mounted at /swap but the swapfile does not need to be directly under / path as you can see it can be a subfolder…

[joe@joe-virtualbox ~]$ sudo file /swap/swapfile
/swap/swapfile: Linux swap file, 4k page size, little endian, version 1, size 131071 pages, 0 bad pages, no label, UUID=0d9c1583-7e35-4585-8a34-0a0985b891aa

2022-09-11_22-05

1 Like

The wiki say also to chattr the directory and not the file only…

Swap files in Btrfs are supported since Linux kernel 5.0.[8] The proper way to initialize a swap file is to first create a non-snapshotted subvolume to host the file and then set the No_COW attribute on the whole directory with chattr.

# chattr +C */path/to/swapsubvolume*
From now on any new file created inside the swap subvolume will have the No_COW attribute set.

[joe@joe-virtualbox ~]$ sudo lsattr /swap
---------------C------ /swap/swapfile
[joe@joe-virtualbox ~]$ sudo lsattr /swap/swapfile
---------------C------ /swap/swapfile

2 Likes

Thanks a lot for your very elaborate answer!
Alas, I don’t even get that far:
Trying to change any attribute on any file on a subvolume, chattr just fails. :roll_eyes:

chattr: Invalid argument while setting flags on swapfile

0-sized swapfile ? why that?

and if something is not setup in the rightway…
https://bbs.archlinux.org/viewtopic.php?id=256913

1 Like

CoW needs to be disabled before any blocks of the file in question are written (resp. not written)

could be it is not needed anymore ( i am not the best expert on BTRFS :wink:
Archwiki say chattr +C on the swap subvol and after this create the swapfile as of the wiki…
the error looks like something is wrong with the used mount options or filesystem … like in the post i linked where user tried to set +C on a swapfile inside ext4 filesystem

1 Like

If CoW is active on a file, mkswap for this file won’t work and leaves a complaint in dmesg.
Somewhere here I read there was a change in the btrfs kernel module resulting that compression and CoW are mutually exclusive (?, not sure, have yet to find the posting).
So I tried this:

/dev/mapper/lukspart /swap      btrfs   subvol=/@swap,defaults,noatime,autodefrag 0 0
#/dev/mapper/lukspart /swap      btrfs   subvol=/@swap,defaults,compress=none,nodatacow,nodatasum,noatime,autodefrag 0 0

btrfs docs say nodatacow, nodatasum and compress are silently ignored (resp. not implemented), but I gave it a try and removed it from the mount options anyway.
And ‘surprise’ chattr worked!
But: To be sure I did a crosscheck and I changed the lines again.
Unexpectedly any chattr - command works this time!
So … now I got a working swapfile (after applying all other commands) but I don’t know why!
:thinking:

I dearly hope that’s not a BTRFS-hickup! Like flicking a switch twice to get the connection working … :roll_eyes:

Found the patch and @dalto 's comment:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0e852ab8974cd2b5946766b2d9baf82c78ace03d

But, in fact, I don’t think that’s relevant to what happened here and I still have no clue!
:roll_eyes:

1 Like

As a side note, are you sure you want autodefrag on your swap subvolume?

1 Like

Why not shrink Btrfs partition size, then create a new Swap partition?

Btrfs supports resizing well.

Puts an unnecessary load on your system, thereby slowing it down? AFAIK swap is cleaned on every reboot?

I am not sure and my logic is not clear if you mean that a swapfile on Btrfs is faster than a swap parititon. :man_shrugging: Do you have any information source?

I thought: The swap partition is native and more reliable and has better performance.
The swapfile is more flexible, however, there is a risk when it runs on btrfs as B-Tree.

Thanks, @dalto this slipped into it! :roll_eyes:

1 Like

Actually, I don’t know.
The entire system is on a LUKS partition, on an NVMe.
IMHO a swapfile is the easiest way to have swap encrypted, that goes in one swoop. *)
From this storage’s point of view it wouldn’t matter where the swap data is being put, any block can be reached in similar time.
Except, if BTRFS has to jump a lot of hoops to get a swapfile working on a subvolume.

*) I just realised the irony in this sentence, given this threads topic.