You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
6.8 KiB
237 lines
6.8 KiB
From f3eb31d9c005558ce975e2806f8dc73b0ecbd7f7 Mon Sep 17 00:00:00 2001
|
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
|
Subject: [PATCH] xfs_quota: support editing and reporting quotas with bigtime
|
|
|
|
Enhance xfs_quota to detect and report grace period expirations past
|
|
2038.
|
|
|
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
|
---
|
|
|
|
diff --git a/include/xqm.h b/include/xqm.h
|
|
index 8ab1907..573441d 100644
|
|
--- a/include/xqm.h
|
|
+++ b/include/xqm.h
|
|
@@ -47,7 +47,10 @@ typedef struct fs_disk_quota {
|
|
__s32 d_btimer; /* similar to above; for disk blocks */
|
|
__u16 d_iwarns; /* # warnings issued wrt num inodes */
|
|
__u16 d_bwarns; /* # warnings issued wrt disk blocks */
|
|
- __s32 d_padding2; /* padding2 - for future use */
|
|
+ __s8 d_itimer_hi; /* upper 8 bits of timer values */
|
|
+ __s8 d_btimer_hi;
|
|
+ __s8 d_rtbtimer_hi;
|
|
+ __s8 d_padding2; /* padding2 - for future use */
|
|
__u64 d_rtb_hardlimit;/* absolute limit on realtime blks */
|
|
__u64 d_rtb_softlimit;/* preferred limit on RT disk blks */
|
|
__u64 d_rtbcount; /* # realtime blocks owned */
|
|
@@ -93,6 +96,21 @@ typedef struct fs_disk_quota {
|
|
#define FS_DQ_RTBWARNS (1<<11)
|
|
#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
|
|
|
|
+/*
|
|
+ * Accounting values. These can only be set for filesystem with
|
|
+ * non-transactional quotas that require quotacheck(8) in userspace.
|
|
+ */
|
|
+#define FS_DQ_BCOUNT (1<<12)
|
|
+#define FS_DQ_ICOUNT (1<<13)
|
|
+#define FS_DQ_RTBCOUNT (1<<14)
|
|
+#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)
|
|
+
|
|
+/*
|
|
+ * Quota expiration timestamps are 40-bit signed integers, with the upper 8
|
|
+ * bits encoded in the _hi fields.
|
|
+ */
|
|
+#define FS_DQ_BIGTIME (1<<15)
|
|
+
|
|
/*
|
|
* Various flags related to quotactl(2). Only relevant to XFS filesystems.
|
|
*/
|
|
diff --git a/quota/edit.c b/quota/edit.c
|
|
index b3cad02..1a3b2d9 100644
|
|
--- a/quota/edit.c
|
|
+++ b/quota/edit.c
|
|
@@ -417,6 +417,53 @@ restore_f(
|
|
return 0;
|
|
}
|
|
|
|
+time64_t
|
|
+decode_timer(
|
|
+ const struct fs_disk_quota *d,
|
|
+ __s32 timer_lo,
|
|
+ __s8 timer_hi)
|
|
+{
|
|
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
|
|
+ return (uint32_t)timer_lo | (int64_t)timer_hi << 32;
|
|
+ return timer_lo;
|
|
+}
|
|
+
|
|
+static inline void
|
|
+encode_timer(
|
|
+ const struct fs_disk_quota *d,
|
|
+ __s32 *timer_lo,
|
|
+ __s8 *timer_hi,
|
|
+ time64_t timer)
|
|
+{
|
|
+ *timer_lo = timer;
|
|
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
|
|
+ *timer_hi = timer >> 32;
|
|
+ else
|
|
+ *timer_hi = 0;
|
|
+}
|
|
+
|
|
+static inline bool want_bigtime(time64_t timer)
|
|
+{
|
|
+ return timer > INT32_MAX || timer < INT32_MIN;
|
|
+}
|
|
+
|
|
+static void
|
|
+encode_timers(
|
|
+ struct fs_disk_quota *d,
|
|
+ time64_t btimer,
|
|
+ time64_t itimer,
|
|
+ time64_t rtbtimer)
|
|
+{
|
|
+ d->d_fieldmask &= ~FS_DQ_BIGTIME;
|
|
+ if (want_bigtime(btimer) || want_bigtime(itimer) ||
|
|
+ want_bigtime(rtbtimer))
|
|
+ d->d_fieldmask |= FS_DQ_BIGTIME;
|
|
+
|
|
+ encode_timer(d, &d->d_btimer, &d->d_btimer_hi, btimer);
|
|
+ encode_timer(d, &d->d_itimer, &d->d_itimer_hi, itimer);
|
|
+ encode_timer(d, &d->d_rtbtimer, &d->d_rtbtimer_hi, rtbtimer);
|
|
+}
|
|
+
|
|
static void
|
|
set_timer(
|
|
uint32_t id,
|
|
@@ -426,6 +473,7 @@ set_timer(
|
|
time64_t value)
|
|
{
|
|
struct fs_disk_quota d;
|
|
+ time64_t btimer, itimer, rtbtimer;
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
|
|
@@ -446,23 +494,28 @@ set_timer(
|
|
|
|
time(&now);
|
|
|
|
+ btimer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
|
+ itimer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
|
+ rtbtimer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
|
+
|
|
/* Only set grace time if user is already past soft limit */
|
|
if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
|
|
- d.d_btimer = now + value;
|
|
+ btimer = now + value;
|
|
if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
|
|
- d.d_itimer = now + value;
|
|
+ itimer = now + value;
|
|
if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
|
|
- d.d_rtbtimer = now + value;
|
|
+ rtbtimer = now + value;
|
|
} else {
|
|
- d.d_btimer = value;
|
|
- d.d_itimer = value;
|
|
- d.d_rtbtimer = value;
|
|
+ btimer = value;
|
|
+ itimer = value;
|
|
+ rtbtimer = value;
|
|
}
|
|
|
|
d.d_version = FS_DQUOT_VERSION;
|
|
d.d_flags = type;
|
|
d.d_fieldmask = mask;
|
|
d.d_id = id;
|
|
+ encode_timers(&d, btimer, itimer, rtbtimer);
|
|
|
|
if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
|
|
exitcode = 1;
|
|
diff --git a/quota/quota.c b/quota/quota.c
|
|
index 8ba0995..0747ced 100644
|
|
--- a/quota/quota.c
|
|
+++ b/quota/quota.c
|
|
@@ -101,7 +101,7 @@ quota_mount(
|
|
}
|
|
|
|
if (form & XFS_BLOCK_QUOTA) {
|
|
- timer = d.d_btimer;
|
|
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|
|
@@ -123,7 +123,7 @@ quota_mount(
|
|
time_to_string(timer, qflags));
|
|
}
|
|
if (form & XFS_INODE_QUOTA) {
|
|
- timer = d.d_itimer;
|
|
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|
|
@@ -145,7 +145,7 @@ quota_mount(
|
|
time_to_string(timer, qflags));
|
|
}
|
|
if (form & XFS_RTBLOCK_QUOTA) {
|
|
- timer = d.d_rtbtimer;
|
|
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|
|
diff --git a/quota/quota.h b/quota/quota.h
|
|
index 13ae450..74eb146 100644
|
|
--- a/quota/quota.h
|
|
+++ b/quota/quota.h
|
|
@@ -3,6 +3,8 @@
|
|
* Copyright (c) 2005 Silicon Graphics, Inc.
|
|
* All Rights Reserved.
|
|
*/
|
|
+#ifndef XFS_QUOTA_QUOTA_H_
|
|
+#define XFS_QUOTA_QUOTA_H_
|
|
|
|
#include "xqm.h"
|
|
#include "path.h"
|
|
@@ -73,3 +75,8 @@ extern char *uid_to_name(uint32_t __uid);
|
|
extern char *gid_to_name(uint32_t __gid);
|
|
extern char *prid_to_name(uint32_t __prid);
|
|
extern bool isdigits_only(const char *);
|
|
+
|
|
+time64_t decode_timer(const struct fs_disk_quota *d, __s32 timer_lo,
|
|
+ __s8 timer_hi);
|
|
+
|
|
+#endif /* XFS_QUOTA_QUOTA_H_ */
|
|
diff --git a/quota/report.c b/quota/report.c
|
|
index 2d5024e..6ac5549 100644
|
|
--- a/quota/report.c
|
|
+++ b/quota/report.c
|
|
@@ -398,7 +398,7 @@ report_mount(
|
|
}
|
|
|
|
if (form & XFS_BLOCK_QUOTA) {
|
|
- timer = d.d_btimer;
|
|
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|
|
@@ -420,7 +420,7 @@ report_mount(
|
|
time_to_string(timer, qflags));
|
|
}
|
|
if (form & XFS_INODE_QUOTA) {
|
|
- timer = d.d_itimer;
|
|
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|
|
@@ -442,7 +442,7 @@ report_mount(
|
|
time_to_string(timer, qflags));
|
|
}
|
|
if (form & XFS_RTBLOCK_QUOTA) {
|
|
- timer = d.d_rtbtimer;
|
|
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
|
qflags = (flags & HUMAN_FLAG);
|
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
|
qflags |= LIMIT_FLAG;
|