Using Linux as a guide, I implemented the `relatime' mount option as mentioned in the Hurd's Contributing page.
diff -ruN a/hurd/libdiskfs/conch-fetch.c b/hurd/libdiskfs/conch-fetch.c --- a/hurd/libdiskfs/conch-fetch.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/conch-fetch.c 2020-09-09 15:32:43.000000000 -0700 @@ -58,7 +58,7 @@ cred->po->np->dn_set_mtime = 1; mod = 1; } - if (cred->mapped->accessed && ! _diskfs_noatime) + if (cred->mapped->accessed && atime_should_update (cred->po->np)) { cred->po->np->dn_set_atime = 1; mod = 1; diff -ruN a/hurd/libdiskfs/diskfs.h b/hurd/libdiskfs/diskfs.h --- a/hurd/libdiskfs/diskfs.h 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/diskfs.h 2020-09-09 23:49:31.000000000 -0700 @@ -1046,7 +1046,9 @@ diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred); /* If disk is not readonly and the noatime option is not enabled, set - NP->dn_set_atime. */ + NP->dn_set_atime. If relatime is enabled, only set NP->dn_set_atime + if the atime has not been updated today, or if ctime or mtime are + more recent than atime */ void diskfs_set_node_atime (struct node *np); /* If NP->dn_set_ctime is set, then modify NP->dn_stat.st_ctim diff -ruN a/hurd/libdiskfs/file-statfs.c b/hurd/libdiskfs/file-statfs.c --- a/hurd/libdiskfs/file-statfs.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/file-statfs.c 2020-09-08 02:21:25.000000000 -0700 @@ -43,6 +43,8 @@ statbuf->f_flag |= ST_SYNCHRONOUS; if (_diskfs_noatime) statbuf->f_flag |= ST_NOATIME; + else if (_diskfs_relatime) + statbuf->f_flag |= ST_RELATIME; diskfs_set_statfs (statbuf); diff -ruN a/hurd/libdiskfs/init-init.c b/hurd/libdiskfs/init-init.c --- a/hurd/libdiskfs/init-init.c 2020-09-10 02:49:31.000000000 -0700 +++ b/hurd/libdiskfs/init-init.c 2020-09-06 22:24:18.000000000 -0700 @@ -38,6 +38,7 @@ int _diskfs_nosuid, _diskfs_noexec; int _diskfs_noatime; +int _diskfs_relatime; struct hurd_port _diskfs_exec_portcell; diff -ruN a/hurd/libdiskfs/node-times.c b/hurd/libdiskfs/node-times.c --- a/hurd/libdiskfs/node-times.c 2020-09-10 02:49:31.000000000 -0700 +++ b/hurd/libdiskfs/node-times.c 2020-09-09 23:47:15.000000000 -0700 @@ -24,12 +24,48 @@ #include "priv.h" #include <maptime.h> +/* If the disk is not readonly and noatime is not set, then check relatime + conditions: if either `np->dn_stat.st_mtim.tv_sec' or + `np->dn_stat.st_ctim.tv_sec' is less than `np->dn_stat.st_atim.tv_sec', + or if the atime is greater than 24 hours old, return true. + */ +int +atime_should_update (struct node *np) +{ + if (_diskfs_noatime) + return 0; + + if (_diskfs_relatime) + { + /* Update atime if mtime is younger than atime. */ + if (np->dn_stat.st_mtim.tv_sec > np->dn_stat.st_atim.tv_sec) + return 1; + /* Update atime if ctime is younger than atime. */ + else if (np->dn_stat.st_ctim.tv_sec > np->dn_stat.st_atim.tv_sec) + return 1; + /* Update atime if current atime is more than 24 hours old. */ + else + { + struct timeval t; + maptime_read (diskfs_mtime, &t); + if ((long)(t.tv_sec - np->dn_stat.st_atim.tv_sec) >= 24 * 60 * 60) + return 1; + } + return 0; + } + + return 1; /* strictatime */ +} + /* If disk is not readonly and the noatime option is not enabled, set - NP->dn_set_atime. */ + NP->dn_set_atime. If relatime is enabled, only set NP->dn_set_atime + if the atime has not been updated today, or if ctime or mtime are + more recent than atime */ void diskfs_set_node_atime (struct node *np) { - if (!_diskfs_noatime && !diskfs_check_readonly ()) + np->dn_set_atime = 0; + if (!diskfs_check_readonly () && atime_should_update (np)) np->dn_set_atime = 1; } diff -ruN a/hurd/libdiskfs/opts-append-std.c b/hurd/libdiskfs/opts-append-std.c --- a/hurd/libdiskfs/opts-append-std.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/opts-append-std.c 2020-09-09 15:06:06.000000000 -0700 @@ -42,6 +42,8 @@ err = argz_add (argz, argz_len, "--no-exec"); if (!err && _diskfs_noatime) err = argz_add (argz, argz_len, "--no-atime"); + else if (!err && _diskfs_relatime) + err = argz_add (argz, argz_len, "--relatime"); if (!err && _diskfs_no_inherit_dir_group) err = argz_add (argz, argz_len, "--no-inherit-dir-group"); diff -ruN a/hurd/libdiskfs/opts-common.c b/hurd/libdiskfs/opts-common.c --- a/hurd/libdiskfs/opts-common.c 2020-09-10 02:49:31.000000000 -0700 +++ b/hurd/libdiskfs/opts-common.c 2020-09-07 00:31:48.000000000 -0700 @@ -47,6 +47,7 @@ "Do not update file access times on disk for reads"}, {"noatime", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, {"atime", OPT_ATIME, 0, 0, "Do update file access times for reads normally"}, + {"strictatime", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, {"no-inherit-dir-group", OPT_NO_INHERIT_DIR_GROUP, 0, 0, "Create new nodes with gid of the process"}, {"nogrpid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, @@ -55,5 +56,8 @@ "Create new nodes with gid of parent dir"}, {"grpid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, {"bsdgroups", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, + {"relatime", 'R', 0, 0, + "Only update access times once daily or if older than change time " + "or modification time."}, {0, 0} }; diff -ruN a/hurd/libdiskfs/opts-std-runtime.c b/hurd/libdiskfs/opts-std-runtime.c --- a/hurd/libdiskfs/opts-std-runtime.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/opts-std-runtime.c 2020-09-09 01:06:22.000000000 -0700 @@ -33,7 +33,7 @@ struct parse_hook { int readonly, sync, sync_interval, remount, nosuid, noexec, noatime, - noinheritdirgroup; + noinheritdirgroup, relatime; }; /* Implement the options in H, and free H. */ @@ -80,6 +80,8 @@ _diskfs_noexec = h->noexec; if (h->noatime != -1) _diskfs_noatime = h->noatime; + else if (h->relatime != -1) + _diskfs_relatime = h->relatime; if (h->noinheritdirgroup != -1) _diskfs_no_inherit_dir_group = h->noinheritdirgroup; @@ -100,10 +102,16 @@ case 'u': h->remount = 1; break; case 'S': h->nosuid = 1; break; case 'E': h->noexec = 1; break; - case 'A': h->noatime = 1; break; + case 'A': + { + h->relatime = -1; + h->noatime = 1; + break; + } + case 'R': h->relatime = 1; break; case OPT_SUID_OK: h->nosuid = 0; break; case OPT_EXEC_OK: h->noexec = 0; break; - case OPT_ATIME: h->noatime = 0; break; + case OPT_ATIME: h->noatime = h->relatime = 0; break; case OPT_NO_INHERIT_DIR_GROUP: h->noinheritdirgroup = 1; break; case OPT_INHERIT_DIR_GROUP: h->noinheritdirgroup = 0; break; case 'n': h->sync_interval = 0; h->sync = 0; break; @@ -129,7 +137,7 @@ h->sync = diskfs_synchronous; h->sync_interval = -1; h->remount = 0; - h->nosuid = h->noexec = h->noatime = h->noinheritdirgroup = -1; + h->nosuid = h->noexec = h->noatime = h->noinheritdirgroup = h->relatime = -1; /* We know that we have one child, with which we share our hook. */ state->child_inputs[0] = h; diff -ruN a/hurd/libdiskfs/opts-std-startup.c b/hurd/libdiskfs/opts-std-startup.c --- a/hurd/libdiskfs/opts-std-startup.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/opts-std-startup.c 2020-09-07 16:10:31.000000000 -0700 @@ -86,10 +86,22 @@ TOGGLE (diskfs_readonly, 'r', 'w'); TOGGLE (_diskfs_nosuid, 'S', OPT_SUID_OK); TOGGLE (_diskfs_noexec, 'E', OPT_EXEC_OK); - TOGGLE (_diskfs_noatime, 'A', OPT_ATIME); TOGGLE (_diskfs_no_inherit_dir_group, OPT_NO_INHERIT_DIR_GROUP, OPT_INHERIT_DIR_GROUP); #undef TOGGLE + /* The next three cases must be done manually to avoid duplicates */ + case 'A': + _diskfs_noatime = 1; + break; + + case 'R': + _diskfs_relatime = 1; + break; + + case OPT_ATIME: /* strictatime. */ + _diskfs_noatime = 0; + _diskfs_relatime = 0; + break; case 's': if (arg == NULL) diff -ruN a/hurd/libdiskfs/priv.h b/hurd/libdiskfs/priv.h --- a/hurd/libdiskfs/priv.h 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/priv.h 2020-09-09 23:50:09.000000000 -0700 @@ -38,6 +38,10 @@ /* This relaxes the requirement to set `st_atim'. */ extern int _diskfs_noatime; +/* Will set `st_atim' if it has not been updated in 24 hours or + if `st_ctim' or `st_mtim' are younger than `st_atim'. */ +extern int _diskfs_relatime; + /* This enables SysV style group behaviour. New nodes inherit the GID of the user creating them unless the SGID bit is set of the parent directory. */ @@ -98,6 +102,13 @@ links, then request soft references to be dropped. */ void _diskfs_lastref (struct node *np); +/* If the disk is not readonly and noatime is not set, then check relatime + conditions: if either `np->dn_stat.st_mtim.tv_sec' or + `np->dn_stat.st_ctim.tv_sec' is less than `np->dn_stat.st_atim.tv_sec', + or if the atime is greater than 24 hours old, return true. + */ +int atime_should_update (struct node *np); + /* Number of outstanding PT_CTL ports. */ extern int _diskfs_ncontrol_ports; diff -ruN a/hurd/libdiskfs/rdwr-internal.c b/hurd/libdiskfs/rdwr-internal.c --- a/hurd/libdiskfs/rdwr-internal.c 2020-07-18 12:08:35.000000000 -0700 +++ b/hurd/libdiskfs/rdwr-internal.c 2020-09-09 15:34:40.000000000 -0700 @@ -49,7 +49,7 @@ { if (dir) np->dn_set_mtime = 1; - else if (! _diskfs_noatime) + else if (atime_should_update (np)) np->dn_set_atime = 1; } @@ -70,7 +70,7 @@ { if (dir) np->dn_set_mtime = 1; - else if (!_diskfs_noatime) + else if (atime_should_update (np)) np->dn_set_atime = 1; }