Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Dec 1996 01:17:04 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bugs@freebsd.org
Cc:        bde@zeta.org.au
Subject:   another POSIX access timestamp pessimization
Message-ID:  <199612281417.BAA20220@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
POSIX says that "Upon successful completion, the exec functions shall
mark for update the st_atime field of the file".  Not content with
this pessimization, it also specifies that exec shall be considered as
doing an open() and close() where the close() occurs before the process
terminates and before the next successful exec.  The access time must
be updated if the close() leaves the file completely closed.  In FreeBSD,
marking for update dirties inodes just as much as update and update is
cheap, so the second pessimization doesn't make much difference.

Here is a (not very good) implementation.  It updates the access time
immediately.  This slows down execs on ufs a little (caching works)
and slows down execs on an nfs file system a lot (about 1 msec per exec
for a 10Mbps ethernet).

It's remarkably inconvenient to get at the update flags and/or the
access times from the vfs level.  I used VFS_SETATTR() and added a flag
to tell it what to do.  There was a bug in handling the existing flag
VA_UTIMES_NULL - suser() was sometimes called although no superuser
privilege was used.

Bruce

diff -c2 src/sys/sys/vnode.h~ src/sys/sys/vnode.h
*** src/sys/sys/vnode.h~	Fri Oct 18 07:07:42 1996
--- src/sys/sys/vnode.h	Wed Dec 11 18:34:10 1996
***************
*** 156,159 ****
--- 156,160 ----
   */
  #define	VA_UTIMES_NULL	0x01		/* utimes argument was NULL */
+ #define	VA_EXECVE_ATIME	0x02		/* setting atime for execve */
  
  /*
diff -c2 src/sys/kern/kern_exec.c~ src/sys/kern/kern_exec.c
*** src/sys/kern/kern_exec.c~	Sun Nov 10 05:00:02 1996
--- src/sys/kern/kern_exec.c	Wed Dec 11 19:12:39 1996
***************
*** 323,326 ****
--- 323,341 ----
  	    (vm_offset_t)imgp->image_header + PAGE_SIZE))
  		panic("execve: header dealloc failed (2)");
+ 
+ 	if (!(ndp->ni_vp->v_mount->mnt_flag & MNT_NOATIME)) {
+ 		struct timeval tv;
+ 		struct vattr vattr;
+ 
+ 		VATTR_NULL(&vattr);
+ 		microtime(&tv);
+ 		TIMEVAL_TO_TIMESPEC(&tv, &vattr.va_atime);
+ 		vattr.va_vaflags |= VA_EXECVE_ATIME;
+ 		LEASE_CHECK(ndp->ni_vp, p, p->p_ucred, LEASE_WRITE);
+ 		VOP_LOCK(ndp->ni_vp);
+ 		(void) VOP_SETATTR(ndp->ni_vp, &vattr, p->p_ucred, p);
+ 		VOP_UNLOCK(ndp->ni_vp);
+ 	}
+ 
  	vrele(ndp->ni_vp);
  	FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
diff -c2 src/sys/ufs/ufs/ufs_vnops.c~ src/sys/ufs/ufs/ufs_vnops.c
*** src/sys/ufs/ufs/ufs_vnops.c~	Tue Nov  5 21:05:36 1996
--- src/sys/ufs/ufs/ufs_vnops.c	Wed Dec 11 19:11:37 1996
***************
*** 422,438 ****
  			return (EROFS);
  		if (cred->cr_uid != ip->i_uid &&
! 		    (error = suser(cred, &p->p_acflag)) &&
! 		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
! 		    (error = VOP_ACCESS(vp, VWRITE, cred, p))))
! 			return (error);
  		if (vap->va_atime.tv_sec != VNOVAL)
  			ip->i_flag |= IN_ACCESS;
  		if (vap->va_mtime.tv_sec != VNOVAL)
  			ip->i_flag |= IN_CHANGE | IN_UPDATE;
  		atimeval.tv_sec = vap->va_atime.tv_sec;
  		atimeval.tv_usec = vap->va_atime.tv_nsec / 1000;
  		mtimeval.tv_sec = vap->va_mtime.tv_sec;
  		mtimeval.tv_usec = vap->va_mtime.tv_nsec / 1000;
! 		error = VOP_UPDATE(vp, &atimeval, &mtimeval, 1);
  		if (error)
  			return (error);
--- 417,438 ----
  			return (EROFS);
  		if (cred->cr_uid != ip->i_uid &&
! 		    !(vap->va_vaflags & VA_EXECVE_ATIME)) {
! 			if (vap->va_vaflags & VA_UTIMES_NULL)
! 				error = VOP_ACCESS(vp, VWRITE, cred, p);
! 			else
! 				error = suser(cred, &p->p_acflag);
! 			if (error != 0)
! 				return (error);
! 		}
  		if (vap->va_atime.tv_sec != VNOVAL)
  			ip->i_flag |= IN_ACCESS;
  		if (vap->va_mtime.tv_sec != VNOVAL)
  			ip->i_flag |= IN_CHANGE | IN_UPDATE;
  		atimeval.tv_sec = vap->va_atime.tv_sec;
  		atimeval.tv_usec = vap->va_atime.tv_nsec / 1000;
  		mtimeval.tv_sec = vap->va_mtime.tv_sec;
  		mtimeval.tv_usec = vap->va_mtime.tv_nsec / 1000;
! 		error = VOP_UPDATE(vp, &atimeval, &mtimeval,
+ 				   vap->va_vaflags & VA_EXECVE_ATIME ? 0 : 1);
  		if (error)
  			return (error);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612281417.BAA20220>