Issue 1013 - update atime on exec and mmap, add helper vop_markatime
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 21 Jan 2009 01:39:51 +0000 (17:39 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 21 Jan 2009 01:39:51 +0000 (17:39 -0800)
Add a new helper VOP which passively updates a vnode's atime.  Implement
the new VOP in HAMMER and UFS and create a default op which does nothing.
Call the new function from mmap() and exec().

Submitted-by: Dion Blazakis
Reported-by: Simon Schubert
lib/libc/sys/stat.2
sys/kern/kern_exec.c
sys/kern/vfs_default.c
sys/kern/vfs_subr.c
sys/kern/vfs_vopops.c
sys/sys/vfsops.h
sys/sys/vnode.h
sys/vfs/hammer/hammer_vnops.c
sys/vfs/ufs/ufs_vnops.c
sys/vm/vm_mmap.c

index 8816375..fa4ab27 100644 (file)
@@ -123,10 +123,12 @@ are as follows:
 .It st_atime
 Time when file data last accessed.
 Changed by the
+.Xr execve 2 ,
 .Xr mknod 2 ,
-.Xr utimes 2
-and
+.Xr mmap 2 ,
 .Xr read 2
+and
+.Xr utimes 2
 system calls.
 .It st_mtime
 Time when file data last modified.
index 1212eef..56e54ec 100644 (file)
@@ -469,6 +469,9 @@ interpret:
        exec_setregs(imgp->entry_addr, (u_long)(uintptr_t)stack_base,
            imgp->ps_strings);
 
+       /* Set the access time on the vnode */
+       vn_mark_atime(imgp->vp, td);
+
        /* Free any previous argument cache */
        if (p->p_args && --p->p_args->ar_ref == 0)
                FREE(p->p_args, M_PARGS);
index da0534c..fe3c033 100644 (file)
@@ -95,6 +95,7 @@ struct vop_ops default_vnode_vops = {
        .vop_aclcheck           = (void *)vop_eopnotsupp,
        .vop_getextattr         = (void *)vop_eopnotsupp,
        .vop_setextattr         = (void *)vop_eopnotsupp,
+       .vop_markatime          = vop_stdmarkatime,
        .vop_nresolve           = vop_compat_nresolve,
        .vop_nlookupdotdot      = vop_compat_nlookupdotdot,
        .vop_ncreate            = vop_compat_ncreate,
@@ -135,6 +136,12 @@ vop_einval(struct vop_generic_args *ap)
        return (EINVAL);
 }
 
+int
+vop_stdmarkatime(struct vop_markatime_args *ap)
+{
+       return (EOPNOTSUPP);
+}
+
 int
 vop_null(struct vop_generic_args *ap)
 {
index 8c9f324..6064667 100644 (file)
@@ -2143,3 +2143,13 @@ vop_write_dirent(int *error, struct uio *uio, ino_t d_ino, uint8_t d_type,
        return(0);
 }
 
+void
+vn_mark_atime(struct vnode *vp, struct thread *td)
+{
+       struct proc *p = td->td_proc;
+       struct ucred *cred = p ? p->p_ucred : proc0.p_ucred;
+
+       if ((vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) {
+               VOP_MARKATIME(vp, cred);
+       }
+}
index a15bddc..89ce089 100644 (file)
@@ -127,6 +127,7 @@ VNODEOP_DESC_INIT(aclcheck);
 VNODEOP_DESC_INIT(getextattr);
 VNODEOP_DESC_INIT(setextattr);
 VNODEOP_DESC_INIT(mountctl);
+VNODEOP_DESC_INIT(markatime);
 
 VNODEOP_DESC_INIT(nresolve);
 VNODEOP_DESC_INIT(nlookupdotdot);
@@ -902,7 +903,7 @@ vop_setextattr(struct vop_ops *ops, struct vnode *vp, char *name,
 
 int
 vop_mountctl(struct vop_ops *ops, int op, struct file *fp, 
-           const void *ctl, int ctllen, void *buf, int buflen, int *res)
+       const void *ctl, int ctllen, void *buf, int buflen, int *res)
 {
        struct vop_mountctl_args ap;
        int error;
@@ -921,6 +922,21 @@ vop_mountctl(struct vop_ops *ops, int op, struct file *fp,
        return(error);
 }
 
+int
+vop_markatime(struct vop_ops *ops, struct vnode *vp, struct ucred *cred)
+{
+       struct vop_markatime_args ap;
+       int error;
+
+       ap.a_head.a_desc = &vop_markatime_desc;
+       ap.a_head.a_ops = ops;
+       ap.a_vp = vp;
+       ap.a_cred = cred;
+
+       DO_OPS(ops, error, &ap, vop_markatime);
+       return(error);
+}
+
 /*
  * NEW API FUNCTIONS
  *
@@ -1605,6 +1621,15 @@ vop_mountctl_ap(struct vop_mountctl_args *ap)
        return(error);
 }
 
+int
+vop_markatime_ap(struct vop_markatime_args *ap)
+{
+       int error;
+
+       DO_OPS(ap->a_head.a_ops, error, ap, vop_markatime);
+       return(error);
+}
+
 int
 vop_nresolve_ap(struct vop_nresolve_args *ap)
 {
index 1e5bd3b..b2ae193 100644 (file)
@@ -417,6 +417,13 @@ struct vop_mountctl_args {
        int *a_res;
 };
 
+struct vop_markatime_args {
+       struct vop_generic_args a_head;
+       int a_op;
+       struct vnode *a_vp;
+       struct ucred *a_cred;
+};
+
 /*
  * NEW API
  */
@@ -621,6 +628,7 @@ struct vop_ops {
        int     (*vop_unused07)(void *);
        int     (*vop_unused08)(void *);
        int     (*vop_mountctl)(struct vop_mountctl_args *);
+       int     (*vop_markatime)(struct vop_markatime_args *);
 
        int     (*vop_nresolve)(struct vop_nresolve_args *);
        int     (*vop_nlookupdotdot)(struct vop_nlookupdotdot_args *);
@@ -693,6 +701,7 @@ union vop_args_union {
        struct vop_getextattr_args vu_getextattr;
        struct vop_setextattr_args vu_setextattr;
        struct vop_mountctl_args vu_mountctl;
+       struct vop_markatime_args vu_markatime;
 
        struct vop_nresolve_args vu_nresolve;
        struct vop_nlookupdotdot_args vu_nlookupdotdot;
@@ -802,6 +811,7 @@ int vop_setextattr(struct vop_ops *ops, struct vnode *vp, char *name,
                struct uio *uio, struct ucred *cred);
 int vop_mountctl(struct vop_ops *ops, int op, struct file *fp, 
                const void *ctl, int ctllen, void *buf, int buflen, int *res);
+int vop_markatime(struct vop_ops *ops, struct vnode *vp, struct ucred *cred);
 int vop_nresolve(struct vop_ops *ops, struct nchandle *nch,
                struct vnode *dvp, struct ucred *cred);
 int vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp,
@@ -883,6 +893,7 @@ int vop_aclcheck_ap(struct vop_aclcheck_args *ap);
 int vop_getextattr_ap(struct vop_getextattr_args *ap);
 int vop_setextattr_ap(struct vop_setextattr_args *ap);
 int vop_mountctl_ap(struct vop_mountctl_args *ap);
+int vop_markatime_ap(struct vop_markatime_args *ap);
 
 int vop_nresolve_ap(struct vop_nresolve_args *ap);
 int vop_nlookupdotdot_ap(struct vop_nlookupdotdot_args *ap);
@@ -945,6 +956,7 @@ extern struct syslink_desc vop_aclcheck_desc;
 extern struct syslink_desc vop_getextattr_desc;
 extern struct syslink_desc vop_setextattr_desc;
 extern struct syslink_desc vop_mountctl_desc;
+extern struct syslink_desc vop_markatime_desc;
 
 extern struct syslink_desc vop_nresolve_desc;
 extern struct syslink_desc vop_nlookupdotdot_desc;
@@ -1026,6 +1038,8 @@ extern struct syslink_desc vop_nrename_desc;
        vop_getextattr(*(vp)->v_ops, vp, name, uio, cred)
 #define VOP_SETEXTATTR(vp, name, uio, cred)            \
        vop_setextattr(*(vp)->v_ops, vp, name, uio, cred)
+#define VOP_MARKATIME(vp, cred)                        \
+       vop_markatime(*(vp)->v_ops, vp, cred)
 /* no VOP_VFSSET() */
 /* VOP_STRATEGY - does not exist, use vn_strategy() */
 
index 253577c..70c7ac4 100644 (file)
@@ -517,12 +517,14 @@ int       vn_rdwr_inchunks (enum uio_rw rw, struct vnode *vp, caddr_t base,
 int    vn_stat (struct vnode *vp, struct stat *sb, struct ucred *cred);
 cdev_t vn_todev (struct vnode *vp);
 void   vfs_timestamp (struct timespec *);
+void   vn_mark_atime(struct vnode *vp, struct thread *td);
 int    vn_writechk (struct vnode *vp, struct nchandle *nch);
 int    ncp_writechk(struct nchandle *nch);
 int    vop_stdopen (struct vop_open_args *ap);
 int    vop_stdclose (struct vop_close_args *ap);
 int    vop_stdgetpages(struct vop_getpages_args *ap);
 int    vop_stdputpages(struct vop_putpages_args *ap);
+int    vop_stdmarkatime(struct vop_markatime_args *ap);
 int    vop_nopoll (struct vop_poll_args *ap);
 int    vop_stdpathconf (struct vop_pathconf_args *ap);
 int    vop_stdpoll (struct vop_poll_args *ap);
index 7c443c8..5b4e14a 100644 (file)
@@ -73,6 +73,7 @@ static int hammer_vop_readlink(struct vop_readlink_args *);
 static int hammer_vop_nremove(struct vop_nremove_args *);
 static int hammer_vop_nrename(struct vop_nrename_args *);
 static int hammer_vop_nrmdir(struct vop_nrmdir_args *);
+static int hammer_vop_markatime(struct vop_markatime_args *);
 static int hammer_vop_setattr(struct vop_setattr_args *);
 static int hammer_vop_strategy(struct vop_strategy_args *);
 static int hammer_vop_bmap(struct vop_bmap_args *ap);
@@ -118,6 +119,7 @@ struct vop_ops hammer_vnode_vops = {
        .vop_nremove =          hammer_vop_nremove,
        .vop_nrename =          hammer_vop_nrename,
        .vop_nrmdir =           hammer_vop_nrmdir,
+       .vop_markatime =        hammer_vop_markatime,
        .vop_setattr =          hammer_vop_setattr,
        .vop_bmap =             hammer_vop_bmap,
        .vop_strategy =         hammer_vop_strategy,
@@ -135,6 +137,7 @@ struct vop_ops hammer_spec_vops = {
        .vop_write =            hammer_vop_specwrite,
        .vop_access =           hammer_vop_access,
        .vop_close =            hammer_vop_specclose,
+       .vop_markatime =        hammer_vop_markatime,
        .vop_getattr =          hammer_vop_getattr,
        .vop_inactive =         hammer_vop_inactive,
        .vop_reclaim =          hammer_vop_reclaim,
@@ -148,6 +151,7 @@ struct vop_ops hammer_fifo_vops = {
        .vop_write =            hammer_vop_fifowrite,
        .vop_access =           hammer_vop_access,
        .vop_close =            hammer_vop_fifoclose,
+       .vop_markatime =        hammer_vop_markatime,
        .vop_getattr =          hammer_vop_getattr,
        .vop_inactive =         hammer_vop_inactive,
        .vop_reclaim =          hammer_vop_reclaim,
@@ -1702,6 +1706,33 @@ hammer_vop_nrmdir(struct vop_nrmdir_args *ap)
        return (error);
 }
 
+/*
+ * hammer_vop_markatime { vp, cred }
+ */
+static
+int
+hammer_vop_markatime(struct vop_markatime_args *ap)
+{
+       struct hammer_transaction trans;
+       struct hammer_inode *ip;
+
+       ip = VTOI(ap->a_vp);
+       if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
+               return (EROFS);
+       if (ip->flags & HAMMER_INODE_RO)
+               return (EROFS);
+       if (ip->hmp->mp->mnt_flag & MNT_NOATIME)
+               return (0);
+       hammer_start_transaction(&trans, ip->hmp);
+       ++hammer_stats_file_iopsw;
+
+       ip->ino_data.atime = trans.time;
+       hammer_modify_inode(ip, HAMMER_INODE_ATIME);
+       hammer_done_transaction(&trans);
+       hammer_knote(ap->a_vp, NOTE_ATTRIB);
+       return (0);
+}
+
 /*
  * hammer_vop_setattr { vp, vap, cred }
  */
index bfcf178..dfdf1ea 100644 (file)
@@ -89,6 +89,7 @@ static int ufs_create (struct vop_old_create_args *);
 static int ufs_getattr (struct vop_getattr_args *);
 static int ufs_link (struct vop_old_link_args *);
 static int ufs_makeinode (int mode, struct vnode *, struct vnode **, struct componentname *);
+static int ufs_markatime (struct vop_markatime_args *);
 static int ufs_missingop (struct vop_generic_args *ap);
 static int ufs_mkdir (struct vop_old_mkdir_args *);
 static int ufs_mknod (struct vop_old_mknod_args *);
@@ -444,6 +445,22 @@ ufs_getattr(struct vop_getattr_args *ap)
        return (0);
 }
 
+static
+int
+ufs_markatime(struct vop_markatime_args *ap)
+{
+       struct vnode *vp = ap->a_vp;
+       struct inode *ip = VTOI(vp);
+
+       if (vp->v_mount->mnt_flag & MNT_RDONLY)
+               return (EROFS);
+       if (vp->v_mount->mnt_flag & MNT_NOATIME)
+               return (0);
+       ip->i_flag |= IN_ACCESS;
+       VN_KNOTE(vp, NOTE_ATTRIB);
+       return (0);
+}
+
 /*
  * Set attribute vnode op. called from several syscalls
  *
@@ -2368,6 +2385,7 @@ static struct vop_ops ufs_vnode_vops = {
        .vop_old_rename =       ufs_rename,
        .vop_old_rmdir =        ufs_rmdir,
        .vop_setattr =          ufs_setattr,
+       .vop_markatime =        ufs_markatime,
        .vop_strategy =         ufs_strategy,
        .vop_old_symlink =      ufs_symlink,
        .vop_old_whiteout =     ufs_whiteout
@@ -2384,6 +2402,7 @@ static struct vop_ops ufs_spec_vops = {
        .vop_read =             ufsspec_read,
        .vop_reclaim =          ufs_reclaim,
        .vop_setattr =          ufs_setattr,
+       .vop_markatime =        ufs_markatime,
        .vop_write =            ufsspec_write
 };
 
@@ -2399,6 +2418,7 @@ static struct vop_ops ufs_fifo_vops = {
        .vop_read =             ufsfifo_read,
        .vop_reclaim =          ufs_reclaim,
        .vop_setattr =          ufs_setattr,
+       .vop_markatime =        ufs_markatime,
        .vop_write =            ufsfifo_write
 };
 
index cfe56ef..1717370 100644 (file)
@@ -985,6 +985,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
        boolean_t fitit;
        vm_object_t object;
        struct vnode *vp = NULL;
+       struct thread *td = curthread;
        struct proc *p;
        objtype_t type;
        int rv = KERN_SUCCESS;
@@ -1136,6 +1137,13 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
                        goto out;
                }
        }
+
+       /*
+        * Set the access time on the vnode
+        */
+       if (handle != NULL) {
+               vn_mark_atime(handle, td);
+       }
 out:
        switch (rv) {
        case KERN_SUCCESS: