summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Jeffrey <ryan@ryanmj.xyz>2020-09-30 21:19:52 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-09-30 21:26:09 +0200
commitda5b44eaf131c748caeedf59b3dc9e42b94c82f0 (patch)
tree12de42e27672510e59aa91100331c458ea3d135e
parent88d7363db23f8dba06ed260e10b5c7f40538565c (diff)
libdiskfs: Add relatime supportv0.9.git20200930
* doc/hurd.texi (diskfs_set_node_atime): Document relatime behavior. * libdiskfs/diskfs.h (diskfs_set_node_atime): Likewise. * libdiskfs/init-init.c (_diskfs_relatime): Add variable. * libdiskfs/file-statfs.c (ST_RELATIME): Define if not defined already. (diskfs_S_file_statfs): Report ST_RELATIME when _diskfs_relatime is set. * libdiskfs/node-times.c (atime_should_update): New function. (diskfs_set_node_atime): Document relatime behavior. Call atime_should_update instead of reading _diskfs_noatime. * libdiskfs/opts-common.c (diskfs_common_options): Add --strictatime and -R/--relatime options. * libdiskfs/opts-std-runtime.c (struct parse_hook): Add relatime field. (set_opts): Set _diskfs_relatime from relatime field. (parse_opt): Parse -R option. * libdiskfs/opts-std-startup.c (parse_startup_opt): Parse -R option. * libdiskfs/priv.h (_diskfs_relatime): Declare variable. (atime_should_update): Declare function. * libdiskfs/opts-append-std.c (diskfs_append_std_options): Add reporting --relatime option. * libdiskfs/conch-fetch.c (iohelp_fetch_shared_data): Call atime_should_update instead of reading _diskfs_noatime. * libdiskfs/rdwr-internal.c (_diskfs_rdwr_internal): Likewise.
-rw-r--r--doc/hurd.texi4
-rw-r--r--libdiskfs/conch-fetch.c2
-rw-r--r--libdiskfs/diskfs.h4
-rw-r--r--libdiskfs/file-statfs.c6
-rw-r--r--libdiskfs/init-init.c1
-rw-r--r--libdiskfs/node-times.c37
-rw-r--r--libdiskfs/opts-append-std.c2
-rw-r--r--libdiskfs/opts-common.c4
-rw-r--r--libdiskfs/opts-std-runtime.c16
-rw-r--r--libdiskfs/opts-std-startup.c14
-rw-r--r--libdiskfs/priv.h11
-rw-r--r--libdiskfs/rdwr-internal.c4
12 files changed, 93 insertions, 12 deletions
diff --git a/doc/hurd.texi b/doc/hurd.texi
index 038d80b6..c3442c8c 100644
--- a/doc/hurd.texi
+++ b/doc/hurd.texi
@@ -3973,7 +3973,9 @@ disk allocation strategies.
@deftypefun void diskfs_set_node_atime (@w{struct node *@var{np}})
If disk is not readonly and the noatime option is not enabled, set
-@code{@var{np}->dn_set_atime}.
+@code{@var{np}->dn_set_atime}. If relatime is enabled, only set
+@code{@var{np}->dn_set_atime} if the atime has not been updated today,
+or if ctime or mtime are more recent than atime.
@end deftypefun
@deftypefun void diskfs_set_node_times (@w{struct node *@var{np}})
diff --git a/libdiskfs/conch-fetch.c b/libdiskfs/conch-fetch.c
index 43a0e870..2a9a5c8f 100644
--- a/libdiskfs/conch-fetch.c
+++ b/libdiskfs/conch-fetch.c
@@ -58,7 +58,7 @@ iohelp_fetch_shared_data (void *arg)
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 --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index dfccf880..2390c64d 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -1046,7 +1046,9 @@ error_t
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 --git a/libdiskfs/file-statfs.c b/libdiskfs/file-statfs.c
index c9fd6f1b..3cc60b4f 100644
--- a/libdiskfs/file-statfs.c
+++ b/libdiskfs/file-statfs.c
@@ -21,6 +21,10 @@
#include "priv.h"
#include "fs_S.h"
+#ifndef ST_RELATIME
+# define ST_RELATIME 64
+#endif /* ST_RELATIME */
+
/* Implement file_getcontrol as described in <hurd/fs.defs>. */
kern_return_t
diskfs_S_file_statfs (struct protid *file,
@@ -43,6 +47,8 @@ diskfs_S_file_statfs (struct protid *file,
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 --git a/libdiskfs/init-init.c b/libdiskfs/init-init.c
index b9a714fe..1c432401 100644
--- a/libdiskfs/init-init.c
+++ b/libdiskfs/init-init.c
@@ -38,6 +38,7 @@ mach_port_t diskfs_fsys_identity;
int _diskfs_nosuid, _diskfs_noexec;
int _diskfs_noatime;
+int _diskfs_relatime;
struct hurd_port _diskfs_exec_portcell;
diff --git a/libdiskfs/node-times.c b/libdiskfs/node-times.c
index 9a6c8dd9..05f558be 100644
--- a/libdiskfs/node-times.c
+++ b/libdiskfs/node-times.c
@@ -24,12 +24,45 @@
#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 greater 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)
+{
+ struct timeval t;
+
+ 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. */
+ 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. */
+ 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 ())
+ if (!diskfs_check_readonly () && atime_should_update (np))
np->dn_set_atime = 1;
}
diff --git a/libdiskfs/opts-append-std.c b/libdiskfs/opts-append-std.c
index b951bf93..98e89dd0 100644
--- a/libdiskfs/opts-append-std.c
+++ b/libdiskfs/opts-append-std.c
@@ -42,6 +42,8 @@ diskfs_append_std_options (char **argz, size_t *argz_len)
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 --git a/libdiskfs/opts-common.c b/libdiskfs/opts-common.c
index d37c2868..841f13c3 100644
--- a/libdiskfs/opts-common.c
+++ b/libdiskfs/opts-common.c
@@ -47,6 +47,7 @@ const struct argp_option diskfs_common_options[] =
"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 @@ const struct argp_option diskfs_common_options[] =
"Create new nodes with gid of parent dir (default)"},
{"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 --git a/libdiskfs/opts-std-runtime.c b/libdiskfs/opts-std-runtime.c
index 177dfaf6..48acbaaf 100644
--- a/libdiskfs/opts-std-runtime.c
+++ b/libdiskfs/opts-std-runtime.c
@@ -33,7 +33,7 @@ std_runtime_options[] =
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 @@ set_opts (struct parse_hook *h)
_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 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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 @@ parse_opt (int opt, char *arg, struct argp_state *state)
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 --git a/libdiskfs/opts-std-startup.c b/libdiskfs/opts-std-startup.c
index a38db99a..e5531a46 100644
--- a/libdiskfs/opts-std-startup.c
+++ b/libdiskfs/opts-std-startup.c
@@ -86,10 +86,22 @@ parse_startup_opt (int opt, char *arg, struct argp_state *state)
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 --git a/libdiskfs/priv.h b/libdiskfs/priv.h
index 5be7c2b5..420323dd 100644
--- a/libdiskfs/priv.h
+++ b/libdiskfs/priv.h
@@ -38,6 +38,10 @@ extern int _diskfs_nosuid, _diskfs_noexec;
/* 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 @@ void _diskfs_control_clean (void *);
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 greater 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 --git a/libdiskfs/rdwr-internal.c b/libdiskfs/rdwr-internal.c
index eec0d6a0..8b2e1319 100644
--- a/libdiskfs/rdwr-internal.c
+++ b/libdiskfs/rdwr-internal.c
@@ -49,7 +49,7 @@ _diskfs_rdwr_internal (struct node *np,
{
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 @@ _diskfs_rdwr_internal (struct node *np,
{
if (dir)
np->dn_set_mtime = 1;
- else if (!_diskfs_noatime)
+ else if (atime_should_update (np))
np->dn_set_atime = 1;
}