What is Discard And TRIM Support-Best Embedded Linux Training Online

Discard And TRIM Support
A free linux device drivers course lesson on how Linux tells flash storage which blocks are really free
Chapter 7 · Storage
~15 min read
Hands-on labs included

Deleting a file on Linux is cheap for a reason that used to not matter, and now matters a great deal: the filesystem only updates its own bookkeeping (the directory entry and the free-space bitmap), it doesn’t actually erase the underlying sectors. On a spinning hard disk that’s a harmless optimization. On flash storage it creates a hidden cost. This lesson, part of our free linux device drivers course and free embedded linux course series, explains why, and shows how the discard/TRIM mechanism fixes it.

discard TRIM flash translation layer fstrim eMMC free linux kernel development course

What You Will Learn

  • Why deleting a file doesn’t actually free space at the flash chip level
  • How the discard/TRIM mechanism closes that gap between filesystem and flash controller
  • How to check whether your storage device and driver support discard
  • The difference between mount-time discard and periodic fstrim
  • Common pitfalls when enabling discard on embedded products

Prerequisites

  • This lesson builds directly on Flash Filesystem Selection Guide — read that first if you haven’t
  • Comfort running commands as root and reading /sys files

The Stale Data Problem

When you delete a file on any filesystem, the operating system removes the directory entry and marks the data blocks as free in its own metadata. It does not, as a rule, overwrite the sectors that used to hold the file’s contents — there’s no need to, since nothing will read them again through the filesystem.

On a plain hard disk, that’s the end of the story. On managed flash, it isn’t, because the flash translation layer (FTL) inside the eMMC or SSD controller has no visibility into filesystem metadata. From the controller’s point of view, those sectors still contain valid data, because nobody told it otherwise. The FTL will happily keep relocating and garbage-collecting that stale data during wear leveling — real work spent preserving bytes nobody wants anymore.

The Visibility Gap Between Filesystem And Controller
Filesystem: [file deleted] → sectors marked free in FS metadata only | | (no signal sent, by default) v Flash controller: still sees those sectors as “live” data → keeps copying them during garbage collection → wastes erase cycles on data nobody wants

Enter discard / TRIM

The fix is a small addition to the storage command set that lets the OS explicitly tell the controller “these sectors no longer matter, you don’t need to preserve their contents.” The exact command name depends on the storage interface:

InterfaceCommand nameLinux term
SATATRIMdiscard
SCSIUNMAPdiscard
MMC/eMMCERASEdiscard
NVMeDeallocatediscard

Linux exposes all of these under one umbrella name: discard. Once the filesystem sends a discard request for a range of sectors, the controller is free to skip them entirely during garbage collection, or even zero them out immediately, depending on the device.

Checking Whether Your Device Supports Discard

Support for discard isn’t universal, and it isn’t automatic just because the chip is flash-based — the device firmware and the kernel block driver both have to cooperate. You can check the block layer’s queue parameters directly under /sys:

$ grep -s "" /sys/block/mmcblk1/queue/discard_*
/sys/block/mmcblk1/queue/discard_granularity:524288
/sys/block/mmcblk1/queue/discard_max_bytes:4294967295
/sys/block/mmcblk1/queue/discard_zeroes_data:0

Three fields matter here:

  • discard_granularity — the smallest chunk the device can discard in one operation. Note it lines up closely with the erase block size we measured with Flashbench in the previous lesson — that’s not a coincidence.
  • discard_max_bytes — the largest single discard request the device will accept.
  • discard_zeroes_data — if set to 1, discarded sectors are guaranteed to read back as zero; if 0, their contents are undefined until overwritten.

If a device or its driver doesn’t support discard at all, every one of these fields reads back as zero.

Two Ways To Trigger Discard

1. Mount-time discard

Both ext4 and F2FS accept a mount option that sends a discard request synchronously, as part of every delete or overwrite operation:

# mount -t ext4 -o discard /dev/mmcblk1p2 /mnt/data

This keeps the flash controller’s view of free space up to date in real time, but it does add a small amount of latency to every write path, since each delete now triggers an extra command to the device.

2. Periodic fstrim

The alternative is to mount normally (without -o discard) and instead run the fstrim command on a schedule — typically via a systemd timer or a cron job once a day or once a week. fstrim operates on an already-mounted filesystem and walks its free-space map, discarding everything that’s currently unused in one batch:

$ sudo fstrim -v /mnt/data
/mnt/data: 512983040 bytes were trimmed

The -v flag reports how many bytes were freed at the device level — a useful number to log if you’re debugging why a product’s flash appears to be wearing out faster than expected.

A Minimal Discard-Aware Maintenance Script

Here’s an original example of a small maintenance script suitable for a systemd timer on an embedded board, discarding all mounted flash filesystems that support it:

#!/bin/sh
# ep_trim_flash.sh — trim every mounted filesystem that supports discard
for mnt in $(awk '$3 == "ext4" || $3 == "f2fs" {print $2}' /proc/mounts); do
    dev=$(findmnt -n -o SOURCE --target "$mnt")
    gran=$(cat /sys/class/block/$(basename "$dev")/queue/discard_granularity 2>/dev/null || echo 0)
    if [ "$gran" != "0" ]; then
        echo "Trimming $mnt ($dev, granularity ${gran} bytes)"
        fstrim -v "$mnt"
    else
        echo "Skipping $mnt ($dev) — discard not supported"
    fi
done
$ sudo ./ep_trim_flash.sh
Trimming / (/dev/mmcblk1p2, granularity 524288 bytes)
/: 512983040 bytes were trimmed
Skipping /mnt/usb (/dev/sda1) — discard not supported

Common Mistakes And Troubleshooting

  • Enabling -o discard without checking support first. The mount option is accepted silently even on devices that don’t support discard — it just becomes a no-op, but you lose the opportunity to catch a misconfigured board early. Always check discard_granularity first.
  • Assuming discard implies secure erase. Unless discard_zeroes_data is 1, a discarded sector’s old contents may still be recoverable until overwritten — don’t rely on discard alone for wiping sensitive data.
  • Running fstrim on a busy production system during peak load. A full-filesystem trim can briefly compete with application I/O; schedule it for an idle period.
  • Forgetting removable media. fstrim and mount-time discard only help the filesystems you actually enable them on — a vfat-formatted SD card used for data logging gets none of this benefit.

Best Practices

  • Prefer periodic fstrim over mount-time -o discard on latency-sensitive embedded workloads, since it batches the cost into a maintenance window.
  • Log the bytes-trimmed output over the product’s lifetime — a sudden drop can indicate the filesystem is filling up in a way discard can’t help with.
  • Verify discard support on every new eMMC part number, not just once per product line.

Security Considerations

If your product handles sensitive data and relies on deletion for compliance, don’t treat discard as secure erase. Check discard_zeroes_data, and where guaranteed erasure matters, use a dedicated secure-erase command supported by your storage device instead of assuming a plain discard is sufficient.

Summary / Key Takeaways

  • Deleting a file only updates filesystem metadata — the flash controller doesn’t know the space is free unless it’s told.
  • Linux’s discard mechanism maps onto TRIM/UNMAP/ERASE/Deallocate depending on the underlying interface.
  • Check /sys/block/<device>/queue/discard_* before relying on discard support.
  • Use mount-time -o discard for real-time cleanup or periodic fstrim for batched, lower-latency maintenance.

Conclusion

Discard support is one of those features that costs almost nothing to enable correctly and quietly extends the useful life of your product’s flash storage. The key is checking support before assuming it, and picking the trigger mechanism — mount-time or periodic — that matches your workload’s latency budget. Next in this chapter, we’ll put this all together and walk through building and mounting an ext4 filesystem tuned for flash from scratch.

FAQ

What is the difference between discard and TRIM?

TRIM is the SATA-specific command name; Linux uses “discard” as a generic term covering TRIM, SCSI UNMAP, MMC ERASE, and NVMe Deallocate.

Does enabling discard slow down my embedded product?

Mount-time discard adds a small latency cost to every delete/overwrite. Periodic fstrim avoids that by batching the work into a scheduled maintenance window instead.

How do I know if my eMMC chip supports discard?

Check /sys/block/<device>/queue/discard_granularity — if it reads 0, the device or driver doesn’t support it.

Is discard the same as securely wiping data?

Not unless discard_zeroes_data is 1. Otherwise the old data may still be recoverable from the chip until it’s physically overwritten.

Which filesystems support the discard mount option?

Both ext4 and F2FS support -o discard, along with several other Linux filesystems designed with flash or SSD storage in mind.

Should I use fstrim or mount-time discard on an embedded board?

For most embedded workloads, periodic fstrim via a systemd timer is the safer default since it keeps discard cost off the hot write path.

Keep Learning Embedded Linux Storage

This lesson is part of a free, complete embedded Linux and kernel development course.

Browse the Free Course Next Lesson: Ext4 For Flash Storage

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *