Fixed some longstanding timestamp bugs:

1. mark atimes and mtimes of special files and fifos for update upon
   successful completion of non-null i/o, not at the beginning of the
   syscall.
2. never update file times for readonly filesystems.  They were updated
   for stats and closes but not for syncs.  The updates were of course
   only in-core and were thrown away when the inode was uncached, so
   the times sometimes appeared to go backwards.

Improved comments in code related to (1) (mostly by removing them).

Unmacroized ITIMES().  The test in (2) bloated it even more.  Don't
call getmicrotime() in the function version of it when we only need
the time in seconds.
This commit is contained in:
bde 1998-06-07 10:49:18 +00:00
parent a34566b534
commit 0af8745beb

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
* $Id: ufs_vnops.c,v 1.84 1998/05/07 04:58:58 msmith Exp $
* $Id: ufs_vnops.c,v 1.85 1998/05/17 11:53:46 phk Exp $
*/
#include "opt_quota.h"
@ -71,6 +71,7 @@
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
static void itimes __P((struct vnode *vp));
static int ufs_abortop __P((struct vop_abortop_args *));
static int ufs_access __P((struct vop_access_args *));
static int ufs_advlock __P((struct vop_advlock_args *));
@ -104,7 +105,6 @@ static int ufsspec_close __P((struct vop_close_args *));
static int ufsspec_read __P((struct vop_read_args *));
static int ufsspec_write __P((struct vop_write_args *));
union _qcvt {
int64_t qcvt;
int32_t val[2];
@ -122,27 +122,6 @@ union _qcvt {
(q) = tmp.qcvt; \
}
/*
* XXX this is too long to be a macro, and isn't used in any time-critical
* place;
*/
#define ITIMES(ip) { \
struct timeval tv; \
getmicrotime(&tv); \
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
(ip)->i_flag |= IN_MODIFIED; \
if ((ip)->i_flag & IN_ACCESS) \
(ip)->i_atime = tv.tv_sec; \
if ((ip)->i_flag & IN_UPDATE) { \
(ip)->i_mtime = tv.tv_sec; \
(ip)->i_modrev++; \
} \
if ((ip)->i_flag & IN_CHANGE) \
(ip)->i_ctime = tv.tv_sec; \
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
} \
}
/*
* A virgin directory (no blushing please).
*/
@ -155,6 +134,31 @@ static struct odirtemplate omastertemplate = {
0, DIRBLKSIZ - 12, 2, ".."
};
static void
itimes(vp)
struct vnode *vp;
{
struct inode *ip;
time_t tv_sec;
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;
ip->i_flag |= IN_MODIFIED;
if (ip->i_flag & IN_ACCESS)
ip->i_atime = tv_sec;
if (ip->i_flag & IN_UPDATE) {
ip->i_mtime = tv_sec;
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE)
ip->i_ctime = tv_sec;
}
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
}
/*
* Create a regular file
*/
@ -263,11 +267,10 @@ ufs_close(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct inode *ip = VTOI(vp);
simple_lock(&vp->v_interlock);
if (vp->v_usecount > 1)
ITIMES(ip);
itimes(vp);
simple_unlock(&vp->v_interlock);
return (0);
}
@ -370,7 +373,7 @@ ufs_getattr(ap)
register struct inode *ip = VTOI(vp);
register struct vattr *vap = ap->a_vap;
ITIMES(ip);
itimes(vp);
/*
* Copy from inode table
*/
@ -1776,13 +1779,15 @@ ufsspec_read(ap)
struct ucred *a_cred;
} */ *ap;
{
int error, resid;
struct uio *uio;
/*
* Set access flag.
*/
if (!(ap->a_vp->v_mount->mnt_flag & MNT_NOATIME))
uio = ap->a_uio;
resid = uio->uio_resid;
error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap);
if (uio->uio_resid != resid)
VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
return (error);
}
/*
@ -1797,12 +1802,15 @@ ufsspec_write(ap)
struct ucred *a_cred;
} */ *ap;
{
int error, resid;
struct uio *uio;
/*
* Set update and change flags.
*/
VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
uio = ap->a_uio;
resid = uio->uio_resid;
error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap);
if (uio->uio_resid != resid)
VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
}
/*
@ -1820,17 +1828,16 @@ ufsspec_close(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
simple_lock(&vp->v_interlock);
if (ap->a_vp->v_usecount > 1)
ITIMES(ip);
if (vp->v_usecount > 1)
itimes(vp);
simple_unlock(&vp->v_interlock);
return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
}
/*
* Read wrapper for fifo's
* Read wrapper for fifos.
*/
int
ufsfifo_read(ap)
@ -1841,17 +1848,20 @@ ufsfifo_read(ap)
struct ucred *a_cred;
} */ *ap;
{
int error, resid;
struct uio *uio;
/*
* Set access flag.
*/
if (!(ap->a_vp->v_mount->mnt_flag & MNT_NOATIME))
uio = ap->a_uio;
resid = uio->uio_resid;
error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap);
if (uio->uio_resid != resid &&
(ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
return (error);
}
/*
* Write wrapper for fifo's.
* Write wrapper for fifos.
*/
int
ufsfifo_write(ap)
@ -1862,15 +1872,19 @@ ufsfifo_write(ap)
struct ucred *a_cred;
} */ *ap;
{
/*
* Set update and change flags.
*/
VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
int error, resid;
struct uio *uio;
uio = ap->a_uio;
resid = uio->uio_resid;
error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap);
if (uio->uio_resid != resid)
VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
}
/*
* Close wrapper for fifo's.
* Close wrapper for fifos.
*
* Update the times on the inode then do device close.
*/
@ -1884,13 +1898,12 @@ ufsfifo_close(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
simple_lock(&vp->v_interlock);
if (ap->a_vp->v_usecount > 1)
ITIMES(ip);
if (vp->v_usecount > 1)
itimes(vp);
simple_unlock(&vp->v_interlock);
return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
}
/*