Support full-precision file timestamps. Until now, only the seconds
have been maintained, and that is still the default. A new sysctl variable "vfs.timestamp_precision" can be used to enable higher levels of precision: 0 = seconds only; nanoseconds zeroed (default). 1 = seconds and nanoseconds, accurate within 1/HZ. 2 = seconds and nanoseconds, truncated to microseconds. >=3 = seconds and nanoseconds, maximum precision. Level 1 uses getnanotime(), which is fast but can be wrong by up to 1/HZ. Level 2 uses microtime(). It might be desirable for consistency with utimes() and friends, which take timeval structures rather than timespecs. Level 3 uses nanotime() for the higest precision. I benchmarked levels 0, 1, and 3 by copying a 550 MB tree with "cpio -pdu". There was almost negligible difference in the system times -- much less than 1%, and less than the variation among multiple runs at the same level. Bruce Evans dreamed up a torture test involving 1-byte reads with intervening fstat() calls, but the cpio test seems more realistic to me. This feature is currently implemented only for the UFS (FFS and MFS) filesystems. But I think it should be easy to support it in the others as well. An earlier version of this was reviewed by Bruce. He's not to blame for any breakage I've introduced since then. Reviewed by: bde (an earlier version of the code)
This commit is contained in:
parent
4039114e6f
commit
9f71d680aa
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
|
||||
* $Id: vfs_subr.c,v 1.216 1999/08/13 10:10:01 phk Exp $
|
||||
* $Id: vfs_subr.c,v 1.217 1999/08/13 10:29:21 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -360,6 +360,48 @@ vfs_getnewfsid(mp)
|
||||
simple_unlock(&mntid_slock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Knob to control the precision of file timestamps:
|
||||
*
|
||||
* 0 = seconds only; nanoseconds zeroed.
|
||||
* 1 = seconds and nanoseconds, accurate within 1/HZ.
|
||||
* 2 = seconds and nanoseconds, truncated to microseconds.
|
||||
* >=3 = seconds and nanoseconds, maximum precision.
|
||||
*/
|
||||
enum { TSP_SEC, TSP_HZ, TSP_USEC, TSP_NSEC };
|
||||
|
||||
static int timestamp_precision = TSP_SEC;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, timestamp_precision, CTLFLAG_RW,
|
||||
×tamp_precision, 0, "");
|
||||
|
||||
/*
|
||||
* Get a current timestamp.
|
||||
*/
|
||||
void
|
||||
vfs_timestamp(tsp)
|
||||
struct timespec *tsp;
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
switch (timestamp_precision) {
|
||||
case TSP_SEC:
|
||||
tsp->tv_sec = time_second;
|
||||
tsp->tv_nsec = 0;
|
||||
break;
|
||||
case TSP_HZ:
|
||||
getnanotime(tsp);
|
||||
break;
|
||||
case TSP_USEC:
|
||||
microtime(&tv);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, tsp);
|
||||
break;
|
||||
case TSP_NSEC:
|
||||
default:
|
||||
nanotime(tsp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set vnode attributes to VNOVAL
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
|
||||
* $Id: vfs_subr.c,v 1.216 1999/08/13 10:10:01 phk Exp $
|
||||
* $Id: vfs_subr.c,v 1.217 1999/08/13 10:29:21 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -360,6 +360,48 @@ vfs_getnewfsid(mp)
|
||||
simple_unlock(&mntid_slock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Knob to control the precision of file timestamps:
|
||||
*
|
||||
* 0 = seconds only; nanoseconds zeroed.
|
||||
* 1 = seconds and nanoseconds, accurate within 1/HZ.
|
||||
* 2 = seconds and nanoseconds, truncated to microseconds.
|
||||
* >=3 = seconds and nanoseconds, maximum precision.
|
||||
*/
|
||||
enum { TSP_SEC, TSP_HZ, TSP_USEC, TSP_NSEC };
|
||||
|
||||
static int timestamp_precision = TSP_SEC;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, timestamp_precision, CTLFLAG_RW,
|
||||
×tamp_precision, 0, "");
|
||||
|
||||
/*
|
||||
* Get a current timestamp.
|
||||
*/
|
||||
void
|
||||
vfs_timestamp(tsp)
|
||||
struct timespec *tsp;
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
switch (timestamp_precision) {
|
||||
case TSP_SEC:
|
||||
tsp->tv_sec = time_second;
|
||||
tsp->tv_nsec = 0;
|
||||
break;
|
||||
case TSP_HZ:
|
||||
getnanotime(tsp);
|
||||
break;
|
||||
case TSP_USEC:
|
||||
microtime(&tv);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, tsp);
|
||||
break;
|
||||
case TSP_NSEC:
|
||||
default:
|
||||
nanotime(tsp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set vnode attributes to VNOVAL
|
||||
*/
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
|
||||
* $Id: vnode.h,v 1.93 1999/08/08 18:43:00 phk Exp $
|
||||
* $Id: vnode.h,v 1.94 1999/08/13 10:10:11 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_VNODE_H_
|
||||
@ -544,6 +544,7 @@ dev_t vn_todev __P((struct vnode *vp));
|
||||
int vfs_cache_lookup __P((struct vop_lookup_args *ap));
|
||||
int vfs_object_create __P((struct vnode *vp, struct proc *p,
|
||||
struct ucred *cred));
|
||||
void vfs_timestamp __P((struct timespec *));
|
||||
int vn_writechk __P((struct vnode *vp));
|
||||
int vop_stdbwrite __P((struct vop_bwrite_args *ap));
|
||||
int vop_stdislocked __P((struct vop_islocked_args *));
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
|
||||
* $Id: ufs_vnops.c,v 1.118 1999/08/13 10:10:12 phk Exp $
|
||||
* $Id: ufs_vnops.c,v 1.119 1999/08/13 10:56:02 phk Exp $
|
||||
*/
|
||||
|
||||
#include "opt_quota.h"
|
||||
@ -138,26 +138,31 @@ ufs_itimes(vp)
|
||||
struct vnode *vp;
|
||||
{
|
||||
struct inode *ip;
|
||||
time_t tv_sec;
|
||||
struct timespec ts;
|
||||
|
||||
ip = VTOI(vp);
|
||||
if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
|
||||
return;
|
||||
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
|
||||
tv_sec = time_second;
|
||||
vfs_timestamp(&ts);
|
||||
if ((vp->v_type == VBLK || vp->v_type == VCHR) &&
|
||||
!DOINGSOFTDEP(vp))
|
||||
ip->i_flag |= IN_LAZYMOD;
|
||||
else
|
||||
ip->i_flag |= IN_MODIFIED;
|
||||
if (ip->i_flag & IN_ACCESS)
|
||||
ip->i_atime = tv_sec;
|
||||
if (ip->i_flag & IN_ACCESS) {
|
||||
ip->i_atime = ts.tv_sec;
|
||||
ip->i_atimensec = ts.tv_nsec;
|
||||
}
|
||||
if (ip->i_flag & IN_UPDATE) {
|
||||
ip->i_mtime = tv_sec;
|
||||
ip->i_mtime = ts.tv_sec;
|
||||
ip->i_mtimensec = ts.tv_nsec;
|
||||
ip->i_modrev++;
|
||||
}
|
||||
if (ip->i_flag & IN_CHANGE)
|
||||
ip->i_ctime = tv_sec;
|
||||
if (ip->i_flag & IN_CHANGE) {
|
||||
ip->i_ctime = ts.tv_sec;
|
||||
ip->i_ctimensec = ts.tv_nsec;
|
||||
}
|
||||
}
|
||||
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
|
||||
}
|
||||
@ -500,10 +505,14 @@ ufs_setattr(ap)
|
||||
if (vap->va_mtime.tv_sec != VNOVAL)
|
||||
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
ufs_itimes(vp);
|
||||
if (vap->va_atime.tv_sec != VNOVAL)
|
||||
if (vap->va_atime.tv_sec != VNOVAL) {
|
||||
ip->i_atime = vap->va_atime.tv_sec;
|
||||
if (vap->va_mtime.tv_sec != VNOVAL)
|
||||
ip->i_atimensec = vap->va_atime.tv_nsec;
|
||||
}
|
||||
if (vap->va_mtime.tv_sec != VNOVAL) {
|
||||
ip->i_mtime = vap->va_mtime.tv_sec;
|
||||
ip->i_mtimensec = vap->va_mtime.tv_nsec;
|
||||
}
|
||||
error = UFS_UPDATE(vp, 0);
|
||||
if (error)
|
||||
return (error);
|
||||
|
Loading…
Reference in New Issue
Block a user