Skip to content

Commit

Permalink
Implement relative atime mount flag. Relative atime means the operator
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
delphij committed May 20, 2013
1 parent e3567b2 commit 6a19982
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 7 deletions.
3 changes: 3 additions & 0 deletions lib/libc/sys/statfs.2
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ Identifies the root file system.
The file system is exported read-only.
.It Dv MNT_NOATIME
Updating of file access times is disabled.
.It Dv MNT_RELATIME
Updating of file access times is only done when it is smaller than both creation
and modification times.
.It Dv MNT_USER
The file system has been mounted by a user.
.\".It Dv MNT_IGNORE
Expand Down
4 changes: 4 additions & 0 deletions sbin/mount/mount.8
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ is useful on file systems where there are large numbers of files and
performance is more critical than updating the file access time (which is
rarely ever important).
This option is currently only supported on local file systems.
.It Cm relatime
Do not update the file access time when reading from a file, if the access
time is already later than both file creation time and file modification
times.
.It Cm noauto
This file system should be skipped when
.Nm
Expand Down
1 change: 1 addition & 0 deletions sbin/mount/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static struct opt {
{ MNT_ASYNC, "asynchronous" },
{ MNT_EXPORTED, "NFS exported" },
{ MNT_LOCAL, "local" },
{ MNT_RELATIME, "relative atime" },
{ MNT_NOATIME, "noatime" },
{ MNT_NOEXEC, "noexec" },
{ MNT_NOSUID, "nosuid" },
Expand Down
10 changes: 9 additions & 1 deletion sys/fs/ext2fs/ext2_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1697,7 +1697,15 @@ ext2_read(struct vop_read_args *ap)
}

if ((error == 0 || uio->uio_resid != orig_resid) &&
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0 &&
(ip->i_flag & IN_ACCESS) == 0 &&
((vp->v_mount->mnt_flag & MNT_RELATIME) == 0 ||
(ip->i_mtime == ip->i_atime ?
ip->i_mtimensec >= ip->i_atimensec :
ip->i_mtime >= ip->i_atime) ||
(ip->i_ctime == ip->i_atime ?
ip->i_ctimensec >= ip->i_atimensec :
ip->i_ctime >= ip->i_atime)))
ip->i_flag |= IN_ACCESS;
return (error);
}
Expand Down
14 changes: 12 additions & 2 deletions sys/kern/vfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static const char *global_opts[] = {
"rw",
"nosuid",
"noexec",
"relatime",
NULL
};

Expand Down Expand Up @@ -602,6 +603,14 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
free(opt->name, M_MOUNT);
opt->name = strdup("nonoatime", M_MOUNT);
}
else if (strcmp(opt->name, "norelatime") == 0) {
vfs_freeopt(optlist, opt);
fsflags &= ~MNT_RELATIME;
}
else if (strcmp(opt->name, "relatime") == 0) {
vfs_freeopt(optlist, opt);
fsflags |= MNT_RELATIME;
}
else if (strcmp(opt->name, "noclusterr") == 0)
fsflags |= MNT_NOCLUSTERR;
else if (strcmp(opt->name, "clusterr") == 0) {
Expand Down Expand Up @@ -811,7 +820,7 @@ vfs_domount_first(
/* XXXMAC: pass to vfs_mount_alloc? */
mp->mnt_optnew = *optlist;
/* Set the mount level flags. */
mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY | MNT_RELATIME));

/*
* Mount the filesystem.
Expand Down Expand Up @@ -933,7 +942,8 @@ vfs_domount_update(
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_UPDATEMASK;
mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY |
MNT_RELATIME);
if ((mp->mnt_flag & MNT_ASYNC) == 0)
mp->mnt_kern_flag &= ~MNTK_ASYNC;
MNT_IUNLOCK(mp);
Expand Down
27 changes: 25 additions & 2 deletions sys/kern/vfs_subr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3004,6 +3004,7 @@ DB_SHOW_COMMAND(mount, db_show_mount)
MNT_FLAG(MNT_GJOURNAL);
MNT_FLAG(MNT_MULTILABEL);
MNT_FLAG(MNT_ACLS);
MNT_FLAG(MNT_RELATIME);
MNT_FLAG(MNT_NOATIME);
MNT_FLAG(MNT_NOCLUSTERR);
MNT_FLAG(MNT_NOCLUSTERW);
Expand Down Expand Up @@ -4526,11 +4527,33 @@ void
vfs_mark_atime(struct vnode *vp, struct ucred *cred)
{
struct mount *mp;
struct vattr vattr;

mp = vp->v_mount;
ASSERT_VOP_LOCKED(vp, "vfs_mark_atime");
if (mp != NULL && (mp->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0)
(void)VOP_MARKATIME(vp);

/*
* Do nothing if the file system is mounted with noatime or
* marked as read only.
*/
if (mp == NULL || (mp->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) != 0)
return;

/*
* Relative atime: do nothing if both ctime and mtime are
* smaller than atime.
*/
if ((mp->mnt_flag & MNT_RELATIME) == MNT_RELATIME) {
if (VOP_GETATTR(vp, &vattr, cred) != 0)
return;
else {
if (timespeccmp(&vattr.va_mtime, &vattr.va_atime, < ) &&
timespeccmp(&vattr.va_ctime, &vattr.va_atime, < ))
return;
}
}

(void)VOP_MARKATIME(vp);
}

/*
Expand Down
3 changes: 2 additions & 1 deletion sys/sys/mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
#define MNT_NOCLUSTERR 0x0000000040000000ULL /* disable cluster read */
#define MNT_NOCLUSTERW 0x0000000080000000ULL /* disable cluster write */
#define MNT_SUJ 0x0000000100000000ULL /* using journaled soft updates */
#define MNT_RELATIME 0x0000000200000000ULL /* using relative atime */

/*
* NFS export related mount flags.
Expand Down Expand Up @@ -295,7 +296,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \
MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \
MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \
MNT_NFS4ACLS)
MNT_NFS4ACLS | MNT_RELATIME)

/* Mask of flags that can be updated. */
#define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \
Expand Down
9 changes: 8 additions & 1 deletion sys/ufs/ffs/ffs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,14 @@ ffs_read(ap)

if ((error == 0 || uio->uio_resid != orig_resid) &&
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0 &&
(ip->i_flag & IN_ACCESS) == 0) {
(ip->i_flag & IN_ACCESS) == 0 &&
((vp->v_mount->mnt_flag & MNT_RELATIME) == 0 ||
(DIP(ip, i_mtime) == DIP(ip, i_atime) ?
(DIP(ip, i_mtimensec) >= DIP(ip, i_atimensec)) :
(DIP(ip, i_mtime) >= DIP(ip, i_atime))) ||
(DIP(ip, i_ctime) == DIP(ip, i_atime) ?
(DIP(ip, i_ctimensec) >= DIP(ip, i_atimensec)) :
(DIP(ip, i_ctime) >= DIP(ip, i_atime))))) {
VI_LOCK(vp);
ip->i_flag |= IN_ACCESS;
VI_UNLOCK(vp);
Expand Down

0 comments on commit 6a19982

Please sign in to comment.