Enabling TRIM on a LUKS Encrypted SSD on Arch Linux

I found that TRIM was not working on an encrypted Arch Linux system.

The first check was:

sudo fstrim -v /

This returned:

fstrim: /: the discard operation is not supported

Next I checked discard support through the storage stack:

lsblk -D

The relevant part of the output was:

nvme0n1              0      512B       2T         0
├─nvme0n1p1          0      512B       2T         0
├─nvme0n1p2          0      512B       2T         0
└─nvme0n1p3          0      512B       2T         0
  └─archlinux        0        0B       0B         0

The NVMe drive and partition support discard, but the encrypted archlinux mapping reports 0B, so discard is not being passed through the encrypted mapping.

I then checked which device contains the root filesystem:

findmnt -no SOURCE /

This returned:

/dev/mapper/archlinux[/@]

Next I checked discard support through the storage stack:

lsblk -D

The relevant part of the output was:

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
  └─archlinux        0        0B       0B         0

The NVMe device and its partition support discard, but the encrypted archlinux mapping reports 0B, so discard is being blocked at the encrypted mapping.

Next I checked which device contains the root filesystem:

findmnt -no SOURCE /

This returned:

/dev/mapper/archlinux[/@]

This shows that the root filesystem is on the archlinux device-mapper mapping, with @ as the Btrfs subvolume.

Next I checked the encrypted mapping:

sudo cryptsetup status archlinux

This returned:

/dev/mapper/archlinux is active and is in use.
  type:    LUKS2
  cipher:  aes-xts-plain64
  keysize: 512 [bits]
  key location: keyring
  device:  /dev/nvme0n1p3
  sector size:  512 [bytes]
  offset:  32768 [512-byte units] (16777216 [bytes])
  size:    975165455 [512-byte units] (499284712960 [bytes])
  mode:    read/write

The important part here is that the mapping is using LUKS2.

The backing device is shown by cryptsetup status. On this system it is:

device:  /dev/nvme0n1p3

So when inspecting the LUKS2 header, use that device rather than a hard-coded device name:

sudo cryptsetup luksDump /dev/nvme0n1p3 | grep -i Flags

Use the device reported by cryptsetup status on your own system.

On this system the check returned:

Flags:          (no flags)

So there were no persistent LUKS2 flags set before enabling discard.

To enable persistent discard on the active LUKS2 mapping:

sudo cryptsetup --allow-discards --persistent refresh archlinux

This prompted for the LUKS passphrase:

Enter passphrase for /dev/nvme0n1p3:

Enter the passphrase used to unlock that encrypted volume.

After entering the passphrase, I checked the LUKS2 flags again:

sudo cryptsetup luksDump /dev/nvme0n1p3 | grep -i Flags

This now returned:

Flags:          allow-discards

So the persistent allow-discards flag is now set on the LUKS2 volume.

With discard enabled through LUKS, I ran TRIM again:

sudo fstrim -v /

This time it succeeded:

/: 100.6 GiB (108015452160 bytes) trimmed

On this system the first successful trim took a few minutes to complete.

Finally, I enabled the weekly systemd TRIM timer:

sudo systemctl enable --now fstrim.timer

This returned:

Created symlink '/etc/systemd/system/timers.target.wants/fstrim.timer' → '/usr/lib/systemd/system/fstrim.timer'.

I then verified the timer:

sudo systemctl status fstrim.timer

The important parts of the output were:

Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; preset: disabled)
Active: active (waiting)
Trigger: Mon 2026-08-31 01:32:52 BST; 6 days left

This confirms that the weekly TRIM timer is enabled and waiting for its next scheduled run.

As a final check, I ran:

lsblk -D

The relevant part now showed:

nvme0n1              0      512B       2T         0
├─nvme0n1p1          0      512B       2T         0
├─nvme0n1p2          0      512B       2T         0
└─nvme0n1p3          0      512B       2T         0
  └─archlinux        0      512B       2T         0

The encrypted archlinux mapping now reports the same discard granularity and maximum discard size as the underlying NVMe device, confirming that discard is being passed through successfully.

A final cryptsetup status check also shows discard enabled on the active mapping:

sudo cryptsetup status archlinux

The relevant line is:

flags:   discards

This confirms that discard is enabled on the currently active LUKS mapping as well as being stored persistently in the LUKS2 metadata.