From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> 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@xxxxxxxxxx> --- include/xfs_mount.h | 5 +++++ libxfs/xfs_dquot_buf.c | 40 ++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_format.h | 26 +++++++++++++++++++++++++- libxfs/xfs_quota_defs.h | 3 ++- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 20c8bfaf4fa8..be74a922b7a1 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -184,4 +184,9 @@ extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *, int libxfs_umount(struct xfs_mount *mp); extern void libxfs_rtmount_destroy (xfs_mount_t *); +/* Dummy xfs_dquot so that libxfs compiles. */ +struct xfs_dquot { + int q_type; +}; + #endif /* __XFS_MOUNT_H__ */ diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c index 847b9ba5280c..e5938ef649f0 100644 --- a/libxfs/xfs_dquot_buf.c +++ b/libxfs/xfs_dquot_buf.c @@ -67,6 +67,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; @@ -294,6 +301,20 @@ xfs_dquot_from_disk_timestamp( time64_t *timer, __be32 dtimer) { + /* Zero always means zero, regardless of encoding. */ + if (!dtimer) { + *timer = 0; + return; + } + + if (ddq->d_type & XFS_DQTYPE_BIGTIME) { + uint64_t t; + + t = be32_to_cpu(dtimer); + *timer = t << XFS_DQ_BIGTIME_SHIFT; + return; + } + *timer = be32_to_cpu(dtimer); } @@ -304,5 +325,24 @@ xfs_dquot_to_disk_timestamp( __be32 *dtimer, time64_t timer) { + /* Zero always means zero, regardless of encoding. */ + if (!timer) { + *dtimer = cpu_to_be32(0); + return; + } + + if (dqp->q_type & XFS_DQTYPE_BIGTIME) { + uint64_t t = timer; + + /* + * Round the end of the grace period up to the nearest bigtime + * interval that we support, to give users the most time to fix + * the problems. + */ + t = roundup_64(t, 1U << XFS_DQ_BIGTIME_SHIFT); + *dtimer = cpu_to_be32(t >> XFS_DQ_BIGTIME_SHIFT); + return; + } + *dtimer = cpu_to_be32(timer); } diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 67303e517260..87c86a6dfb91 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1228,13 +1228,15 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #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 @@ -1271,6 +1273,28 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DQ_GRACE_MIN ((int64_t)0) #define XFS_DQ_GRACE_MAX ((int64_t)U32_MAX) +/* + * When bigtime is enabled, we trade a few bits of precision to expand the + * expiration timeout range to match that of big inode timestamps. The grace + * periods stored in dquot 0 are not shifted, since they record an interval, + * not a timestamp. + */ +#define XFS_DQ_BIGTIME_SHIFT (2) + +/* + * Smallest possible quota expiration with big timestamps, which is + * Jan 1 00:00:01 UTC 1970. + */ +#define XFS_DQ_BIGTIMEOUT_MIN (XFS_DQ_TIMEOUT_MIN) + +/* + * Largest supported quota expiration with traditional timestamps, which is + * the largest bigtime inode timestamp, or Jul 2 20:20:25 UTC 2486. The field + * is large enough that it's possible to fit expirations up to 2514, but we + * want to keep the maximum timestamp in sync. + */ +#define XFS_DQ_BIGTIMEOUT_MAX (XFS_INO_BIGTIME_MAX) + /* * This is the main portion of the on-disk representation of quota information * for a user. We pad this with some more expansion room to construct the on diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h index b524059faab5..b9a47eae684b 100644 --- a/libxfs/xfs_quota_defs.h +++ b/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.