git: c40a160fd0aa - main - Make inode extra time fields updating logic more closer to linux.

Fedor Uporov fsu at FreeBSD.org
Fri May 7 07:49:19 UTC 2021


The branch main has been updated by fsu:

URL: https://cgit.FreeBSD.org/src/commit/?id=c40a160fd0aa48ceb6e243c72cb8b9b59dc4e13d

commit c40a160fd0aa48ceb6e243c72cb8b9b59dc4e13d
Author:     Fedor Uporov <fsu at FreeBSD.org>
AuthorDate: 2021-05-07 07:46:55 +0000
Commit:     Fedor Uporov <fsu at FreeBSD.org>
CommitDate: 2021-05-07 07:46:55 +0000

    Make inode extra time fields updating logic more closer to linux.
    
    Found using pjdfstest:
    pjdfstest/tests/utimensat/09.t
    
    Reviewed by:    pfg
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D29933
---
 sys/fs/ext2fs/ext2_inode_cnv.c | 53 ++++++++++++++++++++++++++++++------------
 sys/fs/ext2fs/inode.h          |  9 +++----
 2 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c
index 3c79e1162896..5ca00f3be050 100644
--- a/sys/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -94,8 +94,6 @@ ext2_print_inode(struct inode *in)
 }
 #endif	/* EXT2FS_PRINT_EXTENTS */
 
-#define XTIME_TO_NSEC(x)	((le32toh(x) & EXT3_NSEC_MASK) >> 2)
-
 static inline bool
 ext2_old_valid_dev(dev_t dev)
 {
@@ -132,6 +130,15 @@ ext2_new_decode_dev(uint32_t dev)
 	return (makedev(maj, min));
 }
 
+static void
+ext2_decode_extra_time(ext_time_t *sec, int32_t *nsec, uint32_t extra)
+{
+	if (extra & htole32(EXT3_EPOCH_MASK))
+		*sec += (uint64_t)(le32toh(extra) & EXT3_EPOCH_MASK) << 32;
+
+	*nsec = (le32toh(extra) & EXT3_NSEC_MASK) >> EXT3_EPOCH_BITS;
+}
+
 /*
  *	raw ext2 inode LE to host inode conversion
  */
@@ -177,15 +184,19 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
 	ip->i_size = le32toh(ei->e2di_size);
 	if (S_ISREG(ip->i_mode))
 		ip->i_size |= (uint64_t)le32toh(ei->e2di_size_high) << 32;
-	ip->i_atime = le32toh(ei->e2di_atime);
-	ip->i_mtime = le32toh(ei->e2di_mtime);
-	ip->i_ctime = le32toh(ei->e2di_ctime);
+	ip->i_atime = (signed)le32toh(ei->e2di_atime);
+	ip->i_mtime = (signed)le32toh(ei->e2di_mtime);
+	ip->i_ctime = (signed)le32toh(ei->e2di_ctime);
 	if (E2DI_HAS_XTIME(ip)) {
-		ip->i_atimensec = XTIME_TO_NSEC(ei->e2di_atime_extra);
-		ip->i_mtimensec = XTIME_TO_NSEC(ei->e2di_mtime_extra);
-		ip->i_ctimensec = XTIME_TO_NSEC(ei->e2di_ctime_extra);
-		ip->i_birthtime = le32toh(ei->e2di_crtime);
-		ip->i_birthnsec = XTIME_TO_NSEC(ei->e2di_crtime_extra);
+		ext2_decode_extra_time(&ip->i_atime, &ip->i_atimensec,
+		    ei->e2di_atime_extra);
+		ext2_decode_extra_time(&ip->i_mtime, &ip->i_mtimensec,
+		    ei->e2di_mtime_extra);
+		ext2_decode_extra_time(&ip->i_ctime, &ip->i_ctimensec,
+		    ei->e2di_ctime_extra);
+		ip->i_birthtime = (signed)le32toh(ei->e2di_crtime);
+		ext2_decode_extra_time(&ip->i_birthtime, &ip->i_birthnsec,
+		    ei->e2di_crtime_extra);
 	}
 	ip->i_flags = 0;
 	ei_flags_host = le32toh(ei->e2di_flags);
@@ -226,7 +237,15 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
 	return (ext2_ei_csum_verify(ip, ei));
 }
 
-#define NSEC_TO_XTIME(t)	(htole32((t << 2) & EXT3_NSEC_MASK))
+static uint32_t
+ext2_encode_extra_time(int64_t sec, int32_t nsec)
+{
+	uint32_t extra;
+
+	extra = ((sec - (int32_t)sec) >> 32) & EXT3_EPOCH_MASK;
+
+	return (htole32(extra | (nsec << EXT3_EPOCH_BITS)));
+}
 
 /*
  *	inode to raw ext2 LE inode conversion
@@ -253,11 +272,15 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
 	ei->e2di_dtime = htole32(le16toh(ei->e2di_nlink) ? 0 :
 	    le32toh(ei->e2di_mtime));
 	if (E2DI_HAS_XTIME(ip)) {
-		ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec);
-		ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec);
-		ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec);
+		ei->e2di_ctime_extra = ext2_encode_extra_time(ip->i_ctime,
+		    ip->i_ctimensec);
+		ei->e2di_mtime_extra = ext2_encode_extra_time(ip->i_mtime,
+		    ip->i_mtimensec);
+		ei->e2di_atime_extra = ext2_encode_extra_time(ip->i_atime,
+		    ip->i_atimensec);
 		ei->e2di_crtime = htole32(ip->i_birthtime);
-		ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
+		ei->e2di_crtime_extra = ext2_encode_extra_time(ip->i_birthtime,
+		    ip->i_birthnsec);
 	}
 	/* Keep these in host endian for a while since they change a lot */
 	ei->e2di_flags = 0;
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index e6af6ef8d5b6..25e77acc3a9d 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -62,6 +62,7 @@
 typedef uint32_t e2fs_daddr_t;
 typedef int64_t e2fs_lbn_t;
 typedef int64_t e4fs_daddr_t;
+typedef int64_t ext_time_t;
 
 /*
  * The inode is used to describe each active (or recently active) file in the
@@ -99,10 +100,10 @@ struct inode {
 	uint32_t	i_gid;		/* File group. */
 	uint64_t	i_size;		/* File byte count. */
 	uint64_t	i_blocks;	/* Blocks actually held. */
-	int32_t		i_atime;	/* Last access time. */
-	int32_t		i_mtime;	/* Last modified time. */
-	int32_t		i_ctime;	/* Last inode change time. */
-	int32_t		i_birthtime;	/* Inode creation time. */
+	ext_time_t	i_atime;	/* Last access time. */
+	ext_time_t	i_mtime;	/* Last modified time. */
+	ext_time_t	i_ctime;	/* Last inode change time. */
+	ext_time_t	i_birthtime;	/* Inode creation time. */
 	int32_t		i_mtimensec;	/* Last modified time. */
 	int32_t		i_atimensec;	/* Last access time. */
 	int32_t		i_ctimensec;	/* Last inode change time. */


More information about the dev-commits-src-all mailing list