summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-02-19 17:02:26 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2020-06-01 21:16:39 -0700
commit4ec2c701e376753c8a81a658f89857938c977601 (patch)
tree1e6a5e00402ba442550b6c9cd50121b73bce3b3c
parentcef4b49366bbeb87c6f271a212d780aaff419c48 (diff)
xfs: enable bigtime for quota timers
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>
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c72
-rw-r--r--fs/xfs/libxfs/xfs_format.h22
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h11
-rw-r--r--fs/xfs/scrub/quota.c5
-rw-r--r--fs/xfs/xfs_dquot.c69
-rw-r--r--fs/xfs/xfs_ondisk.h7
-rw-r--r--fs/xfs/xfs_qm.c13
-rw-r--r--fs/xfs/xfs_qm.h2
-rw-r--r--fs/xfs/xfs_qm_syscalls.c17
9 files changed, 182 insertions, 36 deletions
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index 72e0fcfef580..2b5d51a6d64b 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -40,6 +40,8 @@ xfs_dquot_verify(
xfs_dqid_t id,
uint type) /* used only during quotacheck */
{
+ uint8_t dtype;
+
/*
* We can encounter an uninitialized dquot buffer for 2 reasons:
* 1. If we crash while deleting the quotainode(s), and those blks got
@@ -60,11 +62,22 @@ xfs_dquot_verify(
if (ddq->d_version != XFS_DQUOT_VERSION)
return __this_address;
- if (type && ddq->d_flags != type)
+ dtype = ddq->d_flags & XFS_DQ_ALLTYPES;
+ if (type && dtype != type)
+ return __this_address;
+ if (dtype != XFS_DQ_USER &&
+ dtype != XFS_DQ_PROJ &&
+ dtype != XFS_DQ_GROUP)
+ return __this_address;
+
+ if (ddq->d_flags & ~(XFS_DQ_ALLTYPES | XFS_DQ_BIGTIME))
return __this_address;
- if (ddq->d_flags != XFS_DQ_USER &&
- ddq->d_flags != XFS_DQ_PROJ &&
- ddq->d_flags != XFS_DQ_GROUP)
+
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) &&
+ !xfs_sb_version_hasbigtime(&mp->m_sb))
+ return __this_address;
+
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) && !ddq->d_id)
return __this_address;
if (id != -1 && id != be32_to_cpu(ddq->d_id))
@@ -290,17 +303,68 @@ const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
void
xfs_dquot_from_disk_timestamp(
+ struct xfs_disk_dquot *ddq,
struct timespec64 *tv,
__be32 dtimer)
{
tv->tv_nsec = 0;
+
+ /* Zero always means zero, regardless of encoding. */
+ if (!dtimer) {
+ tv->tv_sec = 0;
+ return;
+ }
+
+ if (ddq->d_flags & XFS_DQ_BIGTIME) {
+ uint64_t t;
+
+ t = be32_to_cpu(dtimer);
+ tv->tv_sec = t << XFS_DQ_BIGTIME_SHIFT;
+ return;
+ }
+
tv->tv_sec = be32_to_cpu(dtimer);
}
void
xfs_dquot_to_disk_timestamp(
+ struct xfs_disk_dquot *ddq,
__be32 *dtimer,
const struct timespec64 *tv)
{
+ /* Zero always means zero, regardless of encoding. */
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) && tv->tv_sec != 0) {
+ uint64_t t = tv->tv_sec;
+
+ /*
+ * 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(tv->tv_sec);
}
+
+/*
+ * Convert the dquot to bigtime format incore so that we'll write out the new
+ * values the next time we flush the dquot to disk. Skip this for d_id == 0
+ * because that dquot stores the grace period intervals. Returns true if we
+ * upgraded the format, false otherwise.
+ */
+bool
+xfs_dquot_add_bigtime(
+ struct xfs_mount *mp,
+ struct xfs_disk_dquot *ddq)
+{
+ if (xfs_sb_version_hasbigtime(&mp->m_sb) && ddq->d_id &&
+ !(ddq->d_flags & XFS_DQ_BIGTIME)) {
+ ddq->d_flags |= XFS_DQ_BIGTIME;
+ return true;
+ }
+
+ return false;
+}
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 159182978ebc..932984737e07 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1262,6 +1262,28 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#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. This is the q_core of the struct xfs_dquot that
* is kept in kernel memory. We pad this with some more expansion room
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index c453611ade3b..4ac486fd20a8 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -26,6 +26,7 @@ typedef uint16_t xfs_qwarncnt_t;
#define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */
#define XFS_DQ_FREEING 0x0010 /* dquot is being torn down */
+#define XFS_DQ_BIGTIME 0x0020 /* big timestamp format */
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
@@ -34,7 +35,8 @@ typedef uint16_t xfs_qwarncnt_t;
{ XFS_DQ_PROJ, "PROJ" }, \
{ XFS_DQ_GROUP, "GROUP" }, \
{ XFS_DQ_DIRTY, "DIRTY" }, \
- { XFS_DQ_FREEING, "FREEING" }
+ { XFS_DQ_FREEING, "FREEING" }, \
+ { XFS_DQ_BIGTIME, "BIGTIME" }
/*
* We have the possibility of all three quota types being active at once, and
@@ -144,7 +146,10 @@ 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);
+void xfs_dquot_from_disk_timestamp(struct xfs_disk_dquot *ddq,
+ struct timespec64 *tv, __be32 dtimer);
+void xfs_dquot_to_disk_timestamp(struct xfs_disk_dquot *ddq,
+ __be32 *dtimer, const struct timespec64 *tv);
+bool xfs_dquot_add_bigtime(struct xfs_mount *mp, struct xfs_disk_dquot *ddq);
#endif /* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c
index 64e24fe5dcb2..6ff402bc0a3e 100644
--- a/fs/xfs/scrub/quota.c
+++ b/fs/xfs/scrub/quota.c
@@ -135,6 +135,11 @@ xchk_quota_item(
if (d->d_pad0 != cpu_to_be32(0) || d->d_pad != cpu_to_be16(0))
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
+ /* incore should always have bigtime iflag set except for root */
+ if (xfs_sb_version_hasbigtime(&mp->m_sb) && d->d_id &&
+ !(d->d_flags & XFS_DQ_BIGTIME))
+ xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
+
/* Check the limits. */
bhard = be64_to_cpu(d->d_blk_hardlimit);
ihard = be64_to_cpu(d->d_ino_hardlimit);
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 78fb08ea461b..dae7c327eab3 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -117,35 +117,42 @@ xfs_quota_exceeded(
*/
static inline time64_t
xfs_dquot_clamp_timer(
- time64_t timer)
+ struct xfs_disk_dquot *ddq,
+ time64_t timer)
{
+ if (ddq->d_flags & XFS_DQ_BIGTIME)
+ return clamp_t(time64_t, timer, XFS_DQ_BIGTIMEOUT_MIN,
+ XFS_DQ_BIGTIMEOUT_MAX);
return clamp_t(time64_t, timer, XFS_DQ_TIMEOUT_MIN, XFS_DQ_TIMEOUT_MAX);
}
/* Set a quota grace period expiration timer. */
static inline void
xfs_quota_set_timer(
+ struct xfs_disk_dquot *ddq,
time64_t *itimer,
__be32 *dtimer,
time64_t limit)
{
struct timespec64 tv = { 0 };
- tv.tv_sec = xfs_dquot_clamp_timer(ktime_get_real_seconds() + limit);
+ tv.tv_sec = xfs_dquot_clamp_timer(ddq,
+ ktime_get_real_seconds() + limit);
*itimer = tv.tv_sec;
- xfs_dquot_to_disk_timestamp(dtimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, dtimer, &tv);
}
/* Clear a quota grace period expiration timer. */
static inline void
xfs_quota_clear_timer(
+ struct xfs_disk_dquot *ddq,
time64_t *itimer,
__be32 *dtimer)
{
struct timespec64 tv = { 0 };
*itimer = tv.tv_sec;
- xfs_dquot_to_disk_timestamp(dtimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, dtimer, &tv);
}
/*
@@ -187,14 +194,14 @@ xfs_qm_adjust_dqtimers(
d->d_blk_softlimit, d->d_blk_hardlimit);
if (!dqp->q_btimer) {
if (over) {
- xfs_quota_set_timer(&dqp->q_btimer, &d->d_btimer,
+ xfs_quota_set_timer(d, &dqp->q_btimer, &d->d_btimer,
mp->m_quotainfo->qi_btimelimit);
} else {
d->d_bwarns = 0;
}
} else {
if (!over) {
- xfs_quota_clear_timer(&dqp->q_btimer, &d->d_btimer);
+ xfs_quota_clear_timer(d, &dqp->q_btimer, &d->d_btimer);
}
}
@@ -202,14 +209,14 @@ xfs_qm_adjust_dqtimers(
d->d_ino_softlimit, d->d_ino_hardlimit);
if (!dqp->q_itimer) {
if (over) {
- xfs_quota_set_timer(&dqp->q_itimer, &d->d_itimer,
+ xfs_quota_set_timer(d, &dqp->q_itimer, &d->d_itimer,
mp->m_quotainfo->qi_itimelimit);
} else {
d->d_iwarns = 0;
}
} else {
if (!over) {
- xfs_quota_clear_timer(&dqp->q_itimer, &d->d_itimer);
+ xfs_quota_clear_timer(d, &dqp->q_itimer, &d->d_itimer);
}
}
@@ -217,14 +224,16 @@ xfs_qm_adjust_dqtimers(
d->d_rtb_softlimit, d->d_rtb_hardlimit);
if (!dqp->q_rtbtimer) {
if (over) {
- xfs_quota_set_timer(&dqp->q_rtbtimer, &d->d_rtbtimer,
+ xfs_quota_set_timer(d, &dqp->q_rtbtimer,
+ &d->d_rtbtimer,
mp->m_quotainfo->qi_rtbtimelimit);
} else {
d->d_rtbwarns = 0;
}
} else {
if (!over) {
- xfs_quota_clear_timer(&dqp->q_rtbtimer, &d->d_rtbtimer);
+ xfs_quota_clear_timer(d, &dqp->q_rtbtimer,
+ &d->d_rtbtimer);
}
}
}
@@ -262,6 +271,7 @@ 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_flags = type;
+ xfs_dquot_add_bigtime(mp, &d->dd_diskdq);
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),
@@ -563,9 +573,10 @@ xfs_dquot_from_disk(
{
struct timespec64 tv;
struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset;
+ struct xfs_disk_dquot *iddq = &dqp->q_core;
/* copy everything from disk dquot to the incore dquot */
- memcpy(&dqp->q_core, ddqp, sizeof(struct xfs_disk_dquot));
+ memcpy(iddq, ddqp, sizeof(struct xfs_disk_dquot));
/*
* Reservation counters are defined as reservation plus current usage
@@ -575,13 +586,28 @@ 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);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_btimer);
dqp->q_btimer = tv.tv_sec;
- xfs_dquot_from_disk_timestamp(&tv, ddqp->d_itimer);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_itimer);
dqp->q_itimer = tv.tv_sec;
- xfs_dquot_from_disk_timestamp(&tv, ddqp->d_rtbtimer);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_rtbtimer);
dqp->q_rtbtimer = tv.tv_sec;
+ /* Upgrade to bigtime if possible. */
+ if (xfs_dquot_add_bigtime(dqp->q_mount, iddq)) {
+ tv.tv_sec = xfs_dquot_clamp_timer(iddq, dqp->q_btimer);
+ xfs_dquot_to_disk_timestamp(iddq, &iddq->d_btimer, &tv);
+ dqp->q_btimer = tv.tv_sec;
+
+ tv.tv_sec = xfs_dquot_clamp_timer(iddq, dqp->q_itimer);
+ xfs_dquot_to_disk_timestamp(iddq, &iddq->d_itimer, &tv);
+ dqp->q_itimer = tv.tv_sec;
+
+ tv.tv_sec = xfs_dquot_clamp_timer(iddq, dqp->q_rtbtimer);
+ xfs_dquot_to_disk_timestamp(iddq, &iddq->d_rtbtimer, &tv);
+ dqp->q_rtbtimer = tv.tv_sec;
+ }
+
/* initialize the dquot speculative prealloc thresholds */
xfs_dquot_set_prealloc_limits(dqp);
}
@@ -1211,6 +1237,21 @@ xfs_qm_dqflush(
memcpy(ddqp, &dqp->q_core, sizeof(struct xfs_disk_dquot));
/*
+ * We should never write non-bigtime dquots to a bigtime fs, except for
+ * the root dquot.
+ */
+ if (!(dqp->q_core.d_flags & XFS_DQ_BIGTIME) && dqp->q_core.d_id &&
+ xfs_sb_version_hasbigtime(&mp->m_sb)) {
+ xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
+ be32_to_cpu(ddqp->d_id), __this_address);
+ xfs_buf_relse(bp);
+ xfs_dqfunlock(dqp);
+ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ xfs_quota_mark_sick(mp, dqp->dq_flags);
+ return -EFSCORRUPTED;
+ }
+
+ /*
* Clear the dirty field and remember the flush lsn for later use.
*/
dqp->dq_flags &= ~XFS_DQ_DIRTY;
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 80129b2dc392..734a0fe7dd73 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -32,6 +32,13 @@ xfs_check_limits(void)
XFS_CHECK_VALUE(XFS_DQ_TIMEOUT_MAX, 4294967295LL);
XFS_CHECK_VALUE(XFS_DQ_GRACE_MIN, 0LL);
XFS_CHECK_VALUE(XFS_DQ_GRACE_MAX, 4294967295LL);
+ XFS_CHECK_VALUE(XFS_DQ_BIGTIMEOUT_MIN, 1LL);
+ XFS_CHECK_VALUE(XFS_DQ_BIGTIMEOUT_MAX, 16299260425LL);
+
+ BUILD_BUG_ON_MSG((XFS_DQ_TIMEOUT_MAX << XFS_DQ_BIGTIME_SHIFT) <
+ XFS_DQ_BIGTIMEOUT_MAX,
+ "XFS: quota timeout field is not large enough to fit "
+ "XFS_DQ_BIGTIMEOUT_MAX");
}
static inline void __init
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index b040ff7e0259..3e4f65681852 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -634,15 +634,15 @@ xfs_qm_init_timelimits(
* more writing. If it is zero, a default is used.
*/
if (ddqp->d_btimer) {
- xfs_dquot_from_disk_timestamp(&tv, ddqp->d_btimer);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_btimer);
qinf->qi_btimelimit = tv.tv_sec;
}
if (ddqp->d_itimer) {
- xfs_dquot_from_disk_timestamp(&tv, ddqp->d_itimer);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_itimer);
qinf->qi_itimelimit = tv.tv_sec;
}
if (ddqp->d_rtbtimer) {
- xfs_dquot_from_disk_timestamp(&tv, ddqp->d_rtbtimer);
+ xfs_dquot_from_disk_timestamp(ddqp, &tv, ddqp->d_rtbtimer);
qinf->qi_rtbtimelimit = tv.tv_sec;
}
if (ddqp->d_bwarns)
@@ -908,12 +908,13 @@ xfs_qm_reset_dqcounts(
* should not reset them.
*/
if (ddq->d_id != 0) {
- xfs_dquot_to_disk_timestamp(&ddq->d_btimer, &tv);
- xfs_dquot_to_disk_timestamp(&ddq->d_itimer, &tv);
- xfs_dquot_to_disk_timestamp(&ddq->d_rtbtimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, &ddq->d_btimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, &ddq->d_itimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, &ddq->d_rtbtimer, &tv);
ddq->d_bwarns = 0;
ddq->d_iwarns = 0;
ddq->d_rtbwarns = 0;
+ xfs_dquot_add_bigtime(mp, ddq);
}
if (xfs_sb_version_hascrc(&mp->m_sb)) {
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index e492013f28d7..d3b69524ca18 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -84,7 +84,7 @@ xfs_dquot_tree(
struct xfs_quotainfo *qi,
int type)
{
- switch (type) {
+ switch (type & XFS_DQ_ALLTYPES) {
case XFS_DQ_USER:
return &qi->qi_uquota_tree;
case XFS_DQ_GROUP:
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 4963d000c137..02bb2ba9cf00 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -442,6 +442,7 @@ xfs_qm_scall_quotaon(
/* Set a new quota grace period. */
static inline void
xfs_qm_set_grace(
+ struct xfs_disk_dquot *ddq,
time64_t *qi_limit,
time64_t *itimer,
__be32 *dtimer,
@@ -453,7 +454,7 @@ xfs_qm_set_grace(
XFS_DQ_GRACE_MAX);
*qi_limit = tv.tv_sec;
*itimer = tv.tv_sec;
- xfs_dquot_to_disk_timestamp(dtimer, &tv);
+ xfs_dquot_to_disk_timestamp(ddq, dtimer, &tv);
}
#define XFS_QC_MASK \
@@ -586,14 +587,14 @@ xfs_qm_scall_setqlim(
* for warnings.
*/
if (newlim->d_fieldmask & QC_SPC_TIMER)
- xfs_qm_set_grace(&q->qi_btimelimit, &dqp->q_btimer,
+ xfs_qm_set_grace(ddq, &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, &dqp->q_itimer,
+ xfs_qm_set_grace(ddq, &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, &dqp->q_rtbtimer,
- &ddq->d_rtbtimer,
+ xfs_qm_set_grace(ddq, &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;
@@ -659,11 +660,11 @@ xfs_qm_scall_getquota_fill_qc(
* so return zeroes in that case.
*/
if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
- dqp->q_core.d_flags == XFS_DQ_USER) ||
+ (dqp->q_core.d_flags & XFS_DQ_ALLTYPES) == XFS_DQ_USER) ||
(!XFS_IS_GQUOTA_ENFORCED(mp) &&
- dqp->q_core.d_flags == XFS_DQ_GROUP) ||
+ (dqp->q_core.d_flags & XFS_DQ_ALLTYPES) == XFS_DQ_GROUP) ||
(!XFS_IS_PQUOTA_ENFORCED(mp) &&
- dqp->q_core.d_flags == XFS_DQ_PROJ)) {
+ (dqp->q_core.d_flags & XFS_DQ_ALLTYPES) == XFS_DQ_PROJ)) {
dst->d_spc_timer = 0;
dst->d_ino_timer = 0;
dst->d_rt_spc_timer = 0;