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)