On Thu, Aug 27, 2020 at 07:58:16AM +0100, Christoph Hellwig wrote: > > - 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. <shrug> I think I'd rather just keep the legacy struct xfs_{ic,}timestamp, change the xfs_dinode/xfs_log_dinode structs to have a be64/u64 timestamp, and cast pointers as needed to support the legacy formats. > > @@ -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; > > ? Heh, ok, will do. > > +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; > } > > ? The previous version had it that way; Dave asked me to make it a helper. --D