Skip to content

Commit 6a19982

Browse files
committed
Implement relative atime mount flag. Relative atime means the operator
wants atime be maintained only when it's older than creation and modification time. For now this only applies to UFS and ext2fs cases. Usage: mount -o relatime <special> <mountpoint>
1 parent e3567b2 commit 6a19982

File tree

8 files changed

+64
-7
lines changed

8 files changed

+64
-7
lines changed

lib/libc/sys/statfs.2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ Identifies the root file system.
142142
The file system is exported read-only.
143143
.It Dv MNT_NOATIME
144144
Updating of file access times is disabled.
145+
.It Dv MNT_RELATIME
146+
Updating of file access times is only done when it is smaller than both creation
147+
and modification times.
145148
.It Dv MNT_USER
146149
The file system has been mounted by a user.
147150
.\".It Dv MNT_IGNORE

sbin/mount/mount.8

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ is useful on file systems where there are large numbers of files and
222222
performance is more critical than updating the file access time (which is
223223
rarely ever important).
224224
This option is currently only supported on local file systems.
225+
.It Cm relatime
226+
Do not update the file access time when reading from a file, if the access
227+
time is already later than both file creation time and file modification
228+
times.
225229
.It Cm noauto
226230
This file system should be skipped when
227231
.Nm

sbin/mount/mount.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ static struct opt {
9797
{ MNT_ASYNC, "asynchronous" },
9898
{ MNT_EXPORTED, "NFS exported" },
9999
{ MNT_LOCAL, "local" },
100+
{ MNT_RELATIME, "relative atime" },
100101
{ MNT_NOATIME, "noatime" },
101102
{ MNT_NOEXEC, "noexec" },
102103
{ MNT_NOSUID, "nosuid" },

sys/fs/ext2fs/ext2_vnops.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,15 @@ ext2_read(struct vop_read_args *ap)
16971697
}
16981698

16991699
if ((error == 0 || uio->uio_resid != orig_resid) &&
1700-
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1700+
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0 &&
1701+
(ip->i_flag & IN_ACCESS) == 0 &&
1702+
((vp->v_mount->mnt_flag & MNT_RELATIME) == 0 ||
1703+
(ip->i_mtime == ip->i_atime ?
1704+
ip->i_mtimensec >= ip->i_atimensec :
1705+
ip->i_mtime >= ip->i_atime) ||
1706+
(ip->i_ctime == ip->i_atime ?
1707+
ip->i_ctimensec >= ip->i_atimensec :
1708+
ip->i_ctime >= ip->i_atime)))
17011709
ip->i_flag |= IN_ACCESS;
17021710
return (error);
17031711
}

sys/kern/vfs_mount.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ static const char *global_opts[] = {
9999
"rw",
100100
"nosuid",
101101
"noexec",
102+
"relatime",
102103
NULL
103104
};
104105

@@ -602,6 +603,14 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
602603
free(opt->name, M_MOUNT);
603604
opt->name = strdup("nonoatime", M_MOUNT);
604605
}
606+
else if (strcmp(opt->name, "norelatime") == 0) {
607+
vfs_freeopt(optlist, opt);
608+
fsflags &= ~MNT_RELATIME;
609+
}
610+
else if (strcmp(opt->name, "relatime") == 0) {
611+
vfs_freeopt(optlist, opt);
612+
fsflags |= MNT_RELATIME;
613+
}
605614
else if (strcmp(opt->name, "noclusterr") == 0)
606615
fsflags |= MNT_NOCLUSTERR;
607616
else if (strcmp(opt->name, "clusterr") == 0) {
@@ -811,7 +820,7 @@ vfs_domount_first(
811820
/* XXXMAC: pass to vfs_mount_alloc? */
812821
mp->mnt_optnew = *optlist;
813822
/* Set the mount level flags. */
814-
mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
823+
mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY | MNT_RELATIME));
815824

816825
/*
817826
* Mount the filesystem.
@@ -933,7 +942,8 @@ vfs_domount_update(
933942
MNT_ILOCK(mp);
934943
mp->mnt_flag &= ~MNT_UPDATEMASK;
935944
mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
936-
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
945+
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY |
946+
MNT_RELATIME);
937947
if ((mp->mnt_flag & MNT_ASYNC) == 0)
938948
mp->mnt_kern_flag &= ~MNTK_ASYNC;
939949
MNT_IUNLOCK(mp);

sys/kern/vfs_subr.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,7 @@ DB_SHOW_COMMAND(mount, db_show_mount)
30043004
MNT_FLAG(MNT_GJOURNAL);
30053005
MNT_FLAG(MNT_MULTILABEL);
30063006
MNT_FLAG(MNT_ACLS);
3007+
MNT_FLAG(MNT_RELATIME);
30073008
MNT_FLAG(MNT_NOATIME);
30083009
MNT_FLAG(MNT_NOCLUSTERR);
30093010
MNT_FLAG(MNT_NOCLUSTERW);
@@ -4526,11 +4527,33 @@ void
45264527
vfs_mark_atime(struct vnode *vp, struct ucred *cred)
45274528
{
45284529
struct mount *mp;
4530+
struct vattr vattr;
45294531

45304532
mp = vp->v_mount;
45314533
ASSERT_VOP_LOCKED(vp, "vfs_mark_atime");
4532-
if (mp != NULL && (mp->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0)
4533-
(void)VOP_MARKATIME(vp);
4534+
4535+
/*
4536+
* Do nothing if the file system is mounted with noatime or
4537+
* marked as read only.
4538+
*/
4539+
if (mp == NULL || (mp->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) != 0)
4540+
return;
4541+
4542+
/*
4543+
* Relative atime: do nothing if both ctime and mtime are
4544+
* smaller than atime.
4545+
*/
4546+
if ((mp->mnt_flag & MNT_RELATIME) == MNT_RELATIME) {
4547+
if (VOP_GETATTR(vp, &vattr, cred) != 0)
4548+
return;
4549+
else {
4550+
if (timespeccmp(&vattr.va_mtime, &vattr.va_atime, < ) &&
4551+
timespeccmp(&vattr.va_ctime, &vattr.va_atime, < ))
4552+
return;
4553+
}
4554+
}
4555+
4556+
(void)VOP_MARKATIME(vp);
45344557
}
45354558

45364559
/*

sys/sys/mount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
259259
#define MNT_NOCLUSTERR 0x0000000040000000ULL /* disable cluster read */
260260
#define MNT_NOCLUSTERW 0x0000000080000000ULL /* disable cluster write */
261261
#define MNT_SUJ 0x0000000100000000ULL /* using journaled soft updates */
262+
#define MNT_RELATIME 0x0000000200000000ULL /* using relative atime */
262263

263264
/*
264265
* NFS export related mount flags.
@@ -295,7 +296,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
295296
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \
296297
MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \
297298
MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \
298-
MNT_NFS4ACLS)
299+
MNT_NFS4ACLS | MNT_RELATIME)
299300

300301
/* Mask of flags that can be updated. */
301302
#define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \

sys/ufs/ffs/ffs_vnops.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,14 @@ ffs_read(ap)
621621

622622
if ((error == 0 || uio->uio_resid != orig_resid) &&
623623
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0 &&
624-
(ip->i_flag & IN_ACCESS) == 0) {
624+
(ip->i_flag & IN_ACCESS) == 0 &&
625+
((vp->v_mount->mnt_flag & MNT_RELATIME) == 0 ||
626+
(DIP(ip, i_mtime) == DIP(ip, i_atime) ?
627+
(DIP(ip, i_mtimensec) >= DIP(ip, i_atimensec)) :
628+
(DIP(ip, i_mtime) >= DIP(ip, i_atime))) ||
629+
(DIP(ip, i_ctime) == DIP(ip, i_atime) ?
630+
(DIP(ip, i_ctimensec) >= DIP(ip, i_atimensec)) :
631+
(DIP(ip, i_ctime) >= DIP(ip, i_atime))))) {
625632
VI_LOCK(vp);
626633
ip->i_flag |= IN_ACCESS;
627634
VI_UNLOCK(vp);

0 commit comments

Comments
 (0)