xfs: redefine xfs_timestamp_t
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 24 Aug 2020 22:15:46 +0000 (15:15 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 16 Sep 2020 03:52:41 +0000 (20:52 -0700)
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@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/libxfs/xfs_inode_buf.h
fs/xfs/scrub/inode.c
fs/xfs/xfs_inode_item_recover.c
fs/xfs/xfs_ondisk.h

index 4b68a47..d9b629f 100644 (file)
@@ -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
index fa83591..4dc43be 100644 (file)
@@ -157,6 +157,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,
@@ -211,12 +226,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);
@@ -229,8 +241,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);
        }
@@ -252,6 +263,21 @@ out_destroy_data_fork:
        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,
@@ -271,12 +297,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);
@@ -295,8 +318,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);
index 89f7bea..3060ecd 100644 (file)
@@ -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__ */
index 6d483ab..eb1cc01 100644 (file)
@@ -195,6 +195,19 @@ bad:
        xchk_ino_set_corrupt(sc, ino);
 }
 
+static inline void
+xchk_dinode_nsec(
+       struct xfs_scrub        *sc,
+       xfs_ino_t               ino,
+       const xfs_timestamp_t   ts)
+{
+       struct timespec64       tv;
+
+       tv = xfs_inode_from_disk_ts(ts);
+       if (tv.tv_nsec < 0 || tv.tv_nsec >= NSEC_PER_SEC)
+               xchk_ino_set_corrupt(sc, ino);
+}
+
 /* Scrub all the ondisk inode fields. */
 STATIC void
 xchk_dinode(
@@ -293,12 +306,9 @@ xchk_dinode(
        }
 
        /* di_[amc]time.nsec */
-       if (be32_to_cpu(dip->di_atime.t_nsec) >= NSEC_PER_SEC)
-               xchk_ino_set_corrupt(sc, ino);
-       if (be32_to_cpu(dip->di_mtime.t_nsec) >= NSEC_PER_SEC)
-               xchk_ino_set_corrupt(sc, ino);
-       if (be32_to_cpu(dip->di_ctime.t_nsec) >= NSEC_PER_SEC)
-               xchk_ino_set_corrupt(sc, ino);
+       xchk_dinode_nsec(sc, ino, dip->di_atime);
+       xchk_dinode_nsec(sc, ino, dip->di_mtime);
+       xchk_dinode_nsec(sc, ino, dip->di_ctime);
 
        /*
         * di_size.  xfs_dinode_verify checks for things that screw up
@@ -403,8 +413,7 @@ xchk_dinode(
        }
 
        if (dip->di_version >= 3) {
-               if (be32_to_cpu(dip->di_crtime.t_nsec) >= NSEC_PER_SEC)
-                       xchk_ino_set_corrupt(sc, ino);
+               xchk_dinode_nsec(sc, ino, dip->di_crtime);
                xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
                xchk_inode_cowextsize(sc, dip, ino, mode, flags,
                                flags2);
index 1e417ac..03fab43 100644 (file)
@@ -115,6 +115,21 @@ out_free_ip:
        return error;
 }
 
+/* Convert a log timestamp to an ondisk timestamp. */
+static inline xfs_timestamp_t
+xfs_log_dinode_to_disk_ts(
+       const xfs_ictimestamp_t         its)
+{
+       struct xfs_legacy_timestamp     *lts;
+       xfs_timestamp_t                 ts;
+
+       lts = (struct xfs_legacy_timestamp *)&ts;
+       lts->t_sec = cpu_to_be32(its.t_sec);
+       lts->t_nsec = cpu_to_be32(its.t_nsec);
+
+       return ts;
+}
+
 STATIC void
 xfs_log_dinode_to_disk(
        struct xfs_log_dinode   *from,
@@ -132,12 +147,9 @@ xfs_log_dinode_to_disk(
        to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
        memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
 
-       to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
-       to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
-       to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
-       to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
-       to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
-       to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
+       to->di_atime = xfs_log_dinode_to_disk_ts(from->di_atime);
+       to->di_mtime = xfs_log_dinode_to_disk_ts(from->di_mtime);
+       to->di_ctime = xfs_log_dinode_to_disk_ts(from->di_ctime);
 
        to->di_size = cpu_to_be64(from->di_size);
        to->di_nblocks = cpu_to_be64(from->di_nblocks);
@@ -153,8 +165,7 @@ xfs_log_dinode_to_disk(
 
        if (from->di_version == 3) {
                to->di_changecount = cpu_to_be64(from->di_changecount);
-               to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
-               to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
+               to->di_crtime = xfs_log_dinode_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(from->di_ino);
index acb9b73..4e5f51d 100644 (file)
@@ -41,7 +41,8 @@ xfs_check_ondisk_structs(void)
        XFS_CHECK_STRUCT_SIZE(struct xfs_refcount_rec,          12);
        XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_key,              20);
        XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_rec,              24);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_timestamp,             8);
+       XFS_CHECK_STRUCT_SIZE(xfs_timestamp_t,                  8);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_legacy_timestamp,      8);
        XFS_CHECK_STRUCT_SIZE(xfs_alloc_key_t,                  8);
        XFS_CHECK_STRUCT_SIZE(xfs_alloc_ptr_t,                  4);
        XFS_CHECK_STRUCT_SIZE(xfs_alloc_rec_t,                  8);