Enabling TRIM on LVM on LUKS on NVMe

I have just recently set up a new Arch Linux system with LVM on LUKS for disk encryption. The system is installed on an NVMe SSD. SSD controllers can be notified about unused blocks using TRIM, but by default this feature is not enabled on Arch Linux.

There are two approaches to enabling TRIM on Linux: periodically running fstrim and enabling discard option on the filesystem. Enabling option the filesystem seems to be discouraged for multiple reasons, one of which is that it wastes throughput on processing TRIM commands while the system is used.

Enabling fstrim.timer

Usually recommended setup is enabling periodic cleanup by enabling fstrim.timer. I enabled it with

# systemctl enable --now fstrim.timer
Created symlink '/etc/systemd/system/timers.target.wants/fstrim.timer' → '/usr/lib/systemd/system/fstrim.timer'.

Then I ran fstrim manually:

# fstrim -av
/efi: 1021.8 MiB (1071456256 bytes) trimmed on /dev/nvme0n1p1
/boot: 890.7 MiB (933982208 bytes) trimmed on /dev/nvme0n1p2

This discarded blocks on /efi and /boot partitions, but did not work for encrypted partitions even though they were mounted.

Enabling discards on LUKS

LUKS disables discard by default for security reasons: it is possible to get some information about disk usage by looking at which blocks are discarded.

The issue sounds mostly theoretical, so I enabled discards on LUKS partition with

# cryptsetup luksDump /dev/nvme0n1p3 | grep Flags
Flags:       	(no flags)
# cryptsetup --allow-discards --persistent refresh crypt
Enter passphrase for /dev/nvme0n1p3:
# cryptsetup luksDump /dev/nvme0n1p3 | grep Flags
Flags:       	allow-discards

Afterwards lsblk showed that discards are now allowed on LUKS.

# lsblk --discard
NAME          DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1              0      512B       2T         0
├─nvme0n1p1          0      512B       2T         0
├─nvme0n1p2          0      512B       2T         0
└─nvme0n1p3          0      512B       2T         0
  └─crypt            0      512B       2T         0
    ├─vg-root        0        0B       0B         0
    └─vg-home        0        0B       0B         0

LVM however still did not allow discards.

Enabling discards on LVM

I rebooted the laptop, and then LVM detected that discards are allowed:

# lsblk --discard
NAME          DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1              0      512B       2T         0
├─nvme0n1p1          0      512B       2T         0
├─nvme0n1p2          0      512B       2T         0
└─nvme0n1p3          0      512B       2T         0
  └─crypt            0      512B       2T         0
    ├─vg-root        0      512B       2T         0
    └─vg-home        0      512B       2T         0

Then I ran fstrim manually again and it detected unused space on /home and / partitions.

# fstrim -av
/home: 167.3 GiB (179596095488 bytes) trimmed on /dev/mapper/vg-home
/efi: 1021.8 MiB (1071456256 bytes) trimmed on /dev/nvme0n1p1
/boot: 890.7 MiB (933982208 bytes) trimmed on /dev/nvme0n1p2
/: 77.1 GiB (82783838208 bytes) trimmed on /dev/mapper/vg-root

I still have unused space on LVM, so I trimmed it manually by temporarily creating a logical volume, discarding it once, and removing it:

# lvcreate vg -l 100%FREE -n trim
# blkdiscard /dev/vg/trim
# lvremove /dev/vg/trim
Do you really want to remove active logical volume vg/trim? [y/n]: y
  Logical volume "trim" successfully removed.