summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1998-06-07 10:49:18 +0000
committerbde <bde@FreeBSD.org>1998-06-07 10:49:18 +0000
commit0af8745beb100dd73cd116f49d475f9280407ada (patch)
tree1f0365d6b5dfd9ded3996f20128c484a9360ad91 /sys/ufs
parenta34566b534bc02b66f0cad9280b0191947d6c721 (diff)
downloadFreeBSD-src-0af8745beb100dd73cd116f49d475f9280407ada.zip
FreeBSD-src-0af8745beb100dd73cd116f49d475f9280407ada.tar.gz
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.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ufs/ufs_vnops.c131
1 files changed, 72 insertions, 59 deletions
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 98c0d07..97a6f8a 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -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];
@@ -123,27 +123,6 @@ union _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).
*/
static struct dirtemplate mastertemplate = {
@@ -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;
{
-
- /*
- * Set update and change flags.
- */
- VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
- return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
+ int error, resid;
+ struct uio *uio;
+
+ 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;
{
-
- /*
- * Set access flag.
- */
- if (!(ap->a_vp->v_mount->mnt_flag & MNT_NOATIME))
+ int error, resid;
+ struct uio *uio;
+
+ 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));
}
/*
OpenPOWER on IntegriCloud