From: guenther Date: Fri, 17 Apr 2015 04:43:20 +0000 (+0000) Subject: Tweaks utimensat/futimens handling to always update ctime, even when both X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=4707cbe35fb28a996a6eab2cd46ba227841d7cb3;p=openbsd Tweaks utimensat/futimens handling to always update ctime, even when both atime and mtime are UTIME_OMIT (at least for ufs, tmpfs, and ext2fs), and to correctly handle a timestamp of -1. ok millert@ --- diff --git a/lib/libc/sys/utimes.2 b/lib/libc/sys/utimes.2 index 5dce0004265..f3d15d5190c 100644 --- a/lib/libc/sys/utimes.2 +++ b/lib/libc/sys/utimes.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: utimes.2,v 1.24 2015/02/27 23:56:03 millert Exp $ +.\" $OpenBSD: utimes.2,v 1.25 2015/04/17 04:43:20 guenther Exp $ .\" $NetBSD: utimes.2,v 1.9 1996/04/23 10:34:16 mycroft Exp $ .\" .\" Copyright (c) 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)utimes.2 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: February 27 2015 $ +.Dd $Mdocdate: April 17 2015 $ .Dt UTIMES 2 .Os .Sh NAME @@ -75,8 +75,7 @@ The access time is set to the value of the first element, and the modification time is set to the value of the second element. The caller must be the owner of the file or be the superuser. .Pp -In either case, the inode-change-time of the file is set to the current -time. +In either case, the file status change time is set to the current time. .Pp The .Fn utimensat @@ -294,15 +293,13 @@ and function calls appeared in .Ox 5.0 . .Sh CAVEATS -.St -p1003.1-2008 -specifies that -.Fn utimensat -and -.Fn futimens -shall mark the last file status change timestamp (i.e.\& -.Fa st_ctim ) -for update upon successful completion. -However, currently some filesystems (e.g. UFS) -will not do so if +Some filesystems, such as FAT, use the same timestamp for both +modification and file status change; +on those filesystems, the file status change timestamp will not be +updated if .Dv UTIME_OMIT is specified for the modification timestamp argument. +Similarly, on NFS the file status change timestamp will not be +updated if +.Dv UTIME_OMIT +is specified for both the access and the modification timestamp arguments. diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c index 07ea2531a69..ce9d1c41cf5 100644 --- a/sys/isofs/cd9660/cd9660_vnops.c +++ b/sys/isofs/cd9660/cd9660_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vnops.c,v 1.71 2015/03/14 03:38:50 jsg Exp $ */ +/* $OpenBSD: cd9660_vnops.c,v 1.72 2015/04/17 04:43:20 guenther Exp $ */ /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ /*- @@ -94,8 +94,9 @@ cd9660_setattr(void *v) struct vattr *vap = ap->a_vap; if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || - vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || - vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) + vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_nsec != VNOVAL || + vap->va_mtime.tv_nsec != VNOVAL || vap->va_mode != (mode_t)VNOVAL || + (vap->va_vaflags & VA_UTIMES_CHANGE)) return (EROFS); if (vap->va_size != VNOVAL) { switch (vp->v_type) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 99d45dafdb0..7cac013b16b 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.217 2015/03/14 03:38:51 jsg Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.218 2015/04/17 04:43:20 guenther Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -2283,6 +2283,10 @@ dovutimens(struct proc *p, struct vnode *vp, struct timespec ts[2]) #endif VATTR_NULL(&vattr); + + /* make sure ctime is updated even if neither mtime nor atime is */ + vattr.va_vaflags = VA_UTIMES_CHANGE; + if (ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) { if (ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW) vattr.va_vaflags |= VA_UTIMES_NULL; @@ -2294,29 +2298,22 @@ dovutimens(struct proc *p, struct vnode *vp, struct timespec ts[2]) ts[1] = now; } - /* - * XXX: Ideally the filesystem code would check tv_nsec == - * UTIME_OMIT instead of tv_sec == VNOVAL, but until then we - * need to fudge tv_sec if it happens to equal VNOVAL. - */ - if (ts[0].tv_nsec == UTIME_OMIT) - ts[0].tv_sec = VNOVAL; - else if (ts[0].tv_sec == VNOVAL) - ts[0].tv_sec = VNOVAL - 1; - - if (ts[1].tv_nsec == UTIME_OMIT) - ts[1].tv_sec = VNOVAL; - else if (ts[1].tv_sec == VNOVAL) - ts[1].tv_sec = VNOVAL - 1; + if (ts[0].tv_nsec != UTIME_OMIT) { + if (ts[0].tv_nsec < 0 || ts[0].tv_nsec >= 1000000000) + return (EINVAL); + vattr.va_atime = ts[0]; + } + if (ts[1].tv_nsec != UTIME_OMIT) { + if (ts[1].tv_nsec < 0 || ts[1].tv_nsec >= 1000000000) + return (EINVAL); + vattr.va_mtime = ts[1]; + } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; - else { - vattr.va_atime = ts[0]; - vattr.va_mtime = ts[1]; + else error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } vput(vp); return (error); } diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index f6807648338..8ab7140ad50 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.23 2015/02/19 10:22:20 tedu Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.24 2015/04/17 04:43:21 guenther Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -478,7 +478,7 @@ fusefs_setattr(void *v) io->fi_flags |= FUSE_FATTR_SIZE; } - if (vap->va_atime.tv_sec != VNOVAL) { + if (vap->va_atime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) { error = EROFS; goto out; @@ -488,7 +488,7 @@ fusefs_setattr(void *v) io->fi_flags |= FUSE_FATTR_ATIME; } - if (vap->va_mtime.tv_sec != VNOVAL) { + if (vap->va_mtime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) { error = EROFS; goto out; @@ -497,6 +497,7 @@ fusefs_setattr(void *v) fbuf->fb_vattr.va_mtime.tv_nsec = vap->va_mtime.tv_nsec; io->fi_flags |= FUSE_FATTR_MTIME; } + /* XXX should set a flag if (vap->va_vaflags & VA_UTIMES_CHANGE) */ if (vap->va_mode != (mode_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) { diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 3f1646010bf..723f1109374 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vnops.c,v 1.99 2015/03/14 03:38:51 jsg Exp $ */ +/* $OpenBSD: msdosfs_vnops.c,v 1.100 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */ /*- @@ -451,7 +451,9 @@ msdosfs_setattr(void *v) if (error) return error; } - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { + if ((vap->va_vaflags & VA_UTIMES_CHANGE) || + vap->va_atime.tv_nsec != VNOVAL || + vap->va_mtime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EINVAL); if (cred->cr_uid != pmp->pm_uid && @@ -461,12 +463,12 @@ msdosfs_setattr(void *v) return (error); if (vp->v_type != VDIR) { if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && - vap->va_atime.tv_sec != VNOVAL) { + vap->va_atime.tv_nsec != VNOVAL) { dep->de_flag &= ~DE_ACCESS; unix2dostime(&vap->va_atime, &dep->de_ADate, NULL, NULL); } - if (vap->va_mtime.tv_sec != VNOVAL) { + if (vap->va_mtime.tv_nsec != VNOVAL) { dep->de_flag &= ~DE_UPDATE; unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime, NULL); diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c index ac27c29b8c0..7fb7eb5d560 100644 --- a/sys/nfs/nfs_subs.c +++ b/sys/nfs/nfs_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_subs.c,v 1.126 2015/03/14 03:38:52 jsg Exp $ */ +/* $OpenBSD: nfs_subs.c,v 1.127 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ /* @@ -1751,7 +1751,7 @@ nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full) tl = nfsm_build(&mb, NFSX_UNSIGNED); *tl = nfs_false; } - if (a->va_atime.tv_sec != VNOVAL) { + if (a->va_atime.tv_nsec != VNOVAL) { if (a->va_atime.tv_sec != time_second) { tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); @@ -1764,7 +1764,7 @@ nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full) tl = nfsm_build(&mb, NFSX_UNSIGNED); *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); } - if (a->va_mtime.tv_sec != VNOVAL) { + if (a->va_mtime.tv_nsec != VNOVAL) { if (a->va_mtime.tv_sec != time_second) { tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); @@ -1870,11 +1870,13 @@ nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); switch (fxdr_unsigned(int, *tl)) { case NFSV3SATTRTIME_TOCLIENT: + va->va_vaflags |= VA_UTIMES_CHANGE; va->va_vaflags &= ~VA_UTIMES_NULL; nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); fxdr_nfsv3time(tl, &va->va_atime); break; case NFSV3SATTRTIME_TOSERVER: + va->va_vaflags |= VA_UTIMES_CHANGE; getnanotime(&va->va_atime); break; }; @@ -1882,11 +1884,13 @@ nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); switch (fxdr_unsigned(int, *tl)) { case NFSV3SATTRTIME_TOCLIENT: + va->va_vaflags |= VA_UTIMES_CHANGE; va->va_vaflags &= ~VA_UTIMES_NULL; nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); fxdr_nfsv3time(tl, &va->va_mtime); break; case NFSV3SATTRTIME_TOSERVER: + va->va_vaflags |= VA_UTIMES_CHANGE; getnanotime(&va->va_mtime); break; }; @@ -1896,3 +1900,22 @@ nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, nfsmout: return (error); } + +void +txdr_nfsv2time(const struct timespec *from, struct nfsv2_time *to) +{ + if (from->tv_nsec == VNOVAL) { + to->nfsv2_sec = nfs_xdrneg1; + to->nfsv2_usec = nfs_xdrneg1; + } else if (from->tv_sec == -1) { + /* + * can't request a time of -1; send + * -1.000001 == {-2,999999} instead + */ + to->nfsv2_sec = htonl(-2); + to->nfsv2_usec = htonl(999999); + } else { + to->nfsv2_sec = htonl(from->tv_sec); + to->nfsv2_usec = htonl(from->tv_nsec / 1000); + } +} diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 8569053dd79..839624970d8 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vnops.c,v 1.162 2015/03/14 03:38:52 jsg Exp $ */ +/* $OpenBSD: nfs_vnops.c,v 1.163 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ /* @@ -565,8 +565,10 @@ nfs_setattr(void *v) * Disallow write attempts if the filesystem is mounted read-only. */ if ((vap->va_uid != (uid_t)VNOVAL || - vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || - vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && + vap->va_gid != (gid_t)VNOVAL || + vap->va_atime.tv_nsec != VNOVAL || + vap->va_mtime.tv_nsec != VNOVAL || + vap->va_mode != (mode_t)VNOVAL) && (vp->v_mount->mnt_flag & MNT_RDONLY)) return (EROFS); if (vap->va_size != VNOVAL) { @@ -577,8 +579,8 @@ nfs_setattr(void *v) case VBLK: case VSOCK: case VFIFO: - if (vap->va_mtime.tv_sec == VNOVAL && - vap->va_atime.tv_sec == VNOVAL && + if (vap->va_mtime.tv_nsec == VNOVAL && + vap->va_atime.tv_nsec == VNOVAL && vap->va_mode == (mode_t)VNOVAL && vap->va_uid == (uid_t)VNOVAL && vap->va_gid == (gid_t)VNOVAL) @@ -604,8 +606,8 @@ nfs_setattr(void *v) np->n_size = np->n_vattr.va_size = vap->va_size; uvm_vnp_setsize(vp, np->n_size); }; - } else if ((vap->va_mtime.tv_sec != VNOVAL || - vap->va_atime.tv_sec != VNOVAL) && + } else if ((vap->va_mtime.tv_nsec != VNOVAL || + vap->va_atime.tv_nsec != VNOVAL) && vp->v_type == VREG && (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p)) == EINTR) @@ -2172,6 +2174,7 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, ndp = (struct nfs_dirent *) uiop->uio_iov->iov_base; dp = &ndp->dirent; + memset(dp, 0, sizeof(dp)); dp->d_fileno = fileno; dp->d_namlen = len; dp->d_reclen = tlen; diff --git a/sys/nfs/xdr_subs.h b/sys/nfs/xdr_subs.h index 80b8b2ad1fd..05324284662 100644 --- a/sys/nfs/xdr_subs.h +++ b/sys/nfs/xdr_subs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xdr_subs.h,v 1.9 2013/08/13 05:52:25 guenther Exp $ */ +/* $OpenBSD: xdr_subs.h,v 1.10 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: xdr_subs.h,v 1.11 1996/02/18 11:54:12 fvdl Exp $ */ /* @@ -60,13 +60,9 @@ else \ (t)->tv_nsec = 0; \ } while (0) -#define txdr_nfsv2time(f, t) do { \ - ((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \ - if ((f)->tv_nsec != -1) \ - ((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \ - else \ - ((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \ -} while (0) + +struct nfsv2_time; +void txdr_nfsv2time(const struct timespec *_from, struct nfsv2_time *_to); #define fxdr_nfsv3time(f, t) do { \ (t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index b9dc772c99f..85727da1bc5 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vnode.h,v 1.129 2015/01/09 05:01:57 tedu Exp $ */ +/* $OpenBSD: vnode.h,v 1.130 2015/04/17 04:43:20 guenther Exp $ */ /* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ /* @@ -150,7 +150,9 @@ struct vnode { /* * Vnode attributes. A field value of VNOVAL represents a field whose value - * is unavailable (getattr) or which is not to be changed (setattr). + * is unavailable (getattr) or which is not to be changed (setattr). For + * the timespec fields, only the tv_nsec member needs to be set to VNOVAL: + * if tv_nsec != VNOVAL then both tv_sec and tv_nsec are valid. */ struct vattr { enum vtype va_type; /* vnode type (for create) */ @@ -177,8 +179,9 @@ struct vattr { /* * Flags for va_vaflags. */ -#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ -#define VA_EXCLUSIVE 0x02 /* exclusive create request */ +#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ +#define VA_EXCLUSIVE 0x02 /* exclusive create request */ +#define VA_UTIMES_CHANGE 0x04 /* ctime should be updated */ /* * Flags for ioflag. */ diff --git a/sys/tmpfs/tmpfs_subr.c b/sys/tmpfs/tmpfs_subr.c index a36eb21abba..ce21637c541 100644 --- a/sys/tmpfs/tmpfs_subr.c +++ b/sys/tmpfs/tmpfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_subr.c,v 1.13 2015/02/10 21:56:10 miod Exp $ */ +/* $OpenBSD: tmpfs_subr.c,v 1.14 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: tmpfs_subr.c,v 1.79 2012/03/13 18:40:50 elad Exp $ */ /* @@ -1112,12 +1112,17 @@ tmpfs_chtimes(struct vnode *vp, const struct timespec *atime, (error = VOP_ACCESS(vp, VWRITE, cred, p)))) return error; - if (atime->tv_sec != VNOVAL && atime->tv_nsec != VNOVAL) + if (atime->tv_nsec != VNOVAL) node->tn_atime = *atime; - if (mtime->tv_sec != VNOVAL && mtime->tv_nsec != VNOVAL) + if (mtime->tv_nsec != VNOVAL) node->tn_mtime = *mtime; + + if (mtime->tv_nsec != VNOVAL || (vaflags & VA_UTIMES_CHANGE)) + tmpfs_update(VP_TO_TMPFS_NODE(vp), TMPFS_NODE_CHANGED); + VN_KNOTE(vp, NOTE_ATTRIB); + return 0; } diff --git a/sys/tmpfs/tmpfs_vnops.c b/sys/tmpfs/tmpfs_vnops.c index 4da35bf4544..518d799ae11 100644 --- a/sys/tmpfs/tmpfs_vnops.c +++ b/sys/tmpfs/tmpfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_vnops.c,v 1.21 2015/03/14 03:38:52 jsg Exp $ */ +/* $OpenBSD: tmpfs_vnops.c,v 1.22 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */ /* @@ -480,7 +480,7 @@ tmpfs_getattr(void *v) return 0; } -#define GOODTIME(tv) ((tv)->tv_sec != VNOVAL || (tv)->tv_nsec != VNOVAL) +#define GOODTIME(tv) ((tv)->tv_nsec != VNOVAL) /* XXX Should this operation be atomic? I think it should, but code in * XXX other places (e.g., ufs) doesn't seem to be... */ int @@ -519,13 +519,12 @@ tmpfs_setattr(void *v) if (error == 0 && (vap->va_mode != VNOVAL)) error = tmpfs_chmod(vp, vap->va_mode, cred, p); - if (error == 0 && (GOODTIME(&vap->va_atime) - || GOODTIME(&vap->va_mtime))) { + if (error == 0 && ((vap->va_vaflags & VA_UTIMES_CHANGE) + || GOODTIME(&vap->va_atime) + || GOODTIME(&vap->va_mtime))) error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime, vap->va_vaflags, cred, p); - if (error == 0) - return 0; - } + return error; } diff --git a/sys/ufs/ext2fs/ext2fs_vnops.c b/sys/ufs/ext2fs/ext2fs_vnops.c index c88e6f4617b..13c3356781b 100644 --- a/sys/ufs/ext2fs/ext2fs_vnops.c +++ b/sys/ufs/ext2fs/ext2fs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_vnops.c,v 1.72 2015/03/14 03:38:52 jsg Exp $ */ +/* $OpenBSD: ext2fs_vnops.c,v 1.73 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: ext2fs_vnops.c,v 1.1 1997/06/11 09:34:09 bouyer Exp $ */ /* @@ -290,7 +290,9 @@ ext2fs_setattr(void *v) if (error) return (error); } - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { + if ((vap->va_vaflags & VA_UTIMES_CHANGE) || + vap->va_atime.tv_nsec != VNOVAL || + vap->va_mtime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != ip->i_e2fs_uid && @@ -298,17 +300,19 @@ ext2fs_setattr(void *v) ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)))) return (error); - if (vap->va_mtime.tv_sec != VNOVAL) + if (vap->va_mtime.tv_nsec != VNOVAL) ip->i_flag |= IN_CHANGE | IN_UPDATE; - if (vap->va_atime.tv_sec != VNOVAL) { + else if (vap->va_vaflags & VA_UTIMES_CHANGE) + ip->i_flag |= IN_CHANGE; + if (vap->va_atime.tv_nsec != VNOVAL) { if (!(vp->v_mount->mnt_flag & MNT_NOATIME) || (ip->i_flag & (IN_CHANGE | IN_UPDATE))) ip->i_flag |= IN_ACCESS; } EXT2FS_ITIMES(ip); - if (vap->va_mtime.tv_sec != VNOVAL) + if (vap->va_mtime.tv_nsec != VNOVAL) ip->i_e2fs_mtime = vap->va_mtime.tv_sec; - if (vap->va_atime.tv_sec != VNOVAL) + if (vap->va_atime.tv_nsec != VNOVAL) ip->i_e2fs_atime = vap->va_atime.tv_sec; error = ext2fs_update(ip, 1); if (error) diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 13761130ce3..e6f543b8cb9 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.120 2015/03/14 03:38:53 jsg Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.121 2015/04/17 04:43:21 guenther Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -420,7 +420,9 @@ ufs_setattr(void *v) if (vap->va_size < oldsize) hint |= NOTE_TRUNCATE; } - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { + if ((vap->va_vaflags & VA_UTIMES_CHANGE) || + vap->va_atime.tv_nsec != VNOVAL || + vap->va_mtime.tv_nsec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != DIP(ip, uid) && @@ -428,19 +430,21 @@ ufs_setattr(void *v) ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)))) return (error); - if (vap->va_mtime.tv_sec != VNOVAL) + if (vap->va_mtime.tv_nsec != VNOVAL) ip->i_flag |= IN_CHANGE | IN_UPDATE; - if (vap->va_atime.tv_sec != VNOVAL) { + else if (vap->va_vaflags & VA_UTIMES_CHANGE) + ip->i_flag |= IN_CHANGE; + if (vap->va_atime.tv_nsec != VNOVAL) { if (!(vp->v_mount->mnt_flag & MNT_NOATIME) || (ip->i_flag & (IN_CHANGE | IN_UPDATE))) ip->i_flag |= IN_ACCESS; } ufs_itimes(vp); - if (vap->va_mtime.tv_sec != VNOVAL) { + if (vap->va_mtime.tv_nsec != VNOVAL) { DIP_ASSIGN(ip, mtime, vap->va_mtime.tv_sec); DIP_ASSIGN(ip, mtimensec, vap->va_mtime.tv_nsec); } - if (vap->va_atime.tv_sec != VNOVAL) { + if (vap->va_atime.tv_nsec != VNOVAL) { DIP_ASSIGN(ip, atime, vap->va_atime.tv_sec); DIP_ASSIGN(ip, atimensec, vap->va_atime.tv_nsec); }