All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 12/14] xfs: cache quota grace period expiration times incore
Date: Tue, 31 Dec 2019 17:12:18 -0800	[thread overview]
Message-ID: <157784113869.1364230.10740359430858443674.stgit@magnolia> (raw)
In-Reply-To: <157784106066.1364230.569420432829402226.stgit@magnolia>

From: Darrick J. Wong <darrick.wong@oracle.com>

Create an in-core timestamp that will tell us when a quota's grace
period expires.  In the subsequent bigtime patchset we will sacrifice
precision in the on-disk grace period timestamp to enable larger
timestamps across the filesystem, but we'll maintain an incore copy so
that we can maintain precision so long as the filesystem isn't
unmounted.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_dquot_buf.c  |   17 +++++++++++++++++
 fs/xfs/libxfs/xfs_quota_defs.h |    2 ++
 fs/xfs/xfs_dquot.c             |   40 +++++++++++++++++++++++++++-------------
 fs/xfs/xfs_dquot.h             |    8 ++++++++
 fs/xfs/xfs_qm.c                |   38 ++++++++++++++++++++++++++------------
 fs/xfs/xfs_qm_syscalls.c       |   26 +++++++++++++++-----------
 fs/xfs/xfs_trans_dquot.c       |    8 ++++----
 7 files changed, 99 insertions(+), 40 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index bedc1e752b60..72e0fcfef580 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -287,3 +287,20 @@ const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
 	.verify_read = xfs_dquot_buf_readahead_verify,
 	.verify_write = xfs_dquot_buf_write_verify,
 };
+
+void
+xfs_dquot_from_disk_timestamp(
+	struct timespec64	*tv,
+	__be32			dtimer)
+{
+	tv->tv_nsec = 0;
+	tv->tv_sec = be32_to_cpu(dtimer);
+}
+
+void
+xfs_dquot_to_disk_timestamp(
+	__be32			*dtimer,
+	const struct timespec64	*tv)
+{
+	*dtimer = cpu_to_be32(tv->tv_sec);
+}
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index b2113b17e53c..c453611ade3b 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -144,5 +144,7 @@ extern xfs_failaddr_t xfs_dqblk_verify(struct xfs_mount *mp,
 extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
 extern void xfs_dqblk_repair(struct xfs_mount *mp, struct xfs_dqblk *dqb,
 		xfs_dqid_t id, uint type);
+void xfs_dquot_from_disk_timestamp(struct timespec64 *tv, __be32 dtimer);
+void xfs_dquot_to_disk_timestamp(__be32 *dtimer, const struct timespec64 *tv);
 
 #endif	/* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 44bae5f16b55..763e974f7aad 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -126,21 +126,27 @@ xfs_dquot_clamp_timer(
 /* Set a quota grace period expiration timer. */
 static inline void
 xfs_quota_set_timer(
+	time64_t		*itimer,
 	__be32			*dtimer,
 	time_t			limit)
 {
-	time64_t		new_timeout;
+	struct timespec64	tv = { 0 };
 
-	new_timeout = xfs_dquot_clamp_timer(get_seconds() + limit);
-	*dtimer = cpu_to_be32(new_timeout);
+	tv.tv_sec = xfs_dquot_clamp_timer(ktime_get_real_seconds() + limit);
+	*itimer = tv.tv_sec;
+	xfs_dquot_to_disk_timestamp(dtimer, &tv);
 }
 
 /* Clear a quota grace period expiration timer. */
 static inline void
 xfs_quota_clear_timer(
+	time64_t		*itimer,
 	__be32			*dtimer)
 {
-	*dtimer = cpu_to_be32(0);
+	struct timespec64	tv = { 0 };
+
+	*itimer = tv.tv_sec;
+	xfs_dquot_to_disk_timestamp(dtimer, &tv);
 }
 
 /*
@@ -180,46 +186,46 @@ xfs_qm_adjust_dqtimers(
 
 	over = xfs_quota_exceeded(&d->d_bcount, dqp->q_ina_bcount,
 			&d->d_blk_softlimit, &d->d_blk_hardlimit);
-	if (!d->d_btimer) {
+	if (!dqp->q_btimer) {
 		if (over) {
-			xfs_quota_set_timer(&d->d_btimer,
+			xfs_quota_set_timer(&dqp->q_btimer, &d->d_btimer,
 					mp->m_quotainfo->qi_btimelimit);
 		} else {
 			d->d_bwarns = 0;
 		}
 	} else {
 		if (!over) {
-			xfs_quota_clear_timer(&d->d_btimer);
+			xfs_quota_clear_timer(&dqp->q_btimer, &d->d_btimer);
 		}
 	}
 
 	over = xfs_quota_exceeded(&d->d_icount, dqp->q_ina_icount,
 			&d->d_ino_softlimit, &d->d_ino_hardlimit);
-	if (!d->d_itimer) {
+	if (!dqp->q_itimer) {
 		if (over) {
-			xfs_quota_set_timer(&d->d_itimer,
+			xfs_quota_set_timer(&dqp->q_itimer, &d->d_itimer,
 					mp->m_quotainfo->qi_itimelimit);
 		} else {
 			d->d_iwarns = 0;
 		}
 	} else {
 		if (!over) {
-			xfs_quota_clear_timer(&d->d_itimer);
+			xfs_quota_clear_timer(&dqp->q_itimer, &d->d_itimer);
 		}
 	}
 
 	over = xfs_quota_exceeded(&d->d_rtbcount, dqp->q_ina_rtbcount,
 			&d->d_rtb_softlimit, &d->d_rtb_hardlimit);
-	if (!d->d_rtbtimer) {
+	if (!dqp->q_rtbtimer) {
 		if (over) {
-			xfs_quota_set_timer(&d->d_rtbtimer,
+			xfs_quota_set_timer(&dqp->q_rtbtimer, &d->d_rtbtimer,
 					mp->m_quotainfo->qi_rtbtimelimit);
 		} else {
 			d->d_rtbwarns = 0;
 		}
 	} else {
 		if (!over) {
-			xfs_quota_clear_timer(&d->d_rtbtimer);
+			xfs_quota_clear_timer(&dqp->q_rtbtimer, &d->d_rtbtimer);
 		}
 	}
 }
@@ -520,6 +526,7 @@ xfs_dquot_from_disk(
 	struct xfs_dquot	*dqp,
 	struct xfs_buf		*bp)
 {
+	struct timespec64	tv;
 	struct xfs_disk_dquot	*ddqp = bp->b_addr + dqp->q_bufoffset;
 
 	/* copy everything from disk dquot to the incore dquot */
@@ -533,6 +540,13 @@ xfs_dquot_from_disk(
 	dqp->q_res_icount = be64_to_cpu(ddqp->d_icount);
 	dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
 
+	xfs_dquot_from_disk_timestamp(&tv, ddqp->d_btimer);
+	dqp->q_btimer = tv.tv_sec;
+	xfs_dquot_from_disk_timestamp(&tv, ddqp->d_itimer);
+	dqp->q_itimer = tv.tv_sec;
+	xfs_dquot_from_disk_timestamp(&tv, ddqp->d_rtbtimer);
+	dqp->q_rtbtimer = tv.tv_sec;
+
 	/* initialize the dquot speculative prealloc thresholds */
 	xfs_dquot_set_prealloc_limits(dqp);
 }
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index d924da98f66a..99c0d6266fd8 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -60,6 +60,14 @@ struct xfs_dquot {
 	xfs_qcnt_t		q_prealloc_lo_wmark;
 	xfs_qcnt_t		q_prealloc_hi_wmark;
 	int64_t			q_low_space[XFS_QLOWSP_MAX];
+
+	/* incore block grace timeout */
+	time64_t		q_btimer;
+	/* incore inode grace timeout */
+	time64_t		q_itimer;
+	/* incore rt block grace timeout */
+	time64_t		q_rtbtimer;
+
 	struct mutex		q_qlock;
 	struct completion	q_flush;
 	atomic_t		q_pincount;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 268e028c9ec8..9be123a0902e 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -589,6 +589,7 @@ xfs_qm_init_timelimits(
 	struct xfs_mount	*mp,
 	struct xfs_quotainfo	*qinf)
 {
+	struct timespec64	tv;
 	struct xfs_disk_dquot	*ddqp;
 	struct xfs_dquot	*dqp;
 	uint			type;
@@ -628,12 +629,18 @@ xfs_qm_init_timelimits(
 	 * a user or group before he or she can not perform any
 	 * more writing. If it is zero, a default is used.
 	 */
-	if (ddqp->d_btimer)
-		qinf->qi_btimelimit = be32_to_cpu(ddqp->d_btimer);
-	if (ddqp->d_itimer)
-		qinf->qi_itimelimit = be32_to_cpu(ddqp->d_itimer);
-	if (ddqp->d_rtbtimer)
-		qinf->qi_rtbtimelimit = be32_to_cpu(ddqp->d_rtbtimer);
+	if (ddqp->d_btimer) {
+		xfs_dquot_from_disk_timestamp(&tv, ddqp->d_btimer);
+		qinf->qi_btimelimit = tv.tv_sec;
+	}
+	if (ddqp->d_itimer) {
+		xfs_dquot_from_disk_timestamp(&tv, ddqp->d_itimer);
+		qinf->qi_itimelimit = tv.tv_sec;
+	}
+	if (ddqp->d_rtbtimer) {
+		xfs_dquot_from_disk_timestamp(&tv, ddqp->d_rtbtimer);
+		qinf->qi_rtbtimelimit = tv.tv_sec;
+	}
 	if (ddqp->d_bwarns)
 		qinf->qi_bwarnlimit = be16_to_cpu(ddqp->d_bwarns);
 	if (ddqp->d_iwarns)
@@ -848,16 +855,23 @@ xfs_qm_reset_dqintervals(
 	struct xfs_mount	*mp,
 	struct xfs_disk_dquot	*ddq)
 {
+	struct timespec64	tv = { 0 };
 	struct xfs_quotainfo	*qinf = mp->m_quotainfo;
 
-	if (qinf->qi_btimelimit != XFS_QM_BTIMELIMIT)
-		ddq->d_btimer = cpu_to_be32(qinf->qi_btimelimit);
+	if (qinf->qi_btimelimit != XFS_QM_BTIMELIMIT) {
+		tv.tv_sec = qinf->qi_btimelimit;
+		xfs_dquot_to_disk_timestamp(&ddq->d_btimer, &tv);
+	}
 
-	if (qinf->qi_itimelimit != XFS_QM_ITIMELIMIT)
-		ddq->d_itimer = cpu_to_be32(qinf->qi_itimelimit);
+	if (qinf->qi_itimelimit != XFS_QM_ITIMELIMIT) {
+		tv.tv_sec = qinf->qi_itimelimit;
+		xfs_dquot_to_disk_timestamp(&ddq->d_itimer, &tv);
+	}
 
-	if (qinf->qi_rtbtimelimit != XFS_QM_RTBTIMELIMIT)
-		ddq->d_rtbtimer = cpu_to_be32(qinf->qi_rtbtimelimit);
+	if (qinf->qi_rtbtimelimit != XFS_QM_RTBTIMELIMIT) {
+		tv.tv_sec = qinf->qi_rtbtimelimit;
+		xfs_dquot_to_disk_timestamp(&ddq->d_rtbtimer, &tv);
+	}
 }
 
 STATIC void
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 20a6d304d1be..bd9db42b89b9 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -442,14 +442,17 @@ xfs_qm_scall_quotaon(
 static inline void
 xfs_qm_set_grace(
 	time_t			*qi_limit,
+	time64_t		*itimer,
 	__be32			*dtimer,
 	const s64		grace)
 {
-	time64_t		new_grace;
+	struct timespec64	tv = { 0 };
 
-	new_grace = clamp_t(time64_t, grace, XFS_DQ_GRACE_MIN,
+	tv.tv_sec = clamp_t(time64_t, grace, XFS_DQ_GRACE_MIN,
 					     XFS_DQ_GRACE_MAX);
-	*dtimer = cpu_to_be32(new_grace);
+	*qi_limit = tv.tv_sec;
+	*itimer = tv.tv_sec;
+	xfs_dquot_to_disk_timestamp(dtimer, &tv);
 }
 
 #define XFS_QC_MASK \
@@ -582,13 +585,14 @@ xfs_qm_scall_setqlim(
 		 * for warnings.
 		 */
 		if (newlim->d_fieldmask & QC_SPC_TIMER)
-			xfs_qm_set_grace(&q->qi_btimelimit, &ddq->d_btimer,
-					newlim->d_spc_timer);
+			xfs_qm_set_grace(&q->qi_btimelimit, &dqp->q_btimer,
+					&ddq->d_btimer, newlim->d_spc_timer);
 		if (newlim->d_fieldmask & QC_INO_TIMER)
-			xfs_qm_set_grace(&q->qi_itimelimit, &ddq->d_itimer,
-					newlim->d_ino_timer);
+			xfs_qm_set_grace(&q->qi_itimelimit, &dqp->q_itimer,
+					&ddq->d_itimer, newlim->d_ino_timer);
 		if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
-			xfs_qm_set_grace(&q->qi_rtbtimelimit, &ddq->d_rtbtimer,
+			xfs_qm_set_grace(&q->qi_rtbtimelimit, &dqp->q_rtbtimer,
+					&ddq->d_rtbtimer,
 					newlim->d_rt_spc_timer);
 		if (newlim->d_fieldmask & QC_SPC_WARNS)
 			q->qi_bwarnlimit = newlim->d_spc_warns;
@@ -635,8 +639,8 @@ xfs_qm_scall_getquota_fill_qc(
 	dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
 	dst->d_space = XFS_FSB_TO_B(mp, dqp->q_res_bcount - dqp->q_ina_bcount);
 	dst->d_ino_count = dqp->q_res_icount - dqp->q_ina_icount;
-	dst->d_spc_timer = be32_to_cpu(dqp->q_core.d_btimer);
-	dst->d_ino_timer = be32_to_cpu(dqp->q_core.d_itimer);
+	dst->d_spc_timer = dqp->q_btimer;
+	dst->d_ino_timer = dqp->q_itimer;
 	dst->d_ino_warns = be16_to_cpu(dqp->q_core.d_iwarns);
 	dst->d_spc_warns = be16_to_cpu(dqp->q_core.d_bwarns);
 	dst->d_rt_spc_hardlimit =
@@ -645,7 +649,7 @@ xfs_qm_scall_getquota_fill_qc(
 		XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
 	dst->d_rt_space =
 		XFS_FSB_TO_B(mp, dqp->q_res_rtbcount - dqp->q_ina_rtbcount);
-	dst->d_rt_spc_timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
+	dst->d_rt_spc_timer = dqp->q_rtbtimer;
 	dst->d_rt_spc_warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
 
 	/*
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 7a2a3bd11db9..62ef99f705df 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -568,7 +568,7 @@ static inline bool
 xfs_quota_timer_exceeded(
 	time64_t		timer)
 {
-	return timer != 0 && get_seconds() > timer;
+	return timer != 0 && ktime_get_real_seconds() > timer;
 }
 
 /*
@@ -608,7 +608,7 @@ xfs_trans_dqresv(
 		softlimit = be64_to_cpu(dqp->q_core.d_blk_softlimit);
 		if (!softlimit)
 			softlimit = defq->bsoftlimit;
-		timer = be32_to_cpu(dqp->q_core.d_btimer);
+		timer = dqp->q_btimer;
 		warns = be16_to_cpu(dqp->q_core.d_bwarns);
 		warnlimit = dqp->q_mount->m_quotainfo->qi_bwarnlimit;
 		resbcountp = &dqp->q_res_bcount;
@@ -620,7 +620,7 @@ xfs_trans_dqresv(
 		softlimit = be64_to_cpu(dqp->q_core.d_rtb_softlimit);
 		if (!softlimit)
 			softlimit = defq->rtbsoftlimit;
-		timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
+		timer = dqp->q_rtbtimer;
 		warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
 		warnlimit = dqp->q_mount->m_quotainfo->qi_rtbwarnlimit;
 		resbcountp = &dqp->q_res_rtbcount;
@@ -655,7 +655,7 @@ xfs_trans_dqresv(
 		}
 		if (ninos > 0) {
 			total_count = be64_to_cpu(dqp->q_core.d_icount) + ninos;
-			timer = be32_to_cpu(dqp->q_core.d_itimer);
+			timer = dqp->q_itimer;
 			warns = be16_to_cpu(dqp->q_core.d_iwarns);
 			warnlimit = dqp->q_mount->m_quotainfo->qi_iwarnlimit;
 			hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);


  parent reply	other threads:[~2020-01-01  1:12 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-01  1:11 [PATCH 00/14] xfs: widen timestamps to deal with y2038 Darrick J. Wong
2020-01-01  1:11 ` [PATCH 01/14] xfs: explicitly define inode timestamp range Darrick J. Wong
2020-02-12 23:00   ` Eric Sandeen
2020-02-13  1:26     ` Darrick J. Wong
2020-02-13  1:50       ` Eric Sandeen
2020-02-13  1:53         ` Darrick J. Wong
2020-01-01  1:11 ` [PATCH 02/14] xfs: preserve default grace interval during quotacheck Darrick J. Wong
2020-02-12 23:35   ` Eric Sandeen
2020-02-19  4:55   ` Eric Sandeen
2020-03-03  3:03     ` Eric Sandeen
2020-03-03 15:48       ` Darrick J. Wong
2020-03-03 15:52         ` Eric Sandeen
2020-01-01  1:11 ` [PATCH 03/14] xfs: refactor quota exceeded test Darrick J. Wong
2020-02-12 23:51   ` Eric Sandeen
2020-02-13  1:41     ` Darrick J. Wong
2020-02-13  1:52       ` Eric Sandeen
2020-02-13  1:59         ` Darrick J. Wong
2020-05-31 14:04       ` Amir Goldstein
2020-01-01  1:11 ` [PATCH 04/14] xfs: fix quota timer inactivation Darrick J. Wong
2020-05-31 15:04   ` Amir Goldstein
2020-06-01 23:56     ` Darrick J. Wong
2020-01-01  1:11 ` [PATCH 05/14] xfs: refactor quota expiration timer modification Darrick J. Wong
2020-02-12 23:57   ` Eric Sandeen
2020-02-13  1:46     ` Darrick J. Wong
2020-02-13  3:27       ` Eric Sandeen
2020-02-13  3:32         ` Eric Sandeen
2020-02-13  5:33           ` Darrick J. Wong
2020-01-01  1:11 ` [PATCH 06/14] xfs: refactor default quota grace period setting code Darrick J. Wong
2020-02-13  0:15   ` Eric Sandeen
2020-02-13  1:53     ` Darrick J. Wong
2020-02-13  2:03       ` Darrick J. Wong
2020-01-01  1:11 ` [PATCH 07/14] xfs: remove xfs_timestamp_t Darrick J. Wong
2020-01-01  1:11 ` [PATCH 08/14] xfs: move xfs_log_dinode_to_disk to the log code Darrick J. Wong
2020-01-01  1:11 ` [PATCH 09/14] xfs: refactor timestamp coding Darrick J. Wong
2020-01-01  1:12 ` [PATCH 10/14] xfs: convert struct xfs_timestamp to union Darrick J. Wong
2020-01-01  1:12 ` [PATCH 11/14] xfs: widen ondisk timestamps to deal with y2038 problem Darrick J. Wong
2020-05-31 12:30   ` Amir Goldstein
2020-06-01 23:17     ` Darrick J. Wong
2020-06-02  4:26       ` Amir Goldstein
2020-01-01  1:12 ` Darrick J. Wong [this message]
2020-01-01  1:12 ` [PATCH 13/14] xfs: enable bigtime for quota timers Darrick J. Wong
2020-05-31 17:07   ` Amir Goldstein
2020-06-02  0:09     ` Darrick J. Wong
2020-06-02  4:04       ` Amir Goldstein
2020-01-01  1:12 ` [PATCH 14/14] xfs: enable big timestamps Darrick J. Wong
2020-05-26  9:20 ` [PATCH 00/14] xfs: widen timestamps to deal with y2038 Amir Goldstein
2020-05-26 15:57   ` Darrick J. Wong
2020-05-26 16:42     ` Amir Goldstein
2020-05-31 17:31       ` Amir Goldstein
2020-06-02  0:09         ` Darrick J. Wong

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=157784113869.1364230.10740359430858443674.stgit@magnolia \
    --to=darrick.wong@oracle.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.