Whamcloud - gitweb
LU-12280 quota: add notify grace 17/36017/8
authorHongchao Zhang <hongchao@whamcloud.com>
Thu, 10 Oct 2019 21:06:05 +0000 (17:06 -0400)
committerOleg Drokin <green@whamcloud.com>
Thu, 20 Feb 2020 07:14:48 +0000 (07:14 +0000)
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 <hongchao@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/36017
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lfs-setquota.1
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/utils/lfs.c

index 1bd6ca6..ffefa6a 100644 (file)
@@ -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}
index b893ba7..a1ec1b2 100644 (file)
@@ -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
index 9a4a194..29cb88c 100644 (file)
@@ -512,8 +512,8 @@ command_t cmdlist[] = {
          "                [--inode-softlimit <inode-softlimit>]\n"
          "                [--inode-hardlimit <inode-hardlimit>] <filesystem>\n"
         "       setquota [-t] <-u|--user|-g|--group|-p|--projid>\n"
-         "                [--block-grace <block-grace>]\n"
-         "                [--inode-grace <inode-grace>] <filesystem>\n"
+        "                [--block-grace 'notify'|<block-grace>]\n"
+        "                [--inode-grace 'notify'|<inode-grace>] <filesystem>\n"
         "       setquota <-U|-G|-P>\n"
         "                -b <block-softlimit> -B <block-hardlimit>\n"
         "                -i <inode-softlimit> -I <inode-hardlimit> <filesystem>\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 <obd_uuid>|-i <mdt_idx>|-I "
                       "<ost_idx>]\n"
         "             [<-u|-g|-p> <uname>|<uid>|<gname>|<gid>|<projid>] <filesystem>\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,