> - tv.tv_sec = (int64_t)t >> 32; > - tv.tv_nsec = (int32_t)(t & 0xffffffff); > + if (xfs_dinode_has_bigtime(dip)) { > + s = xfs_bigtime_to_unix(div_u64_rem(t, NSEC_PER_SEC, &n)); > + } else { > + s = (int64_t)t >> 32; > + n = (int32_t)(t & 0xffffffff); Move this branche into a xfs_legacytime_to_unix helper just to be symmetric? This also made me think of the encoding: another sensible option would be to always read the time stamps as two 32-bit values using the struct type, and just add them up for the bigtime case. > + if (xfs_inode_has_bigtime(ip)) > + t = xfs_inode_encode_bigtime(tv); > + else > + t = ((int64_t)tv.tv_sec << 32) | (tv.tv_nsec & 0xffffffff); > + Same here. > @@ -305,9 +320,9 @@ xfs_inode_to_disk( > to->di_projid_hi = cpu_to_be16(from->di_projid >> 16); > > memset(to->di_pad, 0, sizeof(to->di_pad)); > - to->di_atime = xfs_inode_to_disk_ts(inode->i_atime); > - to->di_mtime = xfs_inode_to_disk_ts(inode->i_mtime); > - to->di_ctime = xfs_inode_to_disk_ts(inode->i_ctime); > + to->di_atime = xfs_inode_to_disk_ts(ip, inode->i_atime); > + to->di_mtime = xfs_inode_to_disk_ts(ip, inode->i_mtime); > + to->di_ctime = xfs_inode_to_disk_ts(ip, inode->i_ctime); > to->di_nlink = cpu_to_be32(inode->i_nlink); > to->di_gen = cpu_to_be32(inode->i_generation); > to->di_mode = cpu_to_be16(inode->i_mode); > @@ -326,7 +341,7 @@ xfs_inode_to_disk( > if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) { > to->di_version = 3; > to->di_changecount = cpu_to_be64(inode_peek_iversion(inode)); > - to->di_crtime = xfs_inode_to_disk_ts(from->di_crtime); > + to->di_crtime = xfs_inode_to_disk_ts(ip, from->di_crtime); > to->di_flags2 = cpu_to_be64(from->di_flags2); > to->di_cowextsize = cpu_to_be32(from->di_cowextsize); > to->di_ino = cpu_to_be64(ip->i_ino); > @@ -546,6 +561,11 @@ xfs_dinode_verify( > if (fa) > return fa; > > + /* bigtime iflag can only happen on bigtime filesystems */ > + if (xfs_dinode_has_bigtime(dip) && > + !xfs_sb_version_hasbigtime(&mp->m_sb)) > + return __this_address; > + > return NULL; > } > > diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h > index 3060ecd24a2e..e05bfe52fd8f 100644 > --- a/fs/xfs/libxfs/xfs_inode_buf.h > +++ b/fs/xfs/libxfs/xfs_inode_buf.h > @@ -32,6 +32,11 @@ struct xfs_icdinode { > struct timespec64 di_crtime; /* time created */ > }; > > +static inline bool xfs_icdinode_has_bigtime(const struct xfs_icdinode *icd) > +{ > + return icd->di_flags2 & XFS_DIFLAG2_BIGTIME; > +} > + > /* > * Inode location information. Stored in the inode and passed to > * xfs_imap_to_bp() to get a buffer and dinode for a given inode. > @@ -58,6 +63,14 @@ xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp, > uint32_t cowextsize, uint16_t mode, uint16_t flags, > uint64_t flags2); > > -struct timespec64 xfs_inode_from_disk_ts(const xfs_timestamp_t ts); > +static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv) > +{ > + uint64_t t = xfs_unix_to_bigtime(tv.tv_sec) * NSEC_PER_SEC; > + > + return t + tv.tv_nsec; Why not: return xfs_unix_to_bigtime(tv.tv_sec) * NSEC_PER_SEC + tv.tv_nsec; ? > +static inline bool xfs_inode_want_bigtime_upgrade(struct xfs_inode *ip) > +{ > + return xfs_sb_version_hasbigtime(&ip->i_mount->m_sb) && > + !xfs_inode_has_bigtime(ip); > +} > + > /* > * This is called to mark the fields indicated in fieldmask as needing to be > * logged when the transaction is committed. The inode must already be > @@ -131,6 +137,16 @@ xfs_trans_log_inode( > iversion_flags = XFS_ILOG_CORE; > } > > + /* > + * If we're updating the inode core or the timestamps and it's possible > + * to upgrade this inode to bigtime format, do so now. > + */ > + if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) && > + xfs_inode_want_bigtime_upgrade(ip)) { > + ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME; > + flags |= XFS_ILOG_CORE; > + } I find the way to directly set XFS_DIFLAG2_BIGTIME but using a helper to check it here rather confusing. Why not: if (xfs_sb_version_hasbigtime(&ip->i_mount->m_sb) && (flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) && !(ip->i_d.di_flags2 & XFS_DIFLAG2_BIGTIME)) { ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME; flags |= XFS_ILOG_CORE; } ?