@@ -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);
+}
@@ -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__ */
@@ -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);
}
@@ -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;
@@ -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
@@ -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);
/*
@@ -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);