TL;DR

A data leakage case had me looking for files a suspect had deleted on an Ubuntu system. So I deleted the same file on ext4 and XFS and went looking for it with every check an NTFS investigator would reach for. On ext4 the folder entry and the map to the data were both zeroes. On XFS the name, most of the inode number and the full map to the data were still there.

Since kernel 5.13 (2021), the ext4 driver wipes a deleted file’s folder entry on purpose, because file names can be sensitive, and it zeroes the block map inside the inode as well. What is left is the inode with its original birth time and a deletion time, and, if you are lucky, older copies of the folder block and the inode in the journal: on kernel 6.18 they were there, on 5.14 they were not. XFS marks the entry free but leaves the name and the low half of the inode number, and the freed inode keeps its extent records, so recovery can be attempted straight from the inode as long as its blocks have not been reused. Image XFS without mounting it.

If you come from Windows investigations, most of your other NTFS checks have nothing to run against. There is no $FILE_NAME to check $STANDARD_INFORMATION with, no $UsnJrnl and no tunneling. One NTFS assumption fails in your favor: neither file system sends TRIM when a file is deleted, so on an SSD the data can outlive the delete until the next scheduled trim. And two things take the place of the lost checks. On my idle test volumes the journal still held every earlier modification time I backdated through, and each inode carries a change counter that rose with every touch and never goes down.

This note started with a data leakage case. The suspect had deleted evidence from an Ubuntu system before it reached us, and the question on the table was the one every investigator knows: what did they delete, and how much of it can we still get back?

Anyone who learned to answer that question on Windows answers it with NTFS reflexes, and NTFS spoils you. The name of a deleted file usually survives in the folder’s $I30 slack with a reference to its MFT record. The record still lists the clusters the data lived in. $FILE_NAME keeps a second set of timestamps to hold the first set to account, and $UsnJrnl writes down that the delete happened and when. On an SSD the data itself may be gone after TRIM, but the story of the file usually is not.

Ubuntu formats its volumes as ext4 by default, and I did not want to lean on any of those reflexes until I knew exactly what an ext4 delete leaves behind. Then a second question followed. RHEL formats its volumes as XFS, so would the same deletion on a RHEL server have left more, or less? I decided to do it the scientific way. I built small ext4 and XFS volumes on Linux kernels 5.14, 6.8, 6.12 and 6.18, created files, backdated them, renamed them and deleted them, then read the raw volume to see what was left. And because many investigators come to Linux with those NTFS reflexes from Windows cases, I compared every step with what NTFS would have given them.

So the sections below follow those reflexes. A few translate with a small adjustment. Two fail outright, and one of those two is the reason this note has the title it has.

The companion note, Reading Linux timestamps, covers what the four timestamps on an inode mean. This one is about the structures around them.

Before you read

This is written for investigators who already work with NTFS at the structure level: MFT records and their attributes, $STANDARD_INFORMATION against $FILE_NAME, $I30 slack, $LogFile and $UsnJrnl. On the Linux side you should be comfortable at a shell and have at least seen debugfs and xfs_db. Everything here applies to ext4 and XFS as current RHEL and Ubuntu releases format them, on kernel 5.14 and later; where the kernel version changes the answer, the text says so. How everything was measured is in Reproduce it at the end.

1. NTFS reflex: compare $STANDARD_INFORMATION with $FILE_NAME

The first timestomping check most of us learned has nothing to compare on Linux. An MFT record carries M, A, C and B in $STANDARD_INFORMATION and again in every $FILE_NAME attribute. A file with a long name usually has two $FILE_NAME attributes, one for the long name and one for the 8.3 short name, and every hard link adds another, so an NTFS file carries eight, twelve or more timestamps. Tools that set timestamps reach $STANDARD_INFORMATION easily and $FILE_NAME much less easily, and the mismatch gives them away.

On ext4 and XFS the inode does the job of the MFT record, and it carries four timestamps, once. A folder entry holds a name, an inode number and a file type, nothing else. A hard link is just another folder entry pointing at the same inode, so it adds a name and no timestamps. Set the inode’s times and there is no second copy anywhere in the live file system that disagrees.

The record is thinner in another way a Windows examiner takes for granted. NTFS keeps a small file’s contents inside its MFT record, and ext4 can do the same with its inline-data feature, which stores up to about 60 bytes in the inode. Neither RHEL nor Ubuntu turns that feature on when it formats a volume, and XFS has no inline data for regular files at all. On both, a 20-byte test file got a data block of its own. What does live inside the inode is a short symbolic link target, a small folder’s entries on XFS, and small extended attributes such as security labels.

The replacement is a counter that only the file system writes. $STANDARD_INFORMATION records the update sequence number of a file’s last change. The inode has its own counter instead: an inode version on ext4 and a change count on XFS. No interface that sets timestamps can reach either one.

  • On ext4 the version rose by one on creation, on every touch, whether backdating or forward-dating, on chmod and on an append. Reads and renames left it alone.
  • On XFS the change count rose on the same changes and on renames; a read moved it only when it updated the access time. XFS also records the log sequence number of the inode’s last write, which only ever increases.

XFS: the change counter under touch

touch -m -d '2001-01-01 00:00:00'  mtime Mon Jan  1 00:00:00 2001  change_count 7
touch -d '2030-01-01 00:00:00'     mtime Tue Jan  1 00:00:00 2030  change_count 8

The backdating moved the timestamp twenty-nine years and the counter one step forward. I got the same on all five test systems: every backdate, forward-date and chmod added exactly one, and nothing ever took one away. It is tempting to call that a timestomping detector, but the kernel promises less. Its own documentation says the value shows only that the inode changed, not how and not how much, and each file system decides the size of its own steps. So a high counter tells you a file has been changed more often. It does not tell you when, or why.

That also decides what you can compare it with. Files installed by the same package, or dropped by the same deployment on the same afternoon, should have lived the same life, and one whose modification time matches the rest of its batch while its counter sits well above them has been touched since. A neighbor in the same folder with its own history proves nothing either way. Starting values differed between my systems as well, 1 to 3 on ext4 and 5 to 6 on XFS. And an attacker who is root and writes to the block device directly can rewrite the counter like any other field.

2. NTFS reflex: ask $UsnJrnl what happened

Neither file system keeps a change journal. There is no record of operations with reasons such as file created or data overwritten, and no interface to query one. For anyone coming from Windows that is the biggest loss, because on NTFS $UsnJrnl is often the only place a deleted file’s name and the time of its deletion survive together.

The rest of the volume’s own metadata maps across more easily. ext4 reserves its first inodes the way NTFS reserves its first MFT records: on every test volume, inode 2 was the root folder, inode 7 the reserve used to grow the volume, inode 8 the journal and inode 11 the lost+found folder, with 1, 3 to 6, 9 and 10 reserved but empty. XFS splits the volume into allocation groups and starts each one with its own copy of the superblock and headers for its free space and its inodes, so that allocations in different groups do not wait on each other. With the mkfs.xfs defaults, a volume got four groups up to 4 TB and then one per TB, because a group holds at most 1 TB; other format options give other layouts.

$Secure has no counterpart either. NTFS stores each distinct security descriptor once and lets every file point to it, because most files share the same few descriptors and storing them per file would waste space. On Linux the owner, group and permission bits live in each inode, and access control lists and security labels are extended attributes, inside the inode when they fit. ext4 can share one external attribute block among files with identical attributes, which is the closest it comes to $Secure’s sharing.

The journal turned out to be the closest thing to a history. ext4 keeps its journal in reserved inode 8 and XFS keeps a log area inside the volume. Like $LogFile, both write a copy of changed metadata before applying it in place. I set one file’s modification time to 2001, 2002, 2003 and 2004 in turn, flushing to disk after each, and unmounted cleanly. The inode held only 2004. A raw search of the ext4 journal and the XFS log still found all three earlier values.

The journal exists to survive a crash, not to keep a record for us, and it goes round in a circle. The old copies I found were leftovers that nothing had written over yet. My test volumes sat idle, so they had all the time in the world. I did not measure how long the copies last on a server doing real work, and there they may be gone within minutes. Image early and you give yourself the best chance.

3. NTFS reflex: carve for records around the $MFT

On NTFS this habit was already weaker than most people think. The boot sector gives the cluster where the $MFT starts, and NTFS keeps an area after it, the MFT zone, free of ordinary files so the $MFT can grow without fragmenting. Microsoft documents the zone as 12.5% of the volume by default, and a registry value can make it larger. When the rest of the volume fills up, NTFS hands the zone over to ordinary files, and from then on the $MFT grows wherever it finds room. On a full volume with a damaged partition table, carving for records only around the start of the $MFT or inside the zone can miss a large share of them.

ext4 is easier than NTFS here: every inode sits where arithmetic puts it. The inode tables are allocated at format time, one per block group, at fixed block ranges, and they never move, grow or fragment. On a 300 MB Ubuntu test volume, group 0’s table occupied blocks 45 to 1644; RHEL formats the same volume into 38 smaller groups instead of 3, with the same principle. An inode’s group is (inode number − 1) divided by the inodes per group, its slot is the remainder, and its byte offset is the start of that group’s table plus the slot times the inode size. The superblock and group descriptors record every number you need. The price of a fixed table is that an ext4 volume can run out of inodes while it still has free space.

XFS has no table at all. It allocates inodes in chunks of 64, a constant of the format (with the sparse-inodes feature a chunk can be partly allocated), when it needs them and wherever an allocation group has room, and records the chunks in that group’s inode index. The inode number itself encodes the location: the high bits give the allocation group, the next bits the block within the group, and the lowest bits the slot within the block. The byte offset is (group × blocks per group + block) × block size + slot × inode size. On a test volume with 19,200 blocks per group, 4 KB blocks and eight 512-byte inodes per block, inode 262,272 decodes to group 1, block 16, slot 0, which is byte 78,708,736 of the volume. New top-level folders went to the next group in turn, 0, 1, 2, 3 and back to 0, and each file landed in its folder’s group.

4. NTFS reflex: recover the file from $I30 slack and its MFT record

This is where the two file systems split, and where ext4 left me with nothing. The NTFS routine is familiar: find the name in $I30 slack, follow its MFT reference to the record, read the data runs, collect the clusters. On ext4 the same routine used to work. Deleting an entry only stretched the previous entry over it, and debugfs would list the deleted name and its inode number. So I deleted a file and asked:

ext4: a folder before and after rm invoice_q3.xlsx

$ debugfs -R 'ls -d -l /d' e.img        (before)
12 40755 .
2 40755 ..
13 100644 report.pdf
14 100644 invoice_q3.xlsx
15 100644 notes.txt
$ debugfs -R 'ls -d -l /d' e.img        (after)
12 40755 .
2 40755 ..
13 100644 report.pdf
15 100644 notes.txt

The -d option asks for deleted entries, and there were none. I searched the folder’s raw blocks for the name to rule out the tool: the live names were there, the deleted one was not, and neither was the inode number. The same held on every kernel I tested, and for the old name of a renamed file.

The entry is gone because the driver wipes it on purpose. A kernel patch titled “ext4: wipe ext4_dir_entry2 upon file deletion”, merged for kernel 5.13 in 2021, zeroes every field of a deleted entry except its length, and does the same when entries move during a split of a large folder’s index. The patch discussion gives the reason: file names can themselves be sensitive. Because it is driver behavior and not a format change, a folder block last written by an older kernel can still hold deleted entries. Anything deleted under 5.13 or later will not.

So I went to the inode instead, and the inode was there:

$ debugfs -R 'stat <14>' e.img
Inode: 14
Links: 0
 ctime: 0x6ac12134:e4cd97dc -- Sat Oct  3 15:37:24 2026
 atime: 0x6ac12133:95a53afc -- Sat Oct  3 15:37:23 2026
 mtime: 0x6ac12134:e4cd97dc -- Sat Oct  3 15:37:24 2026
crtime: 0x6ac12133:95a53afc -- Sat Oct  3 15:37:23 2026
 dtime: 0x6ac12134:(e4cd97dc) -- Sat Oct  3 15:37:24 2026

M and C now carry the deletion time recorded in dtime, and the birth time is the original one. What the inode no longer has is the map to the data. Reading it raw, the extent records were all zero on every kernel, on a frozen volume and after unmounting. On NTFS that would be the equivalent of a deleted MFT record with its data runs blanked out.

The way back runs through the journal. The journal can hold an older copy of the folder block with the entry intact and an older copy of the inode with its block map, and the data blocks stay on disk until something reuses them. That is how extundelete, ext4magic and the AlexSta Velociraptor fork’s ext4 journal plugin recover ext4 files. Whether the copies exist is luck: on kernel 6.18 the journal held the deleted entry with the correct inode number beside the name, and on kernel 5.14 the same test left no copy at all. For larger files whose block map spills out of the inode into separate index blocks, research published in 2012 found those index blocks are not zeroed, which gives a second route.

XFS kept almost everything. In a folder large enough to use data blocks, a deleted entry is marked free by overwriting its first four bytes with a free marker and a length. Those four bytes are the high half of the eight-byte inode number. The low half and the name stay:

XFS: the same delete in a folder of 81 files

invoice_q3.xlsx was inode 212 (0xd4)
00 07 c8 ff ff 05 80 00 00 00 d4 0f 69 6e 76 6f  ............invo
69 63 65 5f 71 33 2e 78 6c 73 78                 ice_q3.xlsx

Read it from the name backwards: 0f is the name length, 00 00 00 d4 is the low half of the inode number, 212, and ff ff 05 80 is the free marker and length that overwrote the high half. On my test volumes the low half always pointed straight at the deleted file, but I wanted to know when that stops being true. An XFS inode number packs the allocation group, the block within the group and the slot within the block together, so how wide it gets depends on the volume. I did the arithmetic for the mkfs.xfs defaults of four groups, 4 KB blocks and 512-byte inodes: every inode number fits in 32 bits on volumes up to 2 TiB, so there the low half is the whole answer. On a bigger volume the lost half carries the top bits of the group number. That sounds worse than it is, because there are only a handful of groups to try, so try each one rather than assuming the missing half was zero. In a small folder kept inside the inode, the remaining entries are packed together on delete, and old names may or may not linger in the spare bytes.

The freed inode was the bigger surprise. XFS zeroes the mode, size, link count and extent count, sets C to the deletion time, keeps M and the birth time, and leaves the extent records themselves in place:

XFS: the freed inode of a deleted 240,000-byte file

                 mode    extent record (start offset, start block, length)
before delete    100644  0, 24, 59
after delete     0       0, 24, 59

The file type and size are gone, the map to its 59 data blocks is not. On kernels 5.14 and 6.18 the map survived on a frozen volume and after a clean unmount. An earlier test with the AlexSta Velociraptor fork on kernel 5.14 had found a clean unmount emptying that area, and I do not yet know which conditions decide it. Until I do, the safe practice is to image an XFS volume without mounting it.

My test file was the easy case, one file in one piece. Real files get split into many extents, some are sparse, and some of their blocks will already have been reused or trimmed by the time you arrive. The size is gone as well, so you have to work out where the last block really ends from the content itself. xfs_undelete, an open-source recovery tool, works from exactly the same leftovers, the extent records XFS never clears, and it sanity-checks every mapping before it trusts one.

One more NTFS reflex needs adjusting: the record number does not identify the file. I created five files, deleted the second and third, and created two more; on both file systems the new files received the deleted files’ numbers. The counterpart of the sequence number in an MFT reference is the inode’s generation number. When ext4 reused inode 18, its generation changed from 2065555774 to 3679271122, so a record that kept both the number and the generation can tell the old file from the new one, and a record that kept only the number cannot. Inode order also matches creation order only where nothing has been deleted: a low number with a recent birth time is normal after a cleanup.

5. NTFS reflex: on an SSD, the deleted data is very likely already gone

This reflex fails in your favor. On Windows, deleting a file on an SSD normally sends TRIM for its clusters straight away, and the deleted data typically reads back as zeros soon after. Neither ext4 nor XFS does that by default. Sending discards at delete time is the discard mount option, which is off unless someone sets it, and Red Hat recommends batch or periodic discard instead. Trimming happens later, in a batch run by a timer: on Ubuntu 24.04 and AlmaLinux 10.2 the weekly fstrim timer was enabled out of the box.

It is tempting to call that a week. It is not. The delete itself leaves the blocks alone, but they stay readable only until the next trim or until the file system hands them to a new file, whichever comes first. If the timer fires an hour after the delete, you had an hour, and on a busy server a reused block can go even sooner. So the real window is anything from minutes to almost seven days. Virtual disks and cloud storage add their own layers, which may pass discards on or trim on a schedule of their own, and since my test volumes were image files I never watched a real SSD do any of this. So check the mount options and when the timer last ran before writing off deleted data on an SSD.

And even a trim is not the end of the story. What a drive returns for a trimmed block is left to its firmware. The ATA standard lets a SATA drive promise zeros, promise the same fixed data on every read, or promise nothing at all, and a drive that promises nothing may still hand you the old data. NVMe drives make the same choice for deallocated blocks. You can ask the drive which one it made: hdparm -I lists “Deterministic read ZEROs after TRIM” on a SATA drive that guarantees zeros, and nvme id-ns shows it in the DLFEAT field. That is worth remembering back on Windows too, where “TRIM ran, so the data is gone” is the same assumption.

6. NTFS reflex: tunneling explains an odd creation time

Linux has no tunneling, so an odd birth time needs another explanation. On NTFS, if a file is deleted or renamed and a new file with the same name appears in the same folder within 15 seconds, the new file inherits the old one’s creation time. Microsoft calls this tunneling, and its original knowledge base article on it, since retired, gave the 15-second default. It exists so that programs that save by deleting and recreating a file keep the original creation date.

I deleted a file and recreated the same name in a single command, on every kernel. The new file’s birth time was always the moment it was recreated. ext4 even handed back the inode number it had just freed, so the new file had the old file’s number and a brand new birth time.

What these structures cannot tell you

None of them says who did anything. The journal copies, the counters and the freed inodes describe what happened to metadata, and they tie it to time only through the same system clock that writes the timestamps. Use them to test a hypothesis built from logs, audit records and shell history.

NTFS to ext4 and XFS at a glance

Every row is documented in the format’s own specification, and most were also measured in my tests. In the source column, ext4 docs is the kernel’s ext4 on-disk documentation, XFS spec is XFS Algorithms and Data Structures, and measured means I read it from a test volume image.

NTFSext4XFSSource
$MFT and its recordsInode tables at fixed offsets, one per block groupInodes created in chunks of 64 inside each allocation groupext4 docs, XFS spec; measured
MFT zone, 12.5% by defaultNone needed; tables never growNone; inodes go where there is roomMicrosoft; ext4 docs, XFS spec
Sequence number in the MFT referenceInode generation, new value when the number is reusedInode generationext4 docs, XFS spec; measured on ext4
$STANDARD_INFORMATION timesInode M, A, C, BInode M, A, C, Bext4 docs, XFS spec; measured
$FILE_NAME times, one set per nameNoneNoneext4 docs, XFS spec (folder entry layout); measured
Last USN in $STANDARD_INFORMATIONInode versionChange count and log sequence numberext4 docs, XFS spec; measured
Resident dataOff by default (inline data is optional); short symlinks in the inodeNone for files; short symlinks and small folders in the inodeext4 docs, XFS spec; measured
$I30 entries and slackNo times; deleted entries wiped from kernel 5.13No times; deleted names kept with half the inode numberKernel 5.13 commit, XFS spec; measured
Deleted record keeps its data runsNo: block map zeroed; look in the journalUsually: extent records stayed in the freed inode in my testsFairbanks (ext4), xfs_undelete (XFS); measured on both
Metafiles in the first MFT recordsReserved inodes 1 to 10Headers at the start of each allocation groupext4 docs, XFS spec; measured
$LogFileJournal in inode 8Log area inside the volumeext4 docs, XFS spec; measured
$SecurePermissions per inode; ACLs and labels as extended attributesThe sameext4 docs (shared attribute blocks)
$UsnJrnlNoneNoneAbsent from both formats’ documentation
TRIM on deleteOnly with the discard mount optionOnly with the discard mount optionRed Hat docs; timer measured
TunnelingNoneNoneMicrosoft (R. Chen); absence measured

Reproduce it

Every behavior above was measured on the five systems below, on small test volumes formatted with each system’s defaults. The volumes were image files attached as loop devices, which is why nothing here tests TRIM on physical flash. Distribution kernels carry backports, so the kernel package matters more than the upstream version it is named after.

SystemKernel packageEnvironmentdebugfsxfs_db
RHEL 9.45.14.0-427.22.1.el9_4Virtual machine1.46.56.3.0
Ubuntu 24.046.8.0-142-genericVirtual machine1.47.06.6.0
AlmaLinux 10.26.12.0-211.7.3.el10_2Virtual machine1.47.16.16.0
Ubuntu 24.046.18.33.2-microsoft-standard-WSL2WSL21.47.06.6.0
RHEL 10.06.18.33.2-microsoft-standard-WSL2WSL21.47.16.11.0

I read every value from the volume image rather than through the mounted file system, which would show the kernel’s view instead of the disk: with debugfs for ext4, xfs_db for XFS, and a raw byte search whose hits I assigned to the structure they fell in, such as a folder’s blocks, an inode, the ext4 journal or the XFS log. The delete tests were read twice, once from a frozen volume and once after unmounting. The excerpts above come from RHEL 9.4 with kernel 5.14. The test harness is available on request.

The tools you need are debugfs with ls -d, stat <inode>, imap and logdump for ext4, and xfs_db in read-only mode with path, inode, convert and print for XFS, where v3.change_count and v3.lsn are the counter fields; xfs_logprint reads the XFS log.

Lessons learned: the four that change how you work

  1. On ext4, the folder and the inode no longer lead you back to the file. From kernel 5.13 the folder entry is wiped, and the inode’s block map is zeroed on every kernel. The journal is the only route back, and it may or may not hold a copy: image early.
  2. On XFS, the trail to the data usually survives the delete. The name stays in the folder with the low half of its inode number, and the freed inode keeps its extent records. Recovery still depends on finding the right inode and on its blocks not being reused. Image without mounting.
  3. No $FILE_NAME check; read the change counter. There is no second set of timestamps to catch timestomping, but the counter rose with every touch in my tests and never goes down. Compare a file only with files that should share its history, and read the counter as how many changes, never when.
  4. Without online discard, deleted SSD data gets a reprieve. Neither file system sends TRIM at delete time unless the volume is mounted with discard; the blocks last until the next scheduled trim or until they are reused.

Also worth knowing

  1. The journal is the nearest thing to $UsnJrnl. On idle test volumes, raw journal space still held every earlier modification time of a backdated file. It is leftover data, not a guaranteed history.
  2. A matching inode number is not the same file. Both file systems reuse numbers at once; the generation number tells the files apart.
  3. ext4 inodes sit at offsets you can compute; XFS inodes are found by decoding their numbers. Neither has an MFT zone, and on NTFS the zone never bounded a carve on a full volume anyway.
  4. No tunneling. A recreated file always gets a new birth time, even when it gets the old inode number.

References

  • Kernel change ext4: wipe ext4_dir_entry2 upon file deletion (L. Rumancik), in the ext4 updates for kernel 5.13 lkml.iu.edu/hypermail/linux/kernel/2104.3/06143.html
  • Kernel change The patch discussion, including the reasoning about sensitive file names lore.kernel.org/all/YIHknqxngB1sUdie@mit.edu/T/
  • Research K. Fairbanks, An analysis of Ext4 for digital forensics, DFRWS 2012: in-inode extents zeroed, extent index nodes not zeroed sciencedirect.com/science/article/pii/S1742287612000357
  • Research H. Pomeranz, the XFS series at Righteous IT, including deleted files righteousit.com/tag/xfs/
  • Recovery tool xfs_undelete: recovering deleted XFS files from the extent records left in freed inodes github.com/ianka/xfs_undelete
  • Kernel source include/linux/iversion.h: what the inode version promises and what it does not github.com/torvalds/linux/blob/master/include/linux/iversion.h
  • Recovery tool ext4magic: recovering deleted ext4 files from journal copies of the inode ext4magic.sourceforge.net/howto_en.html
  • On-disk layout ext4 special inodes, directory entries and extended attributes kernel.org/doc/html/latest/filesystems/ext4/
  • On-disk layout XFS Algorithms and Data Structures: allocation groups, inode numbers, directory blocks, the v3 inode and the log kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
  • NTFS behavior How NTFS reserves space for MFT (originally KB 174619) learn.microsoft.com/troubleshoot/windows-server/backup-and-storage/ntfs-reserves-space-for-mft
  • NTFS behavior R. Chen, The apocryphal history of file system tunnelling, The Old New Thing devblogs.microsoft.com/oldnewthing/20050715-14/?p=34923
  • Discard RHEL 9, Managing file systems: discarding unused blocks (batch, online and periodic discard, fstrim.timer) docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_file_systems/discarding-unused-blocks_managing-file-systems
  • Companion piece Reading Linux timestamps: what MACB actually means on ext4 and XFS /field-notes/reading-linux-timestamps/