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/616ffe7c1a5a
branches:  trunk
changeset: 816943:616ffe7c1a5a
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 ea030d8d64f5 -r 616ffe7c1a5a 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 ea030d8d64f5 -r 616ffe7c1a5a 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 ea030d8d64f5 -r 616ffe7c1a5a 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