From 58811dd55434332d20142f49ac73165b3bffb9a6 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Thu, 10 Oct 2019 17:06:05 -0400 Subject: [PATCH] LU-12280 quota: add notify grace Add an option to get notify when the quota is over soft limit but prevents it from becoming the hard limit. Change-Id: I01ae1266c3683198b82af7bad119db280c1e3a07 Signed-off-by: Hongchao Zhang Reviewed-on: https://review.whamcloud.com/36017 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Wang Shilong Reviewed-by: Oleg Drokin --- lustre/doc/lfs-setquota.1 | 24 ++++--- lustre/include/uapi/linux/lustre/lustre_user.h | 5 ++ lustre/utils/lfs.c | 98 +++++++++++++++----------- 3 files changed, 76 insertions(+), 51 deletions(-) diff --git a/lustre/doc/lfs-setquota.1 b/lustre/doc/lfs-setquota.1 index 1bd6ca6..ffefa6a 100644 --- a/lustre/doc/lfs-setquota.1 +++ b/lustre/doc/lfs-setquota.1 @@ -62,14 +62,18 @@ greater than inode softlimit when it's being specified. .BR "lfs setquota -t " .TP Command sets the filesystem quota grace time for users, groups, or projects. \ -This is a global value that indicates the amount of time, in seconds, that the \ -soft quota limit can be exceeded before users are prevented from creating \ -new files or consuming more space. This is intended to allow users to exceed \ -the quota limit for a short time to complete their work, without having to \ -grant each user a larger hard quota limit. The soft quota limit is reset once \ -the user, group, or project reduces their space usage below the soft quota \ -limit. Grace time is specified in "XXwXXdXXhXXmXXs" format or as an integer \ -seconds value, and the maximum is 2^48 - 1 seconds. +This is a global value that can take two forms: an amount of time or the word \ +\'\fBnotify\fR'. Traditionally, this indicates the amount of time in seconds \ +that the soft quota limit can be exceeded before users are prevented from \ +creating new files or consuming more space. This is intended to allow users \ +to exceed the quota limit for a short time to complete their work without \ +having to grant each user a larger hard quota limit. The alternative value of \ +\'\fBnotify\fR' informs users with an '\fB*\fR' in the quota output that they \ +are nearing their hard quota limit but does not block new writes until the hard \ +quota limit is reached. The soft quota state is reset once the user, group, \ +or project reduces their space usage or file count below the soft quota limit. \ +Grace time is specified in "XXwXXdXXhXXmXXs" format or as an integer seconds \ +value. The maximum is 2^48 - 1 seconds. .TP .B -t Set quota grace times. @@ -83,10 +87,10 @@ Set grace time for group. .B -p Set grace time for project. .TP -.B -b|--block-grace <\fIblock-grace\fR> +.B -b|--block-grace 'notify'|<\fIblock-grace\fR> Specify grace time for block quota. .TP -.B -i|--inode-grace <\fIindoe-grace\fR> +.B -i|--inode-grace 'notify'|<\fIinode-grace\fR> Specify grace time for inode quota. .PP .BR "lfs setquota " {\fB-U|--default-usr|-G|--default-grp|-P|--default-prj\fR} diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index b893ba7..a1ec1b2 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -1216,6 +1216,11 @@ static inline __u64 lustre_stoqb(size_t space) #define LQUOTA_FLAG(t) (t >> LQUOTA_GRACE_BITS) #define LQUOTA_GRACE_FLAG(t, f) ((__u64)t | (__u64)f << LQUOTA_GRACE_BITS) +/* special grace time, only notify the user when its quota is over soft limit + * but doesn't block new writes until the hard limit is reached. */ +#define NOTIFY_GRACE "notify" +#define NOTIFY_GRACE_TIME LQUOTA_GRACE_MASK + /* different quota flags */ /* the default quota flag, the corresponding quota ID will use the default diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 9a4a194..29cb88c 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -512,8 +512,8 @@ command_t cmdlist[] = { " [--inode-softlimit ]\n" " [--inode-hardlimit ] \n" " setquota [-t] <-u|--user|-g|--group|-p|--projid>\n" - " [--block-grace ]\n" - " [--inode-grace ] \n" + " [--block-grace 'notify'|]\n" + " [--inode-grace 'notify'|] \n" " setquota <-U|-G|-P>\n" " -b -B \n" " -i -I \n" @@ -536,8 +536,11 @@ command_t cmdlist[] = { " Quota space rebalancing process will stop when this mininum\n" " value is reached. As a result, quota exceeded can be returned\n" " while many targets still have 1MB or 1K inodes of spare\n" - " quota space."}, - {"quota", lfs_quota, 0, "Display disk usage and limits.\n" + " quota space.\n\n" + " When setting the grace time, 'notify' can be used as grace to\n" + " be notified after the quota is over soft limit but prevents\n" + " the soft limit from becoming the hard limit."}, + {"quota", lfs_quota, 0, "Display disk usage and limits.\n" "usage: quota [-q] [-v] [-h] [-o |-i |-I " "]\n" " [<-u|-g|-p> ||||] \n" @@ -6493,28 +6496,41 @@ quota_type: } qctl.qc_type = qtype; break; - case 'b': - if ((dqi->dqi_bgrace = str2sec(optarg)) == ULONG_MAX) { - fprintf(stderr, "error: bad block-grace: %s\n", - optarg); - return CMD_HELP; - } - dqb->dqb_valid |= QIF_BTIME; - break; - case 'i': - if ((dqi->dqi_igrace = str2sec(optarg)) == ULONG_MAX) { - fprintf(stderr, "error: bad inode-grace: %s\n", - optarg); - return CMD_HELP; - } - dqb->dqb_valid |= QIF_ITIME; - break; - case 't': /* Yes, of course! */ - break; - default: /* getopt prints error message for us when opterr != 0 */ - return CMD_HELP; - } - } + case 'b': + if (strncmp(optarg, NOTIFY_GRACE, + strlen(NOTIFY_GRACE)) == 0) { + dqi->dqi_bgrace = NOTIFY_GRACE_TIME; + } else { + dqi->dqi_bgrace = str2sec(optarg); + if (dqi->dqi_bgrace >= NOTIFY_GRACE_TIME) { + fprintf(stderr, "error: bad " + "block-grace: %s\n", optarg); + return CMD_HELP; + } + } + dqb->dqb_valid |= QIF_BTIME; + break; + case 'i': + if (strncmp(optarg, NOTIFY_GRACE, + strlen(NOTIFY_GRACE)) == 0) { + dqi->dqi_igrace = NOTIFY_GRACE_TIME; + } else { + dqi->dqi_igrace = str2sec(optarg); + if (dqi->dqi_igrace >= NOTIFY_GRACE_TIME) { + fprintf(stderr, "error: bad " + "inode-grace: %s\n", optarg); + return CMD_HELP; + } + } + dqb->dqb_valid |= QIF_ITIME; + break; + case 't': /* Yes, of course! */ + break; + /* getopt prints error message for us when opterr != 0 */ + default: + return CMD_HELP; + } + } if (qctl.qc_type == ALLQUOTA) { fprintf(stderr, "error: neither -u, -g nor -p specified\n"); @@ -6526,12 +6542,6 @@ quota_type: return CMD_HELP; } - if ((dqb->dqb_valid | QIF_BTIME && dqi->dqi_bgrace >= UINT_MAX) || - (dqb->dqb_valid | QIF_ITIME && dqi->dqi_igrace >= UINT_MAX)) { - fprintf(stderr, "error: grace time is too large\n"); - return CMD_HELP; - } - mnt = argv[optind]; rc = llapi_quotactl(mnt, &qctl); if (rc) { @@ -7003,17 +7013,23 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int type, else printf(" %7s %7s %7s %7s", "-", "-", "-", "-"); printf("\n"); + } else if (qctl->qc_cmd == LUSTRE_Q_GETINFO || + qctl->qc_cmd == Q_GETOINFO) { + char bgtimebuf[40]; + char igtimebuf[40]; - } else if (qctl->qc_cmd == LUSTRE_Q_GETINFO || - qctl->qc_cmd == Q_GETOINFO) { - char bgtimebuf[40]; - char igtimebuf[40]; + if (qctl->qc_dqinfo.dqi_bgrace == NOTIFY_GRACE_TIME) + strncpy(bgtimebuf, NOTIFY_GRACE, 40); + else + sec2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf, rc); + if (qctl->qc_dqinfo.dqi_igrace == NOTIFY_GRACE_TIME) + strncpy(igtimebuf, NOTIFY_GRACE, 40); + else + sec2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf, rc); - sec2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf, rc); - sec2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf, rc); - printf("Block grace time: %s; Inode grace time: %s\n", - bgtimebuf, igtimebuf); - } + printf("Block grace time: %s; Inode grace time: %s\n", + bgtimebuf, igtimebuf); + } } static int print_obd_quota(char *mnt, struct if_quotactl *qctl, int is_mdt, -- 1.8.3.1