Module Name: src Committed By: jdolecek Date: Wed Aug 3 23:29:05 UTC 2016
Modified Files: src/sys/ufs/ext2fs: ext2fs_dinode.h ext2fs_subr.c ext2fs_vnops.c Log Message: get and set expanded timestamp if the inode contains the extra information, add support for create time To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/ufs/ext2fs/ext2fs_dinode.h cvs rdiff -u -r1.31 -r1.32 src/sys/ufs/ext2fs/ext2fs_subr.c cvs rdiff -u -r1.118 -r1.119 src/sys/ufs/ext2fs/ext2fs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ext2fs/ext2fs_dinode.h diff -u src/sys/ufs/ext2fs/ext2fs_dinode.h:1.28 src/sys/ufs/ext2fs/ext2fs_dinode.h:1.29 --- src/sys/ufs/ext2fs/ext2fs_dinode.h:1.28 Wed Aug 3 21:53:02 2016 +++ src/sys/ufs/ext2fs/ext2fs_dinode.h Wed Aug 3 23:29:05 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_dinode.h,v 1.28 2016/08/03 21:53:02 jdolecek Exp $ */ +/* $NetBSD: ext2fs_dinode.h,v 1.29 2016/08/03 23:29:05 jdolecek Exp $ */ /* * Copyright (c) 1982, 1989, 1993 @@ -189,6 +189,52 @@ struct ext2fs_dinode { ) /* + * Time encoding + * Lower two bits of extra field are extra high bits for epoch; unfortunately still, Linux kernels treat 11 there as 00 for compatibility + * Rest of extra fields are nanoseconds + */ +static __inline void +ext2fs_dinode_time_get(struct timespec *ts, uint32_t epoch, uint32_t extra) +{ + ts->tv_sec = (signed) epoch; + + if (extra) { + uint64_t epoch_bits = extra & 0x3; + /* XXX compatibility with linux kernel < 4.20 */ + if (epoch_bits == 3 && ts->tv_sec < 0) + epoch_bits = 0; + + ts->tv_sec |= epoch_bits << 32; + + ts->tv_nsec = extra >> 2; + } else { + ts->tv_nsec = 0; + } +} +#define EXT2_DINODE_TIME_GET(ts, dinode, field, isize) \ + ext2fs_dinode_time_get(ts, (dinode)->field, \ + EXT2_DINODE_FITS(dinode, field ## _extra, isize) \ + ? (dinode)->field ## _extra : 0 \ + ) + +static __inline void +ext2fs_dinode_time_set(const struct timespec *ts, uint32_t *epoch, uint32_t *extra) +{ + *epoch = (int32_t) ts->tv_sec; + + if (extra) { + uint32_t epoch_bits = (ts->tv_sec >> 32) & 0x3; + + *extra = (ts->tv_nsec << 2) | epoch_bits; + } +} +#define EXT2_DINODE_TIME_SET(ts, dinode, field, isize) \ + ext2fs_dinode_time_set(ts, &(dinode)->field, \ + EXT2_DINODE_FITS(dinode, field ## _extra, isize) \ + ? &(dinode)->field ## _extra : NULL \ + ) + +/* * The e2di_blocks fields may be overlaid with other information for * file types that do not have associated disk storage. Block * and character devices overlay the first data block with their Index: src/sys/ufs/ext2fs/ext2fs_subr.c diff -u src/sys/ufs/ext2fs/ext2fs_subr.c:1.31 src/sys/ufs/ext2fs/ext2fs_subr.c:1.32 --- src/sys/ufs/ext2fs/ext2fs_subr.c:1.31 Sat Mar 28 19:24:04 2015 +++ src/sys/ufs/ext2fs/ext2fs_subr.c Wed Aug 3 23:29:05 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_subr.c,v 1.31 2015/03/28 19:24:04 maxv Exp $ */ +/* $NetBSD: ext2fs_subr.c,v 1.32 2016/08/03 23:29:05 jdolecek Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_subr.c,v 1.31 2015/03/28 19:24:04 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_subr.c,v 1.32 2016/08/03 23:29:05 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -115,18 +115,18 @@ ext2fs_itimes(struct inode *ip, const st if (ip->i_flag & IN_ACCESS) { if (acc == NULL) acc = &now; - ip->i_e2fs_atime = acc->tv_sec; + EXT2_DINODE_TIME_SET(acc, ip->i_din.e2fs_din, e2di_atime, EXT2_DINODE_SIZE(ip->i_e2fs)); } if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) { if (mod == NULL) mod = &now; - ip->i_e2fs_mtime = mod->tv_sec; + EXT2_DINODE_TIME_SET(mod, ip->i_din.e2fs_din, e2di_mtime, EXT2_DINODE_SIZE(ip->i_e2fs)); ip->i_modrev++; } if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) { if (cre == NULL) cre = &now; - ip->i_e2fs_ctime = cre->tv_sec; + EXT2_DINODE_TIME_SET(cre, ip->i_din.e2fs_din, e2di_ctime, EXT2_DINODE_SIZE(ip->i_e2fs)); } if (ip->i_flag & (IN_ACCESS | IN_MODIFY)) ip->i_flag |= IN_ACCESSED; Index: src/sys/ufs/ext2fs/ext2fs_vnops.c diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.118 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.119 --- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.118 Wed Aug 3 21:53:03 2016 +++ src/sys/ufs/ext2fs/ext2fs_vnops.c Wed Aug 3 23:29:05 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vnops.c,v 1.118 2016/08/03 21:53:03 jdolecek Exp $ */ +/* $NetBSD: ext2fs_vnops.c,v 1.119 2016/08/03 23:29:05 jdolecek Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.118 2016/08/03 21:53:03 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.119 2016/08/03 23:29:05 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -305,12 +305,12 @@ ext2fs_getattr(void *v) vap->va_gid = ip->i_gid; vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din->e2di_rdev); vap->va_size = vp->v_size; - vap->va_atime.tv_sec = ip->i_e2fs_atime; - vap->va_atime.tv_nsec = 0; - vap->va_mtime.tv_sec = ip->i_e2fs_mtime; - vap->va_mtime.tv_nsec = 0; - vap->va_ctime.tv_sec = ip->i_e2fs_ctime; - vap->va_ctime.tv_nsec = 0; + EXT2_DINODE_TIME_GET(&vap->va_atime, ip->i_din.e2fs_din, e2di_atime, EXT2_DINODE_SIZE(ip->i_e2fs)); + EXT2_DINODE_TIME_GET(&vap->va_mtime, ip->i_din.e2fs_din, e2di_mtime, EXT2_DINODE_SIZE(ip->i_e2fs)); + EXT2_DINODE_TIME_GET(&vap->va_ctime, ip->i_din.e2fs_din, e2di_ctime, EXT2_DINODE_SIZE(ip->i_e2fs)); + if (EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs))) { + EXT2_DINODE_TIME_GET(&vap->va_birthtime, ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs)); + } #ifdef EXT2FS_SYSTEM_FLAGS vap->va_flags = (ip->i_e2fs_flags & EXT2_APPEND) ? SF_APPEND : 0; vap->va_flags |= (ip->i_e2fs_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0; @@ -439,7 +439,7 @@ ext2fs_setattr(void *v) return (error); } ip = VTOI(vp); - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { + if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_birthtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, @@ -455,6 +455,11 @@ ext2fs_setattr(void *v) if (vp->v_mount->mnt_flag & MNT_RELATIME) ip->i_flag |= IN_ACCESS; } + if (vap->va_birthtime.tv_sec != VNOVAL && + EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs))) { + + EXT2_DINODE_TIME_SET(&vap->va_birthtime, ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs)); + } error = ext2fs_update(vp, &vap->va_atime, &vap->va_mtime, UPDATE_WAIT); if (error)