Blame SOURCES/xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch

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