Message ID | 159847955663.2601708.15732334977032233773.stgit@magnolia (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xfs: widen timestamps to deal with y2038 | expand |
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > index 972c740aaf7b..9cf84b57e2ce 100644 > --- a/fs/xfs/libxfs/xfs_format.h > +++ b/fs/xfs/libxfs/xfs_format.h > @@ -1257,13 +1257,15 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) > #define XFS_DQTYPE_USER 0x01 /* user dquot record */ > #define XFS_DQTYPE_PROJ 0x02 /* project dquot record */ > #define XFS_DQTYPE_GROUP 0x04 /* group dquot record */ > +#define XFS_DQTYPE_BIGTIME 0x08 /* large expiry timestamps */ Maybe make this the high bit in the field to keep space for adding more actual quota types if we need them? Otherwise looks good: Reviewed-by: Christoph Hellwig <hch@lst.de>
On Thu, Aug 27, 2020 at 08:00:50AM +0100, Christoph Hellwig wrote: > > diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > > index 972c740aaf7b..9cf84b57e2ce 100644 > > --- a/fs/xfs/libxfs/xfs_format.h > > +++ b/fs/xfs/libxfs/xfs_format.h > > @@ -1257,13 +1257,15 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) > > #define XFS_DQTYPE_USER 0x01 /* user dquot record */ > > #define XFS_DQTYPE_PROJ 0x02 /* project dquot record */ > > #define XFS_DQTYPE_GROUP 0x04 /* group dquot record */ > > +#define XFS_DQTYPE_BIGTIME 0x08 /* large expiry timestamps */ > > Maybe make this the high bit in the field to keep space for adding more > actual quota types if we need them? Ok. 0x80 it is. --D > Otherwise looks good: > > Reviewed-by: Christoph Hellwig <hch@lst.de>
On 8/26/20 3:05 PM, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@oracle.com> > > Enable the bigtime feature for quota timers. We decrease the accuracy > of the timers to ~4s in exchange for being able to set timers up to the > bigtime maximum. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> ok, looks ok to me Reviewed-by: Allison Collins <allison.henderson@oracle.com> > --- > fs/xfs/libxfs/xfs_dquot_buf.c | 21 +++++++++++++++-- > fs/xfs/libxfs/xfs_format.h | 50 +++++++++++++++++++++++++++++++++++++++- > fs/xfs/libxfs/xfs_quota_defs.h | 3 ++ > fs/xfs/xfs_dquot.c | 10 ++++++++ > fs/xfs/xfs_ondisk.h | 5 ++++ > fs/xfs/xfs_qm.c | 13 +++++++++- > fs/xfs/xfs_trans_dquot.c | 6 +++++ > 7 files changed, 102 insertions(+), 6 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c > index cf85bad8a894..6766417d5ba4 100644 > --- a/fs/xfs/libxfs/xfs_dquot_buf.c > +++ b/fs/xfs/libxfs/xfs_dquot_buf.c > @@ -69,6 +69,13 @@ xfs_dquot_verify( > ddq_type != XFS_DQTYPE_GROUP) > return __this_address; > > + if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && > + !xfs_sb_version_hasbigtime(&mp->m_sb)) > + return __this_address; > + > + if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id) > + return __this_address; > + > if (id != -1 && id != be32_to_cpu(ddq->d_id)) > return __this_address; > > @@ -295,7 +302,12 @@ xfs_dquot_from_disk_ts( > struct xfs_disk_dquot *ddq, > __be32 dtimer) > { > - return be32_to_cpu(dtimer); > + uint32_t t = be32_to_cpu(dtimer); > + > + if (t != 0 && (ddq->d_type & XFS_DQTYPE_BIGTIME)) > + return xfs_dq_bigtime_to_unix(t); > + > + return t; > } > > /* Convert an incore timer value into an on-disk timer value. */ > @@ -304,5 +316,10 @@ xfs_dquot_to_disk_ts( > struct xfs_dquot *dqp, > time64_t timer) > { > - return cpu_to_be32(timer); > + uint32_t t = timer; > + > + if (timer != 0 && (dqp->q_type & XFS_DQTYPE_BIGTIME)) > + t = xfs_dq_unix_to_bigtime(timer); > + > + return cpu_to_be32(t); > } > diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > index 972c740aaf7b..9cf84b57e2ce 100644 > --- a/fs/xfs/libxfs/xfs_format.h > +++ b/fs/xfs/libxfs/xfs_format.h > @@ -1257,13 +1257,15 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) > #define XFS_DQTYPE_USER 0x01 /* user dquot record */ > #define XFS_DQTYPE_PROJ 0x02 /* project dquot record */ > #define XFS_DQTYPE_GROUP 0x04 /* group dquot record */ > +#define XFS_DQTYPE_BIGTIME 0x08 /* large expiry timestamps */ > > /* bitmask to determine if this is a user/group/project dquot */ > #define XFS_DQTYPE_REC_MASK (XFS_DQTYPE_USER | \ > XFS_DQTYPE_PROJ | \ > XFS_DQTYPE_GROUP) > > -#define XFS_DQTYPE_ANY (XFS_DQTYPE_REC_MASK) > +#define XFS_DQTYPE_ANY (XFS_DQTYPE_REC_MASK | \ > + XFS_DQTYPE_BIGTIME) > > /* > * XFS Quota Timers > @@ -1276,6 +1278,10 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) > * ondisk min and max defined here can be used directly to constrain the incore > * quota expiration timestamps on a Unix system. > * > + * When bigtime is enabled, we trade two bits of precision to expand the > + * expiration timeout range to match that of big inode timestamps. The min and > + * max recorded here are the on-disk limits, not a Unix timestamp. > + * > * The grace period for each quota type is stored in the root dquot (id = 0) > * and is applied to a non-root dquot when it exceeds the soft or hard limits. > * The length of quota grace periods are unsigned 32-bit quantities measured in > @@ -1294,6 +1300,48 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) > */ > #define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX) > > +/* > + * Smallest possible ondisk quota expiration value with bigtime timestamps. > + * This corresponds (after conversion to a Unix timestamp) with the incore > + * expiration of Jan 1 00:00:04 UTC 1970. > + */ > +#define XFS_DQ_BIGTIME_EXPIRY_MIN (XFS_DQ_LEGACY_EXPIRY_MIN) > + > +/* > + * Largest supported ondisk quota expiration value with bigtime timestamps. > + * This corresponds (after conversion to a Unix timestamp) with an incore > + * expiration of Jul 2 20:20:24 UTC 2486. > + * > + * The ondisk field supports values up to -1U, which corresponds to an incore > + * expiration in 2514. This is beyond the maximum the bigtime inode timestamp, > + * so we cap the maximum bigtime quota expiration to the max inode timestamp. > + */ > +#define XFS_DQ_BIGTIME_EXPIRY_MAX ((int64_t)4074815106U) > + > +/* > + * The following conversion factors assist in converting a quota expiration > + * timestamp between the incore and ondisk formats. > + */ > +#define XFS_DQ_BIGTIME_SHIFT (2) > +#define XFS_DQ_BIGTIME_SLACK ((int64_t)(1ULL << XFS_DQ_BIGTIME_SHIFT) - 1) > + > +/* Convert an incore quota expiration timestamp to an ondisk bigtime value. */ > +static inline uint32_t xfs_dq_unix_to_bigtime(time64_t unix_seconds) > +{ > + /* > + * Round the expiration timestamp up to the nearest bigtime timestamp > + * that we can store, to give users the most time to fix problems. > + */ > + return ((uint64_t)unix_seconds + XFS_DQ_BIGTIME_SLACK) >> > + XFS_DQ_BIGTIME_SHIFT; > +} > + > +/* Convert an ondisk bigtime quota expiration value to an incore timestamp. */ > +static inline time64_t xfs_dq_bigtime_to_unix(uint32_t ondisk_seconds) > +{ > + return (time64_t)ondisk_seconds << XFS_DQ_BIGTIME_SHIFT; > +} > + > /* > * Default quota grace periods, ranging from zero (use the compiled defaults) > * to ~136 years. These are applied to a non-root dquot that has exceeded > diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h > index 9a99910d857e..0f0af4e35032 100644 > --- a/fs/xfs/libxfs/xfs_quota_defs.h > +++ b/fs/xfs/libxfs/xfs_quota_defs.h > @@ -23,7 +23,8 @@ typedef uint8_t xfs_dqtype_t; > #define XFS_DQTYPE_STRINGS \ > { XFS_DQTYPE_USER, "USER" }, \ > { XFS_DQTYPE_PROJ, "PROJ" }, \ > - { XFS_DQTYPE_GROUP, "GROUP" } > + { XFS_DQTYPE_GROUP, "GROUP" }, \ > + { XFS_DQTYPE_BIGTIME, "BIGTIME" } > > /* > * flags for q_flags field in the dquot. > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c > index 59c03e973741..3f9e11c3df1e 100644 > --- a/fs/xfs/xfs_dquot.c > +++ b/fs/xfs/xfs_dquot.c > @@ -223,6 +223,8 @@ xfs_qm_init_dquot_blk( > d->dd_diskdq.d_version = XFS_DQUOT_VERSION; > d->dd_diskdq.d_id = cpu_to_be32(curid); > d->dd_diskdq.d_type = type; > + if (curid > 0 && xfs_sb_version_hasbigtime(&mp->m_sb)) > + d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME; > if (xfs_sb_version_hascrc(&mp->m_sb)) { > uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); > xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), > @@ -1167,6 +1169,14 @@ xfs_qm_dqflush_check( > !dqp->q_rtb.timer) > return __this_address; > > + /* bigtime flag should never be set on root dquots */ > + if (dqp->q_type & XFS_DQTYPE_BIGTIME) { > + if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb)) > + return __this_address; > + if (dqp->q_id == 0) > + return __this_address; > + } > + > return NULL; > } > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h > index 52db8743def1..a13686ce0626 100644 > --- a/fs/xfs/xfs_ondisk.h > +++ b/fs/xfs/xfs_ondisk.h > @@ -165,6 +165,11 @@ xfs_check_ondisk_structs(void) > XFS_LEGACY_TIME_MIN); > XFS_CHECK_VALUE(XFS_BIGTIME_TIME_MAX - XFS_BIGTIME_EPOCH_OFFSET, > 16299260424LL); > + > + /* Do the same with the incore quota expiration range. */ > + XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MIN << XFS_DQ_BIGTIME_SHIFT, 4); > + XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MAX << XFS_DQ_BIGTIME_SHIFT, > + 16299260424LL); > } > > #endif /* __XFS_ONDISK_H */ > diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c > index b83a12ecfc35..259588a4227d 100644 > --- a/fs/xfs/xfs_qm.c > +++ b/fs/xfs/xfs_qm.c > @@ -661,8 +661,15 @@ xfs_qm_init_quotainfo( > /* Precalc some constants */ > qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); > qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen); > - qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN; > - qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX; > + if (xfs_sb_version_hasbigtime(&mp->m_sb)) { > + qinf->qi_expiry_min = > + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN); > + qinf->qi_expiry_max = > + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX); > + } else { > + qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN; > + qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX; > + } > > mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); > > @@ -881,6 +888,8 @@ xfs_qm_reset_dqcounts( > ddq->d_bwarns = 0; > ddq->d_iwarns = 0; > ddq->d_rtbwarns = 0; > + if (xfs_sb_version_hasbigtime(&mp->m_sb)) > + ddq->d_type |= XFS_DQTYPE_BIGTIME; > } > > if (xfs_sb_version_hascrc(&mp->m_sb)) { > diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c > index c6ba7ef18e06..133fc6fc3edd 100644 > --- a/fs/xfs/xfs_trans_dquot.c > +++ b/fs/xfs/xfs_trans_dquot.c > @@ -55,6 +55,12 @@ xfs_trans_log_dquot( > { > ASSERT(XFS_DQ_IS_LOCKED(dqp)); > > + /* Upgrade the dquot to bigtime format if possible. */ > + if (dqp->q_id != 0 && > + xfs_sb_version_hasbigtime(&tp->t_mountp->m_sb) && > + !(dqp->q_type & XFS_DQTYPE_BIGTIME)) > + dqp->q_type |= XFS_DQTYPE_BIGTIME; > + > tp->t_flags |= XFS_TRANS_DIRTY; > set_bit(XFS_LI_DIRTY, &dqp->q_logitem.qli_item.li_flags); > } >
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c index cf85bad8a894..6766417d5ba4 100644 --- a/fs/xfs/libxfs/xfs_dquot_buf.c +++ b/fs/xfs/libxfs/xfs_dquot_buf.c @@ -69,6 +69,13 @@ xfs_dquot_verify( ddq_type != XFS_DQTYPE_GROUP) return __this_address; + if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && + !xfs_sb_version_hasbigtime(&mp->m_sb)) + return __this_address; + + if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id) + return __this_address; + if (id != -1 && id != be32_to_cpu(ddq->d_id)) return __this_address; @@ -295,7 +302,12 @@ xfs_dquot_from_disk_ts( struct xfs_disk_dquot *ddq, __be32 dtimer) { - return be32_to_cpu(dtimer); + uint32_t t = be32_to_cpu(dtimer); + + if (t != 0 && (ddq->d_type & XFS_DQTYPE_BIGTIME)) + return xfs_dq_bigtime_to_unix(t); + + return t; } /* Convert an incore timer value into an on-disk timer value. */ @@ -304,5 +316,10 @@ xfs_dquot_to_disk_ts( struct xfs_dquot *dqp, time64_t timer) { - return cpu_to_be32(timer); + uint32_t t = timer; + + if (timer != 0 && (dqp->q_type & XFS_DQTYPE_BIGTIME)) + t = xfs_dq_unix_to_bigtime(timer); + + return cpu_to_be32(t); } diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 972c740aaf7b..9cf84b57e2ce 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1257,13 +1257,15 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) #define XFS_DQTYPE_USER 0x01 /* user dquot record */ #define XFS_DQTYPE_PROJ 0x02 /* project dquot record */ #define XFS_DQTYPE_GROUP 0x04 /* group dquot record */ +#define XFS_DQTYPE_BIGTIME 0x08 /* large expiry timestamps */ /* bitmask to determine if this is a user/group/project dquot */ #define XFS_DQTYPE_REC_MASK (XFS_DQTYPE_USER | \ XFS_DQTYPE_PROJ | \ XFS_DQTYPE_GROUP) -#define XFS_DQTYPE_ANY (XFS_DQTYPE_REC_MASK) +#define XFS_DQTYPE_ANY (XFS_DQTYPE_REC_MASK | \ + XFS_DQTYPE_BIGTIME) /* * XFS Quota Timers @@ -1276,6 +1278,10 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) * ondisk min and max defined here can be used directly to constrain the incore * quota expiration timestamps on a Unix system. * + * When bigtime is enabled, we trade two bits of precision to expand the + * expiration timeout range to match that of big inode timestamps. The min and + * max recorded here are the on-disk limits, not a Unix timestamp. + * * The grace period for each quota type is stored in the root dquot (id = 0) * and is applied to a non-root dquot when it exceeds the soft or hard limits. * The length of quota grace periods are unsigned 32-bit quantities measured in @@ -1294,6 +1300,48 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) */ #define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX) +/* + * Smallest possible ondisk quota expiration value with bigtime timestamps. + * This corresponds (after conversion to a Unix timestamp) with the incore + * expiration of Jan 1 00:00:04 UTC 1970. + */ +#define XFS_DQ_BIGTIME_EXPIRY_MIN (XFS_DQ_LEGACY_EXPIRY_MIN) + +/* + * Largest supported ondisk quota expiration value with bigtime timestamps. + * This corresponds (after conversion to a Unix timestamp) with an incore + * expiration of Jul 2 20:20:24 UTC 2486. + * + * The ondisk field supports values up to -1U, which corresponds to an incore + * expiration in 2514. This is beyond the maximum the bigtime inode timestamp, + * so we cap the maximum bigtime quota expiration to the max inode timestamp. + */ +#define XFS_DQ_BIGTIME_EXPIRY_MAX ((int64_t)4074815106U) + +/* + * The following conversion factors assist in converting a quota expiration + * timestamp between the incore and ondisk formats. + */ +#define XFS_DQ_BIGTIME_SHIFT (2) +#define XFS_DQ_BIGTIME_SLACK ((int64_t)(1ULL << XFS_DQ_BIGTIME_SHIFT) - 1) + +/* Convert an incore quota expiration timestamp to an ondisk bigtime value. */ +static inline uint32_t xfs_dq_unix_to_bigtime(time64_t unix_seconds) +{ + /* + * Round the expiration timestamp up to the nearest bigtime timestamp + * that we can store, to give users the most time to fix problems. + */ + return ((uint64_t)unix_seconds + XFS_DQ_BIGTIME_SLACK) >> + XFS_DQ_BIGTIME_SHIFT; +} + +/* Convert an ondisk bigtime quota expiration value to an incore timestamp. */ +static inline time64_t xfs_dq_bigtime_to_unix(uint32_t ondisk_seconds) +{ + return (time64_t)ondisk_seconds << XFS_DQ_BIGTIME_SHIFT; +} + /* * Default quota grace periods, ranging from zero (use the compiled defaults) * to ~136 years. These are applied to a non-root dquot that has exceeded diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h index 9a99910d857e..0f0af4e35032 100644 --- a/fs/xfs/libxfs/xfs_quota_defs.h +++ b/fs/xfs/libxfs/xfs_quota_defs.h @@ -23,7 +23,8 @@ typedef uint8_t xfs_dqtype_t; #define XFS_DQTYPE_STRINGS \ { XFS_DQTYPE_USER, "USER" }, \ { XFS_DQTYPE_PROJ, "PROJ" }, \ - { XFS_DQTYPE_GROUP, "GROUP" } + { XFS_DQTYPE_GROUP, "GROUP" }, \ + { XFS_DQTYPE_BIGTIME, "BIGTIME" } /* * flags for q_flags field in the dquot. diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 59c03e973741..3f9e11c3df1e 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -223,6 +223,8 @@ xfs_qm_init_dquot_blk( d->dd_diskdq.d_version = XFS_DQUOT_VERSION; d->dd_diskdq.d_id = cpu_to_be32(curid); d->dd_diskdq.d_type = type; + if (curid > 0 && xfs_sb_version_hasbigtime(&mp->m_sb)) + d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME; if (xfs_sb_version_hascrc(&mp->m_sb)) { uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), @@ -1167,6 +1169,14 @@ xfs_qm_dqflush_check( !dqp->q_rtb.timer) return __this_address; + /* bigtime flag should never be set on root dquots */ + if (dqp->q_type & XFS_DQTYPE_BIGTIME) { + if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb)) + return __this_address; + if (dqp->q_id == 0) + return __this_address; + } + return NULL; } diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 52db8743def1..a13686ce0626 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -165,6 +165,11 @@ xfs_check_ondisk_structs(void) XFS_LEGACY_TIME_MIN); XFS_CHECK_VALUE(XFS_BIGTIME_TIME_MAX - XFS_BIGTIME_EPOCH_OFFSET, 16299260424LL); + + /* Do the same with the incore quota expiration range. */ + XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MIN << XFS_DQ_BIGTIME_SHIFT, 4); + XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MAX << XFS_DQ_BIGTIME_SHIFT, + 16299260424LL); } #endif /* __XFS_ONDISK_H */ diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index b83a12ecfc35..259588a4227d 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -661,8 +661,15 @@ xfs_qm_init_quotainfo( /* Precalc some constants */ qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(qinf->qi_dqchunklen); - qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN; - qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX; + if (xfs_sb_version_hasbigtime(&mp->m_sb)) { + qinf->qi_expiry_min = + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN); + qinf->qi_expiry_max = + xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX); + } else { + qinf->qi_expiry_min = XFS_DQ_LEGACY_EXPIRY_MIN; + qinf->qi_expiry_max = XFS_DQ_LEGACY_EXPIRY_MAX; + } mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); @@ -881,6 +888,8 @@ xfs_qm_reset_dqcounts( ddq->d_bwarns = 0; ddq->d_iwarns = 0; ddq->d_rtbwarns = 0; + if (xfs_sb_version_hasbigtime(&mp->m_sb)) + ddq->d_type |= XFS_DQTYPE_BIGTIME; } if (xfs_sb_version_hascrc(&mp->m_sb)) { diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index c6ba7ef18e06..133fc6fc3edd 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -55,6 +55,12 @@ xfs_trans_log_dquot( { ASSERT(XFS_DQ_IS_LOCKED(dqp)); + /* Upgrade the dquot to bigtime format if possible. */ + if (dqp->q_id != 0 && + xfs_sb_version_hasbigtime(&tp->t_mountp->m_sb) && + !(dqp->q_type & XFS_DQTYPE_BIGTIME)) + dqp->q_type |= XFS_DQTYPE_BIGTIME; + tp->t_flags |= XFS_TRANS_DIRTY; set_bit(XFS_LI_DIRTY, &dqp->q_logitem.qli_item.li_flags); }