From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Source kernel commit: 5a0bb066f60fa02f453d7721844eae59f505c06e Redefine xfs_timestamp_t as a __be64 typedef in preparation for the bigtime functionality. Preserve the legacy structure format so that we can let the compiler take care of masking and shifting. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> Reviewed-by: Gao Xiang <hsiangkao@xxxxxxxxxx> Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx> Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- db/fprint.c | 10 +++++---- libxfs/libxfs_api_defs.h | 1 + libxfs/xfs_format.h | 10 ++++++--- libxfs/xfs_inode_buf.c | 54 ++++++++++++++++++++++++++++++++-------------- libxfs/xfs_inode_buf.h | 2 ++ repair/dinode.c | 5 +++- 6 files changed, 58 insertions(+), 24 deletions(-) diff --git a/db/fprint.c b/db/fprint.c index 996e9325ddcc..1e8a7b49efe6 100644 --- a/db/fprint.c +++ b/db/fprint.c @@ -123,6 +123,7 @@ fp_time( int base, int array) { + struct timespec64 tv; xfs_timestamp_t *ts; int bitpos; char *c; @@ -137,7 +138,8 @@ fp_time( dbprintf("%d:", i + base); ts = obj + byteize(bitpos); - t = (int)be32_to_cpu(ts->t_sec); + tv = libxfs_inode_from_disk_ts(*ts); + t = tv.tv_sec; c = ctime(&t); dbprintf("%24.24s", c); @@ -159,8 +161,8 @@ fp_nsec( int base, int array) { + struct timespec64 tv; xfs_timestamp_t *ts; - unsigned int nsec; int bitpos; int i; @@ -172,9 +174,9 @@ fp_nsec( dbprintf("%d:", i + base); ts = obj + byteize(bitpos); - nsec = (int)be32_to_cpu(ts->t_nsec); + tv = libxfs_inode_from_disk_ts(*ts); - dbprintf("%u", nsec); + dbprintf("%u", tv.tv_nsec); if (i < count - 1) dbprintf(" "); diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 7029d0e7daf7..40da71ab3163 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -116,6 +116,7 @@ #define xfs_inobt_maxrecs libxfs_inobt_maxrecs #define xfs_inobt_stage_cursor libxfs_inobt_stage_cursor #define xfs_inode_from_disk libxfs_inode_from_disk +#define xfs_inode_from_disk_ts libxfs_inode_from_disk_ts #define xfs_inode_to_disk libxfs_inode_to_disk #define xfs_inode_validate_cowextsize libxfs_inode_validate_cowextsize #define xfs_inode_validate_extsize libxfs_inode_validate_extsize diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index a5bf27afdd44..ca11a3eb56dd 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -856,12 +856,16 @@ struct xfs_agfl { * seconds and nanoseconds; time zero is the Unix epoch, Jan 1 00:00:00 UTC * 1970, which means that the timestamp epoch is the same as the Unix epoch. * Therefore, the ondisk min and max defined here can be used directly to - * constrain the incore timestamps on a Unix system. + * constrain the incore timestamps on a Unix system. Note that we actually + * encode a __be64 value on disk. */ -typedef struct xfs_timestamp { +typedef __be64 xfs_timestamp_t; + +/* Legacy timestamp encoding format. */ +struct xfs_legacy_timestamp { __be32 t_sec; /* timestamp seconds */ __be32 t_nsec; /* timestamp nanoseconds */ -} xfs_timestamp_t; +}; /* * Smallest possible ondisk seconds value with traditional timestamps. This diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index e3fdd71a0c63..1b9f63ebe9f9 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -154,6 +154,21 @@ xfs_imap_to_bp( return 0; } +/* Convert an ondisk timestamp to an incore timestamp. */ +struct timespec64 +xfs_inode_from_disk_ts( + const xfs_timestamp_t ts) +{ + struct timespec64 tv; + struct xfs_legacy_timestamp *lts; + + lts = (struct xfs_legacy_timestamp *)&ts; + tv.tv_sec = (int)be32_to_cpu(lts->t_sec); + tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec); + + return tv; +} + int xfs_inode_from_disk( struct xfs_inode *ip, @@ -208,12 +223,9 @@ xfs_inode_from_disk( * a time before epoch is converted to a time long after epoch * on 64 bit systems. */ - inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec); - inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec); - inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec); - inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec); - inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec); - inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec); + inode->i_atime = xfs_inode_from_disk_ts(from->di_atime); + inode->i_mtime = xfs_inode_from_disk_ts(from->di_mtime); + inode->i_ctime = xfs_inode_from_disk_ts(from->di_ctime); to->di_size = be64_to_cpu(from->di_size); to->di_nblocks = be64_to_cpu(from->di_nblocks); @@ -226,8 +238,7 @@ xfs_inode_from_disk( if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) { inode_set_iversion_queried(inode, be64_to_cpu(from->di_changecount)); - to->di_crtime.tv_sec = be32_to_cpu(from->di_crtime.t_sec); - to->di_crtime.tv_nsec = be32_to_cpu(from->di_crtime.t_nsec); + to->di_crtime = xfs_inode_from_disk_ts(from->di_crtime); to->di_flags2 = be64_to_cpu(from->di_flags2); to->di_cowextsize = be32_to_cpu(from->di_cowextsize); } @@ -249,6 +260,21 @@ xfs_inode_from_disk( return error; } +/* Convert an incore timestamp to an ondisk timestamp. */ +static inline xfs_timestamp_t +xfs_inode_to_disk_ts( + const struct timespec64 tv) +{ + struct xfs_legacy_timestamp *lts; + xfs_timestamp_t ts; + + lts = (struct xfs_legacy_timestamp *)&ts; + lts->t_sec = cpu_to_be32(tv.tv_sec); + lts->t_nsec = cpu_to_be32(tv.tv_nsec); + + return ts; +} + void xfs_inode_to_disk( struct xfs_inode *ip, @@ -268,12 +294,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.t_sec = cpu_to_be32(inode->i_atime.tv_sec); - to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec); - to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec); - to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec); - to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec); - to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec); + 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_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); @@ -292,8 +315,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.t_sec = cpu_to_be32(from->di_crtime.tv_sec); - to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.tv_nsec); + to->di_crtime = xfs_inode_to_disk_ts(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); diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h index 89f7bea8efd6..3060ecd24a2e 100644 --- a/libxfs/xfs_inode_buf.h +++ b/libxfs/xfs_inode_buf.h @@ -58,4 +58,6 @@ 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); + #endif /* __XFS_INODE_BUF_H__ */ diff --git a/repair/dinode.c b/repair/dinode.c index 95e57b5318b5..c1d9d9727d62 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2167,9 +2167,12 @@ static void check_nsec( const char *name, xfs_ino_t lino, - struct xfs_timestamp *t, + xfs_timestamp_t *ts, int *dirty) { + struct xfs_legacy_timestamp *t; + + t = (struct xfs_legacy_timestamp *)ts; if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC) return;