linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Amir Goldstein <amir73il@gmail.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [RFC][PATCH] xfs: extended timestamp range
Date: Mon, 11 Nov 2019 14:35:08 -0800	[thread overview]
Message-ID: <20191111223508.GS6219@magnolia> (raw)
In-Reply-To: <20191111213630.14680-1-amir73il@gmail.com>

On Mon, Nov 11, 2019 at 11:36:30PM +0200, Amir Goldstein wrote:
> Use similar on-disk encoding for timestamps as ext4 to push back
> the y2038 deadline to 2446.
> 
> The encoding uses the 2 free MSB in 32bit nsec field to extend the
> seconds field storage size to 34bit.
> 
> Those 2 bits should be zero on existing xfs inodes, so the extended
> timestamp range feature is declared read-only compatible with old
> on-disk format.

What do you think about making the timestamp field a uint64_t counting
nanoseconds since Dec 14 09:15:53 UTC 1901 (a.k.a. the minimum datetime
we support with the existing encoding scheme)?  Instead of using the
upper 2 bits of the nsec field for an epoch encoding, which ext4 screwed
up years ago and has not fully fixed?

Also, please change struct xfs_inode.i_crtime to a timespec64 to match
the other three timestamps in struct inode...

...and following the usual xfs indenting style for all the new functions.

--D

> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
> 
> Hi,
> 
> This is a very lightly tested RFC patch.
> Naming and splitting to patches aside, I'd like to know what folks think
> about this direction for fixing y2038 xfs support.
> 
> With XFS_TIMESTAMP_DEBUG defined, it provides correct output for test
> generic/402 (timestamp range test), when matching xfs expected timestamp
> ranges to those of ext4 (_filesystem_timestamp_range).
> And then the test (naturally) fails on corrupted fs check.
> 
> If this direction is acceptable, I will proceed with patching xfsprogs.
> 
> I'd also like to hear your thoughts about migration process.
> Should the new feature be ro_compat as I defined it or incompat?
> In pricipal, all user would need to do is set the feature flag, but
> I am not aware of any precedent of a similar format upgrade in xfs.
> 
> Thanks,
> Amir.
> 
>  fs/xfs/libxfs/xfs_format.h      |  14 ++-
>  fs/xfs/libxfs/xfs_inode_buf.c   |  36 ++++----
>  fs/xfs/libxfs/xfs_log_format.h  |   4 +-
>  fs/xfs/libxfs/xfs_timestamp.h   | 151 ++++++++++++++++++++++++++++++++
>  fs/xfs/libxfs/xfs_trans_inode.c |   7 +-
>  fs/xfs/scrub/inode.c            |  11 ++-
>  fs/xfs/xfs_inode.c              |   4 +-
>  fs/xfs/xfs_inode_item.c         |  13 ++-
>  fs/xfs/xfs_iops.c               |   5 +-
>  fs/xfs/xfs_itable.c             |   3 +-
>  fs/xfs/xfs_super.c              |   5 +-
>  11 files changed, 208 insertions(+), 45 deletions(-)
>  create mode 100644 fs/xfs/libxfs/xfs_timestamp.h
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index c968b60cee15..227a775a9889 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -449,10 +449,12 @@ xfs_sb_has_compat_feature(
>  #define XFS_SB_FEAT_RO_COMPAT_FINOBT   (1 << 0)		/* free inode btree */
>  #define XFS_SB_FEAT_RO_COMPAT_RMAPBT   (1 << 1)		/* reverse map btree */
>  #define XFS_SB_FEAT_RO_COMPAT_REFLINK  (1 << 2)		/* reflinked files */
> +#define XFS_SB_FEAT_RO_COMPAT_EXTTIME  (1 << 3)		/* extended time_max */
>  #define XFS_SB_FEAT_RO_COMPAT_ALL \
>  		(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
>  		 XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
> -		 XFS_SB_FEAT_RO_COMPAT_REFLINK)
> +		 XFS_SB_FEAT_RO_COMPAT_REFLINK | \
> +		 XFS_SB_FEAT_RO_COMPAT_EXTTIME)
>  #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN	~XFS_SB_FEAT_RO_COMPAT_ALL
>  static inline bool
>  xfs_sb_has_ro_compat_feature(
> @@ -546,6 +548,12 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
>  		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
>  }
>  
> +static inline bool xfs_sb_version_hasexttime(struct xfs_sb *sbp)
> +{
> +	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
> +		(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_EXTTIME);
> +}
> +
>  /*
>   * end of superblock version macros
>   */
> @@ -824,8 +832,8 @@ typedef struct xfs_agfl {
>  		   xfs_daddr_to_agno(mp, (d) + (len) - 1)))
>  
>  typedef struct xfs_timestamp {
> -	__be32		t_sec;		/* timestamp seconds */
> -	__be32		t_nsec;		/* timestamp nanoseconds */
> +	__be32	t_sec;		/* timestamp seconds */
> +	__be32	t_nsec_epoch;	/* timestamp nanoseconds | extra epoch */
>  } xfs_timestamp_t;
>  
>  /*
> diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
> index 28ab3c5255e1..aaf411da6263 100644
> --- a/fs/xfs/libxfs/xfs_inode_buf.c
> +++ b/fs/xfs/libxfs/xfs_inode_buf.c
> @@ -17,6 +17,7 @@
>  #include "xfs_trans.h"
>  #include "xfs_ialloc.h"
>  #include "xfs_dir2.h"
> +#include "xfs_timestamp.h"
>  
>  #include <linux/iversion.h>
>  
> @@ -204,6 +205,7 @@ xfs_inode_from_disk(
>  {
>  	struct xfs_icdinode	*to = &ip->i_d;
>  	struct inode		*inode = VFS_I(ip);
> +	struct xfs_sb		*sbp = &ip->i_mount->m_sb;
>  
>  
>  	/*
> @@ -233,12 +235,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);
> +	xfs_timestamp_di_decode(sbp, &inode->i_atime, &from->di_atime);
> +	xfs_timestamp_di_decode(sbp, &inode->i_mtime, &from->di_mtime);
> +	xfs_timestamp_di_decode(sbp, &inode->i_ctime, &from->di_ctime);
>  	inode->i_generation = be32_to_cpu(from->di_gen);
>  	inode->i_mode = be16_to_cpu(from->di_mode);
>  
> @@ -257,7 +256,8 @@ xfs_inode_from_disk(
>  		inode_set_iversion_queried(inode,
>  					   be64_to_cpu(from->di_changecount));
>  		to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
> -		to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec);
> +		to->di_crtime.t_nsec_epoch =
> +			be32_to_cpu(from->di_crtime.t_nsec_epoch);
>  		to->di_flags2 = be64_to_cpu(from->di_flags2);
>  		to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
>  	}
> @@ -271,6 +271,7 @@ xfs_inode_to_disk(
>  {
>  	struct xfs_icdinode	*from = &ip->i_d;
>  	struct inode		*inode = VFS_I(ip);
> +	struct xfs_sb		*sbp = &ip->i_mount->m_sb;
>  
>  	to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
>  	to->di_onlink = 0;
> @@ -283,12 +284,9 @@ xfs_inode_to_disk(
>  	to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
>  
>  	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);
> +	xfs_timestamp_di_encode(sbp, &inode->i_atime, &to->di_atime);
> +	xfs_timestamp_di_encode(sbp, &inode->i_mtime, &to->di_mtime);
> +	xfs_timestamp_di_encode(sbp, &inode->i_ctime, &to->di_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);
> @@ -307,7 +305,8 @@ xfs_inode_to_disk(
>  	if (from->di_version == 3) {
>  		to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
>  		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.t_nsec_epoch =
> +			cpu_to_be32(from->di_crtime.t_nsec_epoch);
>  		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);
> @@ -338,11 +337,11 @@ xfs_log_dinode_to_disk(
>  	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_atime.t_nsec_epoch = cpu_to_be32(from->di_atime.t_nsec_epoch);
>  	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_mtime.t_nsec_epoch = cpu_to_be32(from->di_mtime.t_nsec_epoch);
>  	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_ctime.t_nsec_epoch = cpu_to_be32(from->di_ctime.t_nsec_epoch);
>  
>  	to->di_size = cpu_to_be64(from->di_size);
>  	to->di_nblocks = cpu_to_be64(from->di_nblocks);
> @@ -359,7 +358,8 @@ 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.t_nsec_epoch =
> +			cpu_to_be32(from->di_crtime.t_nsec_epoch);
>  		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);
> diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
> index e5f97c69b320..08f9d119e0d5 100644
> --- a/fs/xfs/libxfs/xfs_log_format.h
> +++ b/fs/xfs/libxfs/xfs_log_format.h
> @@ -369,8 +369,8 @@ static inline int xfs_ilog_fdata(int w)
>   * information.
>   */
>  typedef struct xfs_ictimestamp {
> -	int32_t		t_sec;		/* timestamp seconds */
> -	int32_t		t_nsec;		/* timestamp nanoseconds */
> +	int32_t t_sec;		/* timestamp seconds */
> +	uint32_t t_nsec_epoch;	/* timestamp nanoseconds | extra epoch */
>  } xfs_ictimestamp_t;
>  
>  /*
> diff --git a/fs/xfs/libxfs/xfs_timestamp.h b/fs/xfs/libxfs/xfs_timestamp.h
> new file mode 100644
> index 000000000000..b514a9f40704
> --- /dev/null
> +++ b/fs/xfs/libxfs/xfs_timestamp.h
> @@ -0,0 +1,151 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2019 CTERA Networks.
> + * All Rights Reserved.
> + */
> +#ifndef __XFS_TIMESTAMP_H__
> +#define __XFS_TIMESTAMP_H__
> +
> +//#define XFS_TIMESTAMP_DEBUG
> +
> +#ifdef XFS_TIMESTAMP_DEBUG
> +#define XFS_TIMESTAMP_EXTENDED(sbp) 1
> +#else
> +#define XFS_TIMESTAMP_EXTENDED(sbp) xfs_sb_version_hasexttime(sbp)
> +#endif
> +
> +/*
> + * We use 2 unused msb of 32bit t_nsec to encode time ranges beyond y2038.
> + *
> + * We use an encoding that preserves the times for extra epoch "00":
> + *
> + * extra  msb of                         adjust for signed
> + * epoch  32-bit                         32-bit tv_sec to
> + * bits   time    decoded 64-bit tv_sec  64-bit tv_sec      valid time range
> + * 0 0    1    -0x80000000..-0x00000001  0x000000000 1901-12-13..1969-12-31
> + * 0 0    0    0x000000000..0x07fffffff  0x000000000 1970-01-01..2038-01-19
> + * 0 1    1    0x080000000..0x0ffffffff  0x100000000 2038-01-19..2106-02-07
> + * 0 1    0    0x100000000..0x17fffffff  0x100000000 2106-02-07..2174-02-25
> + * 1 0    1    0x180000000..0x1ffffffff  0x200000000 2174-02-25..2242-03-16
> + * 1 0    0    0x200000000..0x27fffffff  0x200000000 2242-03-16..2310-04-04
> + * 1 1    1    0x280000000..0x2ffffffff  0x300000000 2310-04-04..2378-04-22
> + * 1 1    0    0x300000000..0x37fffffff  0x300000000 2378-04-22..2446-05-10
> + */
> +
> +#define XFS_TIMESTAMP_NSEC_BITS		30
> +#define XFS_TIMESTAMP_NSEC_MASK		((1U << XFS_TIMESTAMP_NSEC_BITS) - 1)
> +#define XFS_TIMESTAMP_NSEC(nsec_epoch)	((nsec_epoch) & XFS_TIMESTAMP_NSEC_MASK)
> +#define XFS_TIMESTAMP_EPOCH_SHIFT	XFS_TIMESTAMP_NSEC_BITS
> +#define XFS_TIMESTAMP_EPOCH_BITS	(32 - XFS_TIMESTAMP_NSEC_BITS)
> +#define XFS_TIMESTAMP_EPOCH_MASK	(((1U << XFS_TIMESTAMP_EPOCH_BITS) \
> +					  - 1) << XFS_TIMESTAMP_EPOCH_SHIFT)
> +#define XFS_TIMESTAMP_SEC_BITS		(32 + XFS_TIMESTAMP_EPOCH_BITS)
> +
> +#define XFS_TIMESTAMP_SEC_MIN		S32_MIN
> +#define XFS_TIMESTAMP_SEC32_MAX		S32_MAX
> +#define XFS_TIMESTAMP_SEC64_MAX		((1LL << XFS_TIMESTAMP_SEC_BITS) \
> +					 - 1  + S32_MIN)
> +#define XFS_TIMESTAMP_SEC_MAX(sbp) \
> +	(XFS_TIMESTAMP_EXTENDED(sbp) ? XFS_TIMESTAMP_SEC64_MAX : \
> +					XFS_TIMESTAMP_SEC32_MAX)
> +
> +
> +static inline int64_t xfs_timestamp_decode_sec64(int32_t sec32,
> +						 uint32_t nsec_epoch)
> +{
> +	int64_t sec64 = sec32;
> +
> +	if (unlikely(nsec_epoch & XFS_TIMESTAMP_EPOCH_MASK)) {
> +		sec64 += ((int64_t)(nsec_epoch & XFS_TIMESTAMP_EPOCH_MASK)) <<
> +			XFS_TIMESTAMP_EPOCH_BITS;
> +#ifdef XFS_TIMESTAMP_DEBUG
> +		pr_info("%s: %lld.%d epoch=%x sec32=%d", __func__, sec64,
> +			XFS_TIMESTAMP_NSEC(nsec_epoch),
> +			(nsec_epoch & XFS_TIMESTAMP_EPOCH_MASK), sec32);
> +#endif
> +	}
> +	return sec64;
> +}
> +
> +static inline int64_t xfs_timestamp_sec64(struct xfs_sb *sbp, int32_t sec32,
> +					  uint32_t nsec_epoch)
> +{
> +	return XFS_TIMESTAMP_EXTENDED(sbp) ?
> +		xfs_timestamp_decode_sec64(sec32, nsec_epoch) : sec32;
> +}
> +
> +static inline bool xfs_timestamp_nsec_is_valid(struct xfs_sb *sbp,
> +					       uint32_t nsec_epoch)
> +{
> +	if (!XFS_TIMESTAMP_EXTENDED(sbp) &&
> +	    (nsec_epoch & XFS_TIMESTAMP_EPOCH_MASK))
> +		return false;
> +
> +	return XFS_TIMESTAMP_NSEC(nsec_epoch) < NSEC_PER_SEC;
> +}
> +
> +static inline bool xfs_timestamp_is_valid(struct xfs_sb *sbp,
> +					  xfs_timestamp_t *dtsp)
> +{
> +	return xfs_timestamp_nsec_is_valid(sbp,
> +				be32_to_cpu(dtsp->t_nsec_epoch));
> +}
> +
> +static inline void xfs_timestamp_ic_decode(struct xfs_sb *sbp,
> +					   struct timespec64 *time,
> +					   xfs_ictimestamp_t *itsp)
> +{
> +	time->tv_sec = xfs_timestamp_sec64(sbp, itsp->t_sec,
> +					   itsp->t_nsec_epoch);
> +	time->tv_nsec = XFS_TIMESTAMP_NSEC(itsp->t_nsec_epoch);
> +}
> +
> +static inline void xfs_timestamp_di_decode(struct xfs_sb *sbp,
> +					   struct timespec64 *time,
> +					   xfs_timestamp_t *dtsp)
> +{
> +	time->tv_sec = xfs_timestamp_sec64(sbp, be32_to_cpu(dtsp->t_sec),
> +					   be32_to_cpu(dtsp->t_nsec_epoch));
> +	time->tv_nsec = XFS_TIMESTAMP_NSEC(be32_to_cpu(dtsp->t_nsec_epoch));
> +}
> +
> +static inline int32_t xfs_timestamp_encode_nsec_epoch(int64_t sec64,
> +						      int32_t nsec)
> +{
> +	int32_t epoch = ((sec64 - (int32_t)sec64) >> XFS_TIMESTAMP_EPOCH_BITS) &
> +			XFS_TIMESTAMP_EPOCH_MASK;
> +
> +#ifdef XFS_TIMESTAMP_DEBUG
> +	if (epoch)
> +		pr_info("%s: %lld.%d epoch=%x sec32=%d", __func__, sec64, nsec,
> +			epoch, (int32_t)sec64);
> +#endif
> +	return (nsec & XFS_TIMESTAMP_NSEC_MASK) | epoch;
> +}
> +
> +static inline int32_t xfs_timestamp_nsec_epoch(struct xfs_sb *sbp,
> +					       int64_t sec64, int32_t nsec)
> +{
> +	return XFS_TIMESTAMP_EXTENDED(sbp) ?
> +		xfs_timestamp_encode_nsec_epoch(sec64, nsec) : nsec;
> +}
> +
> +static inline void xfs_timestamp_ic_encode(struct xfs_sb *sbp,
> +					   struct timespec64 *time,
> +					   xfs_ictimestamp_t *itsp)
> +{
> +	itsp->t_sec = (int32_t)time->tv_sec;
> +	itsp->t_nsec_epoch = xfs_timestamp_nsec_epoch(sbp, time->tv_sec,
> +						      time->tv_nsec);
> +}
> +
> +static inline void xfs_timestamp_di_encode(struct xfs_sb *sbp,
> +					   struct timespec64 *time,
> +					   xfs_timestamp_t *dtsp)
> +{
> +	dtsp->t_sec = cpu_to_be32(time->tv_sec);
> +	dtsp->t_nsec_epoch = cpu_to_be32(xfs_timestamp_nsec_epoch(sbp,
> +						time->tv_sec, time->tv_nsec));
> +}
> +
> +#endif /* __XFS_TIMESTAMP_H__ */
> diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c
> index a9ad90926b87..48c9c9e3654d 100644
> --- a/fs/xfs/libxfs/xfs_trans_inode.c
> +++ b/fs/xfs/libxfs/xfs_trans_inode.c
> @@ -8,10 +8,13 @@
>  #include "xfs_shared.h"
>  #include "xfs_format.h"
>  #include "xfs_log_format.h"
> +#include "xfs_trans_resv.h"
> +#include "xfs_mount.h"
>  #include "xfs_inode.h"
>  #include "xfs_trans.h"
>  #include "xfs_trans_priv.h"
>  #include "xfs_inode_item.h"
> +#include "xfs_timestamp.h"
>  
>  #include <linux/iversion.h>
>  
> @@ -67,8 +70,8 @@ xfs_trans_ichgtime(
>  	if (flags & XFS_ICHGTIME_CHG)
>  		inode->i_ctime = tv;
>  	if (flags & XFS_ICHGTIME_CREATE) {
> -		ip->i_d.di_crtime.t_sec = (int32_t)tv.tv_sec;
> -		ip->i_d.di_crtime.t_nsec = (int32_t)tv.tv_nsec;
> +		xfs_timestamp_ic_encode(&ip->i_mount->m_sb, &tv,
> +					&ip->i_d.di_crtime);
>  	}
>  }
>  
> diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
> index 6d483ab29e63..981f86387dc3 100644
> --- a/fs/xfs/scrub/inode.c
> +++ b/fs/xfs/scrub/inode.c
> @@ -17,6 +17,7 @@
>  #include "xfs_reflink.h"
>  #include "xfs_rmap.h"
>  #include "xfs_bmap_util.h"
> +#include "xfs_timestamp.h"
>  #include "scrub/scrub.h"
>  #include "scrub/common.h"
>  #include "scrub/btree.h"
> @@ -293,11 +294,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)
> +	if (!xfs_timestamp_is_valid(&mp->m_sb, &dip->di_atime) ||
> +	    !xfs_timestamp_is_valid(&mp->m_sb, &dip->di_mtime) ||
> +	    !xfs_timestamp_is_valid(&mp->m_sb, &dip->di_ctime))
>  		xchk_ino_set_corrupt(sc, ino);
>  
>  	/*
> @@ -403,7 +402,7 @@ xchk_dinode(
>  	}
>  
>  	if (dip->di_version >= 3) {
> -		if (be32_to_cpu(dip->di_crtime.t_nsec) >= NSEC_PER_SEC)
> +		if (!xfs_timestamp_is_valid(&mp->m_sb, &dip->di_crtime))
>  			xchk_ino_set_corrupt(sc, ino);
>  		xchk_inode_flags2(sc, dip, ino, mode, flags, flags2);
>  		xchk_inode_cowextsize(sc, dip, ino, mode, flags,
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index a92d4521748d..ca1538b31170 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -35,6 +35,7 @@
>  #include "xfs_log.h"
>  #include "xfs_bmap_btree.h"
>  #include "xfs_reflink.h"
> +#include "xfs_timestamp.h"
>  
>  kmem_zone_t *xfs_inode_zone;
>  
> @@ -851,8 +852,7 @@ xfs_ialloc(
>  		inode_set_iversion(inode, 1);
>  		ip->i_d.di_flags2 = 0;
>  		ip->i_d.di_cowextsize = 0;
> -		ip->i_d.di_crtime.t_sec = (int32_t)tv.tv_sec;
> -		ip->i_d.di_crtime.t_nsec = (int32_t)tv.tv_nsec;
> +		xfs_timestamp_ic_encode(&mp->m_sb, &tv, &ip->i_d.di_crtime);
>  	}
>  
>  
> diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
> index 726aa3bfd6e8..2b5db9af6a9d 100644
> --- a/fs/xfs/xfs_inode_item.c
> +++ b/fs/xfs/xfs_inode_item.c
> @@ -18,6 +18,7 @@
>  #include "xfs_buf_item.h"
>  #include "xfs_log.h"
>  #include "xfs_error.h"
> +#include "xfs_timestamp.h"
>  
>  #include <linux/iversion.h>
>  
> @@ -303,6 +304,7 @@ xfs_inode_to_log_dinode(
>  {
>  	struct xfs_icdinode	*from = &ip->i_d;
>  	struct inode		*inode = VFS_I(ip);
> +	struct xfs_sb		*sbp = &ip->i_mount->m_sb;
>  
>  	to->di_magic = XFS_DINODE_MAGIC;
>  
> @@ -315,12 +317,9 @@ xfs_inode_to_log_dinode(
>  
>  	memset(to->di_pad, 0, sizeof(to->di_pad));
>  	memset(to->di_pad3, 0, sizeof(to->di_pad3));
> -	to->di_atime.t_sec = inode->i_atime.tv_sec;
> -	to->di_atime.t_nsec = inode->i_atime.tv_nsec;
> -	to->di_mtime.t_sec = inode->i_mtime.tv_sec;
> -	to->di_mtime.t_nsec = inode->i_mtime.tv_nsec;
> -	to->di_ctime.t_sec = inode->i_ctime.tv_sec;
> -	to->di_ctime.t_nsec = inode->i_ctime.tv_nsec;
> +	xfs_timestamp_ic_encode(sbp, &inode->i_atime, &to->di_atime);
> +	xfs_timestamp_ic_encode(sbp, &inode->i_mtime, &to->di_mtime);
> +	xfs_timestamp_ic_encode(sbp, &inode->i_ctime, &to->di_ctime);
>  	to->di_nlink = inode->i_nlink;
>  	to->di_gen = inode->i_generation;
>  	to->di_mode = inode->i_mode;
> @@ -342,7 +341,7 @@ xfs_inode_to_log_dinode(
>  	if (from->di_version == 3) {
>  		to->di_changecount = inode_peek_iversion(inode);
>  		to->di_crtime.t_sec = from->di_crtime.t_sec;
> -		to->di_crtime.t_nsec = from->di_crtime.t_nsec;
> +		to->di_crtime.t_nsec_epoch = from->di_crtime.t_nsec_epoch;
>  		to->di_flags2 = from->di_flags2;
>  		to->di_cowextsize = from->di_cowextsize;
>  		to->di_ino = ip->i_ino;
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 4c7962ccb0c4..aa294597d16f 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -21,6 +21,7 @@
>  #include "xfs_dir2.h"
>  #include "xfs_iomap.h"
>  #include "xfs_error.h"
> +#include "xfs_timestamp.h"
>  
>  #include <linux/xattr.h>
>  #include <linux/posix_acl.h>
> @@ -556,8 +557,8 @@ xfs_vn_getattr(
>  	if (ip->i_d.di_version == 3) {
>  		if (request_mask & STATX_BTIME) {
>  			stat->result_mask |= STATX_BTIME;
> -			stat->btime.tv_sec = ip->i_d.di_crtime.t_sec;
> -			stat->btime.tv_nsec = ip->i_d.di_crtime.t_nsec;
> +			xfs_timestamp_ic_decode(&mp->m_sb, &stat->btime,
> +						&ip->i_d.di_crtime);
>  		}
>  	}
>  
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 884950adbd16..3e55cf029414 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -19,6 +19,7 @@
>  #include "xfs_error.h"
>  #include "xfs_icache.h"
>  #include "xfs_health.h"
> +#include "xfs_timestamp.h"
>  
>  /*
>   * Bulk Stat
> @@ -98,7 +99,7 @@ xfs_bulkstat_one_int(
>  	buf->bs_ctime = inode->i_ctime.tv_sec;
>  	buf->bs_ctime_nsec = inode->i_ctime.tv_nsec;
>  	buf->bs_btime = dic->di_crtime.t_sec;
> -	buf->bs_btime_nsec = dic->di_crtime.t_nsec;
> +	buf->bs_btime_nsec = XFS_TIMESTAMP_NSEC(dic->di_crtime.t_nsec_epoch);
>  	buf->bs_gen = inode->i_generation;
>  	buf->bs_mode = inode->i_mode;
>  
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index b3188ea49413..b940ce6dac07 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -35,6 +35,7 @@
>  #include "xfs_refcount_item.h"
>  #include "xfs_bmap_item.h"
>  #include "xfs_reflink.h"
> +#include "xfs_timestamp.h"
>  
>  #include <linux/magic.h>
>  #include <linux/fs_context.h>
> @@ -1438,8 +1439,8 @@ xfs_fc_fill_super(
>  	sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits);
>  	sb->s_max_links = XFS_MAXLINK;
>  	sb->s_time_gran = 1;
> -	sb->s_time_min = S32_MIN;
> -	sb->s_time_max = S32_MAX;
> +	sb->s_time_min = XFS_TIMESTAMP_SEC_MIN;
> +	sb->s_time_max = XFS_TIMESTAMP_SEC_MAX(&mp->m_sb);
>  	sb->s_iflags |= SB_I_CGROUPWB;
>  
>  	set_posix_acl_flag(sb);
> -- 
> 2.17.1
> 

  reply	other threads:[~2019-11-11 22:35 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-11 21:36 [RFC][PATCH] xfs: extended timestamp range Amir Goldstein
2019-11-11 22:35 ` Darrick J. Wong [this message]
2019-11-12  4:00   ` Amir Goldstein
2019-11-12 21:11     ` Dave Chinner
2019-11-13  3:56       ` Darrick J. Wong
2019-11-13  4:08         ` Dave Chinner
2019-11-13  4:42         ` Amir Goldstein
2019-11-13  4:58           ` Darrick J. Wong
2019-11-13  5:17             ` Amir Goldstein
2019-11-13  5:20               ` Darrick J. Wong
2019-11-18  4:52                 ` Amir Goldstein
2019-11-18  8:22                   ` Dave Chinner
2019-11-18  9:30                     ` Amir Goldstein
2019-11-19  5:34                       ` Darrick J. Wong
2019-11-19 13:37                         ` Arnd Bergmann
2019-11-13 13:20             ` Arnd Bergmann
2019-11-13 20:40               ` Dave Chinner
2019-11-12  8:25   ` Christoph Hellwig
2019-11-12 16:09     ` Darrick J. Wong
2019-11-12 16:12       ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191111223508.GS6219@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=amir73il@gmail.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).