Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ext2fs get and set expanded timestamp if the inode c...
details: https://anonhg.NetBSD.org/src/rev/bfa7c0ea2978
branches: trunk
changeset: 346801:bfa7c0ea2978
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Wed Aug 03 23:29:05 2016 +0000
description:
get and set expanded timestamp if the inode contains the extra information, add support for create time
diffstat:
sys/ufs/ext2fs/ext2fs_dinode.h | 48 +++++++++++++++++++++++++++++++++++++++++-
sys/ufs/ext2fs/ext2fs_subr.c | 10 ++++----
sys/ufs/ext2fs/ext2fs_vnops.c | 23 ++++++++++++-------
3 files changed, 66 insertions(+), 15 deletions(-)
diffs (160 lines):
diff -r f1262a9a4a8d -r bfa7c0ea2978 sys/ufs/ext2fs/ext2fs_dinode.h
--- a/sys/ufs/ext2fs/ext2fs_dinode.h Wed Aug 03 23:28:01 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_dinode.h Wed Aug 03 23:29:05 2016 +0000
@@ -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 @@
)
/*
+ * 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
diff -r f1262a9a4a8d -r bfa7c0ea2978 sys/ufs/ext2fs/ext2fs_subr.c
--- a/sys/ufs/ext2fs/ext2fs_subr.c Wed Aug 03 23:28:01 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_subr.c Wed Aug 03 23:29:05 2016 +0000
@@ -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 @@
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;
diff -r f1262a9a4a8d -r bfa7c0ea2978 sys/ufs/ext2fs/ext2fs_vnops.c
--- a/sys/ufs/ext2fs/ext2fs_vnops.c Wed Aug 03 23:28:01 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_vnops.c Wed Aug 03 23:29:05 2016 +0000
@@ -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 @@
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 @@
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 @@
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)
Home |
Main Index |
Thread Index |
Old Index