|
|
1569e6 |
From 36dc471cc9bb17868b79cf8dea8151b207387539 Mon Sep 17 00:00:00 2001
|
|
|
1569e6 |
From: Eric Sandeen <sandeen@redhat.com>
|
|
|
1569e6 |
Date: Tue, 26 May 2020 14:36:26 -0400
|
|
|
1569e6 |
Subject: [PATCH] xfs_quota: allow individual timer extension
|
|
|
1569e6 |
|
|
|
1569e6 |
The only grace period which can be set via xfs_quota today is for id 0,
|
|
|
1569e6 |
i.e. the default grace period for all users. However, setting an
|
|
|
1569e6 |
individual grace period is useful; for example:
|
|
|
1569e6 |
|
|
|
1569e6 |
Alice has a soft quota of 100 inodes, and a hard quota of 200 inodes
|
|
|
1569e6 |
Alice uses 150 inodes, and enters a short grace period
|
|
|
1569e6 |
Alice really needs to use those 150 inodes past the grace period
|
|
|
1569e6 |
The administrator extends Alice's grace period until next Monday
|
|
|
1569e6 |
|
|
|
1569e6 |
vfs quota users such as ext4 can do this today, with setquota -T
|
|
|
1569e6 |
|
|
|
1569e6 |
xfs_quota can now accept an optional user id or name (symmetric with
|
|
|
1569e6 |
how warn limits are specified), in which case that user's grace period
|
|
|
1569e6 |
is extended to expire the given amount of time from now().
|
|
|
1569e6 |
|
|
|
1569e6 |
To maintain compatibility with old command lines, if none of
|
|
|
1569e6 |
[-d|id|name] are specified, default limits are set as before.
|
|
|
1569e6 |
|
|
|
1569e6 |
(kernelspace requires updates to enable all this as well.)
|
|
|
1569e6 |
|
|
|
1569e6 |
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
|
|
1569e6 |
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
|
|
1569e6 |
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
|
|
1569e6 |
---
|
|
|
1569e6 |
man/man8/xfs_quota.8 | 36 +++++++++++++++++--
|
|
|
1569e6 |
quota/edit.c | 83 +++++++++++++++++++++++++++++++++++++-------
|
|
|
1569e6 |
2 files changed, 104 insertions(+), 15 deletions(-)
|
|
|
1569e6 |
|
|
|
1569e6 |
Index: xfsprogs-5.0.0/man/man8/xfs_quota.8
|
|
|
1569e6 |
===================================================================
|
|
|
1569e6 |
--- xfsprogs-5.0.0.orig/man/man8/xfs_quota.8
|
|
|
1569e6 |
+++ xfsprogs-5.0.0/man/man8/xfs_quota.8
|
|
|
1569e6 |
@@ -460,14 +460,46 @@ must be specified.
|
|
|
1569e6 |
.B \-bir
|
|
|
1569e6 |
]
|
|
|
1569e6 |
.I value
|
|
|
1569e6 |
+[
|
|
|
1569e6 |
+.B -d
|
|
|
1569e6 |
+|
|
|
|
1569e6 |
+.I id
|
|
|
1569e6 |
+|
|
|
|
1569e6 |
+.I name
|
|
|
1569e6 |
+]
|
|
|
1569e6 |
.br
|
|
|
1569e6 |
Allows the quota enforcement timeout (i.e. the amount of time allowed
|
|
|
1569e6 |
to pass before the soft limits are enforced as the hard limits) to
|
|
|
1569e6 |
be modified. The current timeout setting can be displayed using the
|
|
|
1569e6 |
.B state
|
|
|
1569e6 |
-command. The value argument is a number of seconds, but units of
|
|
|
1569e6 |
-\&'minutes', 'hours', 'days', and 'weeks' are also understood
|
|
|
1569e6 |
+command.
|
|
|
1569e6 |
+.br
|
|
|
1569e6 |
+When setting the default timer via the
|
|
|
1569e6 |
+.B \-d
|
|
|
1569e6 |
+option, or for
|
|
|
1569e6 |
+.B id
|
|
|
1569e6 |
+0, or if no argument is given after
|
|
|
1569e6 |
+.I value
|
|
|
1569e6 |
+the
|
|
|
1569e6 |
+.I value
|
|
|
1569e6 |
+argument is a number of seconds indicating the relative amount of time after
|
|
|
1569e6 |
+soft limits are exceeded, before hard limits are enforced.
|
|
|
1569e6 |
+.br
|
|
|
1569e6 |
+When setting any other individual timer by
|
|
|
1569e6 |
+.I id
|
|
|
1569e6 |
+or
|
|
|
1569e6 |
+.I name,
|
|
|
1569e6 |
+the
|
|
|
1569e6 |
+.I value
|
|
|
1569e6 |
+is the number of seconds from now, at which time the hard limits will be enforced.
|
|
|
1569e6 |
+This allows extending the grace time of an individual user who has exceeded soft
|
|
|
1569e6 |
+limits.
|
|
|
1569e6 |
+.br
|
|
|
1569e6 |
+For
|
|
|
1569e6 |
+.I value,
|
|
|
1569e6 |
+units of \&'minutes', 'hours', 'days', and 'weeks' are also understood
|
|
|
1569e6 |
(as are their abbreviations 'm', 'h', 'd', and 'w').
|
|
|
1569e6 |
+.br
|
|
|
1569e6 |
.HP
|
|
|
1569e6 |
.B warn
|
|
|
1569e6 |
[
|
|
|
1569e6 |
Index: xfsprogs-5.0.0/quota/edit.c
|
|
|
1569e6 |
===================================================================
|
|
|
1569e6 |
--- xfsprogs-5.0.0.orig/quota/edit.c
|
|
|
1569e6 |
+++ xfsprogs-5.0.0/quota/edit.c
|
|
|
1569e6 |
@@ -419,6 +419,7 @@ restore_f(
|
|
|
1569e6 |
|
|
|
1569e6 |
static void
|
|
|
1569e6 |
set_timer(
|
|
|
1569e6 |
+ uint32_t id,
|
|
|
1569e6 |
uint type,
|
|
|
1569e6 |
uint mask,
|
|
|
1569e6 |
char *dev,
|
|
|
1569e6 |
@@ -427,14 +428,43 @@ set_timer(
|
|
|
1569e6 |
fs_disk_quota_t d;
|
|
|
1569e6 |
|
|
|
1569e6 |
memset(&d, 0, sizeof(d));
|
|
|
1569e6 |
+
|
|
|
1569e6 |
+ /*
|
|
|
1569e6 |
+ * If id is specified we are extending grace time by value
|
|
|
1569e6 |
+ * Otherwise we are setting the default grace time
|
|
|
1569e6 |
+ */
|
|
|
1569e6 |
+ if (id) {
|
|
|
1569e6 |
+ time_t now;
|
|
|
1569e6 |
+
|
|
|
1569e6 |
+ /* Get quota to find out whether user is past soft limits */
|
|
|
1569e6 |
+ if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) {
|
|
|
1569e6 |
+ exitcode = 1;
|
|
|
1569e6 |
+ fprintf(stderr, _("%s: cannot get quota: %s\n"),
|
|
|
1569e6 |
+ progname, strerror(errno));
|
|
|
1569e6 |
+ return;
|
|
|
1569e6 |
+ }
|
|
|
1569e6 |
+
|
|
|
1569e6 |
+ time(&now;;
|
|
|
1569e6 |
+
|
|
|
1569e6 |
+ /* Only set grace time if user is already past soft limit */
|
|
|
1569e6 |
+ if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
|
|
|
1569e6 |
+ d.d_btimer = now + value;
|
|
|
1569e6 |
+ if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
|
|
|
1569e6 |
+ d.d_itimer = now + value;
|
|
|
1569e6 |
+ if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
|
|
|
1569e6 |
+ d.d_rtbtimer = now + value;
|
|
|
1569e6 |
+ } else {
|
|
|
1569e6 |
+ d.d_btimer = value;
|
|
|
1569e6 |
+ d.d_itimer = value;
|
|
|
1569e6 |
+ d.d_rtbtimer = value;
|
|
|
1569e6 |
+ }
|
|
|
1569e6 |
+
|
|
|
1569e6 |
d.d_version = FS_DQUOT_VERSION;
|
|
|
1569e6 |
d.d_flags = type;
|
|
|
1569e6 |
d.d_fieldmask = mask;
|
|
|
1569e6 |
- d.d_itimer = value;
|
|
|
1569e6 |
- d.d_btimer = value;
|
|
|
1569e6 |
- d.d_rtbtimer = value;
|
|
|
1569e6 |
+ d.d_id = id;
|
|
|
1569e6 |
|
|
|
1569e6 |
- if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) {
|
|
|
1569e6 |
+ if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
|
|
|
1569e6 |
exitcode = 1;
|
|
|
1569e6 |
fprintf(stderr, _("%s: cannot set timer: %s\n"),
|
|
|
1569e6 |
progname, strerror(errno));
|
|
|
1569e6 |
@@ -447,10 +477,15 @@ timer_f(
|
|
|
1569e6 |
char **argv)
|
|
|
1569e6 |
{
|
|
|
1569e6 |
uint value;
|
|
|
1569e6 |
- int c, type = 0, mask = 0;
|
|
|
1569e6 |
+ char *name = NULL;
|
|
|
1569e6 |
+ uint32_t id = 0;
|
|
|
1569e6 |
+ int c, flags = 0, type = 0, mask = 0;
|
|
|
1569e6 |
|
|
|
1569e6 |
- while ((c = getopt(argc, argv, "bgipru")) != EOF) {
|
|
|
1569e6 |
+ while ((c = getopt(argc, argv, "bdgipru")) != EOF) {
|
|
|
1569e6 |
switch (c) {
|
|
|
1569e6 |
+ case 'd':
|
|
|
1569e6 |
+ flags |= DEFAULTS_FLAG;
|
|
|
1569e6 |
+ break;
|
|
|
1569e6 |
case 'b':
|
|
|
1569e6 |
mask |= FS_DQ_BTIMER;
|
|
|
1569e6 |
break;
|
|
|
1569e6 |
@@ -474,23 +509,45 @@ timer_f(
|
|
|
1569e6 |
}
|
|
|
1569e6 |
}
|
|
|
1569e6 |
|
|
|
1569e6 |
- if (argc != optind + 1)
|
|
|
1569e6 |
+ /*
|
|
|
1569e6 |
+ * Older versions of the command did not accept -d|id|name,
|
|
|
1569e6 |
+ * so in that case we assume we're setting default timer,
|
|
|
1569e6 |
+ * and the last arg is the timer value.
|
|
|
1569e6 |
+ *
|
|
|
1569e6 |
+ * Otherwise, if the defaults flag is set, we expect 1 more arg for
|
|
|
1569e6 |
+ * timer value ; if not, 2 more args: 1 for value, one for id/name.
|
|
|
1569e6 |
+ */
|
|
|
1569e6 |
+ if (!(flags & DEFAULTS_FLAG) && (argc == optind + 1)) {
|
|
|
1569e6 |
+ value = cvttime(argv[optind++]);
|
|
|
1569e6 |
+ } else if (flags & DEFAULTS_FLAG) {
|
|
|
1569e6 |
+ if (argc != optind + 1)
|
|
|
1569e6 |
+ return command_usage(&timer_cmd);
|
|
|
1569e6 |
+ value = cvttime(argv[optind++]);
|
|
|
1569e6 |
+ } else if (argc == optind + 2) {
|
|
|
1569e6 |
+ value = cvttime(argv[optind++]);
|
|
|
1569e6 |
+ name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++];
|
|
|
1569e6 |
+ } else
|
|
|
1569e6 |
return command_usage(&timer_cmd);
|
|
|
1569e6 |
|
|
|
1569e6 |
- value = cvttime(argv[optind++]);
|
|
|
1569e6 |
|
|
|
1569e6 |
+ /* if none of -bir specified, set them all */
|
|
|
1569e6 |
if (!mask)
|
|
|
1569e6 |
mask = FS_DQ_TIMER_MASK;
|
|
|
1569e6 |
|
|
|
1569e6 |
if (!type) {
|
|
|
1569e6 |
type = XFS_USER_QUOTA;
|
|
|
1569e6 |
} else if (type != XFS_GROUP_QUOTA &&
|
|
|
1569e6 |
- type != XFS_PROJ_QUOTA &&
|
|
|
1569e6 |
- type != XFS_USER_QUOTA) {
|
|
|
1569e6 |
+ type != XFS_PROJ_QUOTA &&
|
|
|
1569e6 |
+ type != XFS_USER_QUOTA) {
|
|
|
1569e6 |
return command_usage(&timer_cmd);
|
|
|
1569e6 |
}
|
|
|
1569e6 |
|
|
|
1569e6 |
- set_timer(type, mask, fs_path->fs_name, value);
|
|
|
1569e6 |
+ if (name)
|
|
|
1569e6 |
+ id = id_from_string(name, type);
|
|
|
1569e6 |
+
|
|
|
1569e6 |
+ if (id >= 0)
|
|
|
1569e6 |
+ set_timer(id, type, mask, fs_path->fs_name, value);
|
|
|
1569e6 |
+
|
|
|
1569e6 |
return 0;
|
|
|
1569e6 |
}
|
|
|
1569e6 |
|
|
|
1569e6 |
@@ -616,9 +673,9 @@ edit_init(void)
|
|
|
1569e6 |
|
|
|
1569e6 |
timer_cmd.name = "timer";
|
|
|
1569e6 |
timer_cmd.cfunc = timer_f;
|
|
|
1569e6 |
- timer_cmd.argmin = 2;
|
|
|
1569e6 |
+ timer_cmd.argmin = 1;
|
|
|
1569e6 |
timer_cmd.argmax = -1;
|
|
|
1569e6 |
- timer_cmd.args = _("[-bir] [-g|-p|-u] value");
|
|
|
1569e6 |
+ timer_cmd.args = _("[-bir] [-g|-p|-u] value [-d|id|name]");
|
|
|
1569e6 |
timer_cmd.oneline = _("set quota enforcement timeouts");
|
|
|
1569e6 |
timer_cmd.help = timer_help;
|
|
|
1569e6 |
timer_cmd.flags = CMD_FLAG_FOREIGN_OK;
|