Understanding Unix filesystem timestamps
Published on 2022-10-25.
The POSIX standard requires that operating systems maintain filesystem metadata that record when each file was last accessed. Let's take a look at what all that means.
In my previous tutorial, Void Linux root on an encrypted ZFS mirror with syslinux MBR and ZFSBootMenu, I briefly touched on the ZFS properties atime
and relatime
, but didn't feel satisfied with leaving a brief note about the topic. I decided to delete what I had written and link to this article instead.
A lot of information on the Internet about filesystem timestamps are either outdated or simply misunderstood. Some people also tend to generalize a specific option's pros and cons across all setups, not knowing when the option is actually appropriate. For example, I might think that setting atime
to on
is unconditionally bad because it will have a detrimental effect on the performance of the filesystem without knowing that atime
is required by some applications in order to function properly.
The POSIX standard mandates that metadata for three timestamps are stored in the filesystem regarding each file. These three timestamps are:
- atime - the access timestamp of the last read.
- mtime - the modification timestamp of the last write.
- ctime - the status change timestamp of the last change to the file’s meta-information.
An example of a change to the ctime property is when the file permissions change. Changing file permissions doesn't access the file itself, so atime doesn't change. The file is also not modified in any way, so the mtime options also doesn't change. Still, we have changed the permissions of the file itself, and this must be registered somewhere. The POSIX standard gives this job to the ctime field.
But why would we need to store that information in the first place? Well, if we make a backup of the file, a backup tool may need to know if the file has changed in order to determine if a new backup is required, or if it can simply skip the file because nothing has changed. Another operation that also changes the ctime option is renaming a file.
As you can properly guess, the atime property comes with both a performance penalty and a wear penalty on a very busy filesystem because every read operation on a file also generates a write operation. When you read the file, the atime metadata field is updated, which requires a write.
So, a file's atime, mtime, and ctime are set to the current time whenever you read, write, or change the attributes of the file. Searching a directory also counts as reading it. And a file's atime and mtime can be set directly, via the touch command.
On any Unix like operating system, like Linux or BSD, you can display a file's timestamps with the stat
command.
On Arch Linux:
$ stat /bin/ls File: /bin/ls Size: 137744 Blocks: 272 IO Block: 4096 regular file Device: 254,0 Inode: 29897362 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2022-04-21 22:11:19.000000000 +0200 Modify: 2022-04-17 20:21:13.000000000 +0200 Change: 2022-04-21 22:11:19.555074371 +0200 Birth: 2022-04-21 22:11:19.555074371 +0200
On OpenBSD:
$ stat -x /bin/ls File: "/bin/ls" Size: 317048 FileType: Regular File Mode: (0555/-r-xr-xr-x) Uid: ( 0/ root) Gid: ( 7/ bin) Device: 4,0 Inode: 25942 Links: 1 Access: Tue Sep 27 19:40:00 2022 Modify: Tue Sep 27 19:40:00 2022 Change: Thu Oct 20 16:11:01 2022
Each operating system has it's own set of time related mount options that directly control how atime, mtime and ctime is affected. You can take a look at the man page for the mount
command on your operating system to read about each of these options.
Depending on the operating system and filesystem we have some of the following mount options:
- noatime - Do not update the file access time when reading from a file. This option is useful on filesystems where there are large numbers of files and performance is more critical than keeping the file's access time updated (which is very rarely important).
- nodiratime - Disables the writing of access times only for directories while other files still get access times written. noatime implies nodiratime so you do not need to specify both.
- relatime - Update atime relative to mtime or ctime. atime is only updated if the previous atime was earlier than the current mtime or ctime, or if the previous atime is over 24 hours old. This is similar to noatime, but it doesn't break email applications like mutt or other applications that need to know if a file has been read since the last time it was modified.
NOTE! OpenBSD and FreeBSD does not have the relatime option for the mount
command. On OpenBSD the noatime option behaves more like Linux's relatime.
NOTE! OpenZFS controls it's own mount properties and you don't use the mount
command for ZFS. OpenZFS supports relatime regardless of operating system, but the ZFS relatime option behaves different from the Linux mount relatime option, which is important to understand.
On OpenZFS, relatime controls the manner in which atime is updated.
When atime is set to on, and relatime is also set to on, relatime "rules", meaning access time is set relative to mtime and ctime as described above (with the 24 hours rule). If atime is set to on and relatime is set to off, then atime works as it normally would.
If atime is set to off, relatime has no effect whether it is set to on or off.
So in order to get the effect of relatime, both atime and relatime needs to be set to on on OpenZFS.
On Linux, since kernel 4.0, the option lazytime was introduced. lazytime reduces writes to disk by maintaining changes to atime, ctime and mtime timestamps only in memory. The disk timestamps are then updated only if the file inode needs to be updated for some change unrelated to file timestamps, or if a sync to disk occurs, or if an undeleted inode is evicted from memory, or lastly, if more than 24 hours has passed since the last time the in-memory copy was written to disk.
To disable atime, in order to improve both performance and wear of the disks, a filesystem can be mounted with the noatime option when needed. On ZFS this is done by setting the atime option to off for the specific pool and dataset.
However, turning atime off can break certain applications like mail related applications. As such, on FreeBSD, atime is enabled on the /var/mail
directory.
NOTE! The reason why atime is required by some mail applications is because they compare mtime and atime to determine if the mail is read or not. Some backup applications also require atime to be enabled in order to function correctly.
A less "drastic" alternative to completely disabling atime is to use relatime. relatime was developed to mitigate the problems that disabling atime can present.
NOTE! By default on most major Linux distribution, all filesystems are now mounted with relatime enabled.
NOTE! The default option of atime on OpenZFS is on, which means that a file's access time is written to the ZFS metadata (not the file itself) every time the file is accessed. This means that we're getting a write to disk every time the file is read. Furthermore, if we leave atime set to on, we also experience an increase in shapshot size because the snapshot retains the original metadata access time, while the running filesystem contains the newly updated access time.
In my humble opinion, the best approach is to manually tune the filesystems to your specific requirements. You can for example choose to disable atime completely for the /
(root partition) and then enable relatime for the /var/spool
or /var/mail
directories, if you need that.
If you know for a fact that you don't need atime, such as if you're running a storage system, disable it by mounting the filesystem with noatime, or if it's ZFS, by setting atime to off for the entire pool and all datasets. This will not only improve performance, but also the wear and tear of the disks, especially if you're using SSDs!
NOTE! A lot of misunderstanding regarding the level of endurance of SSDs exist on the Internet. The fact is that a lot of different things affects both the quality and reliability of an SSD, but the determining factor to wear out an SSD, is writes and erasing.
When you write to a NAND cell, or when you erase it, the electrons jump through the insulating layers via the Fowler-Nordheim Tunneling and that is what eventually physically wears our the SSD.
Things like room temperature can effect the data retention of the SSD, and the cell technologies (MLC, TLC, QLC) affect this, but that is not what wears it out, it is only the writing and erasing. Thus, disabling atime definitely has an effect of the wear and tear of an SSD.
Partitions like /home
can be mounted with relatime or noatime depending on your specific needs and the applications being run on your system.
System administration tasks that use file access properties
On most normal day usage of desktops and laptops, you never need to know when a file was last accessed, however as a system administrator running a server, you might need to:
- Know when a configuration file was last changed.
- Know when a specific file was last accessed and possibly changed.
- Locate files that was changed on a specific date.
- Store old files on backup sorted by age.
- Etc.
I recommend that you always specifically set your mount options for the requirements of your system.