Whamcloud - gitweb
Branch HEAD
authoranserper <anserper>
Fri, 23 Nov 2007 13:25:39 +0000 (13:25 +0000)
committeranserper <anserper>
Fri, 23 Nov 2007 13:25:39 +0000 (13:25 +0000)
b=13915
i=johann
i=tianzy

implementation of "lfs quota -t" and "lfs setquota -t" time format string

lustre/doc/lfs.1
lustre/doc/lfs.lyx
lustre/tests/sanity-quota.sh
lustre/utils/lfs.c

index d8f4c76..d8455bb 100644 (file)
@@ -30,8 +30,12 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the
 .B lfs setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> 
              \fB<inode-softlimit> <inode-hardlimit> <filesystem>\fR
 .br
+.B lfs setquota -t [-u|-g] <block-grace> <inode-grace> <filesystem>
+.br
 .B lfs quota [-o obd_uuid] [-u|-g] <name> <filesystem>
 .br
+.B lfs quota -t [-u|-g] <filesystem>
+.br
 .B lfs check <mds| osts| servers>
 .br
 .B lfs df [-i] [-h] [path]
@@ -70,9 +74,15 @@ To turn filesystem quotas off.  Options specify quota for users (-u) groups (-g)
 .B setquota  [-u|-g] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>
 To set filesystem quotas for users or groups. Limits are specific as blocks and inodes, see EXAMPLES
 .TP
+.B setquota -t [-u|-g] <block-grace> <inode-grace> <filesystem>
+To set filesystem quota grace times for users or groups. Grace time is specified in "XXwXXdXXhXXmXXs" format or as an integer seconds value, see EXAMPLES
+.TP
 .B quota [-o obd_uuid] [-u|-g] <name> <filesystem>
 To display disk usage and limits, either for the full filesystem, or for objects on a specific obd. A user or group name must be specified.
 .TP
+.B quota -t [-u|-g] <filesystem>
+To display block and inode grace times for user (-u) or group (-g) quotas
+.TP
 .B check 
 Display the status of MDS or OSTs (as specified in the command) or all the servers (MDS and OSTs)
 .TP
@@ -122,9 +132,15 @@ Turn quotas of user and group off
 .B $ lfs setquota -u bob 0 1000000 0 10000 /mnt/lustre
 Set quotas of user `bob': 1GB block quota and 10,000 file quota
 .TP
+.B $ lfs setquota -t -u 1000 1w4d /mnt/lustre
+Set grace times for user quotas: 1000 seconds for block quotas, 1 week and 4 days for inode quotas
+.TP
 .B $ lfs quota -u bob /mnt/lustre
 List quotas of user `bob'
 .TP
+.B $ lfs quota -t -u /mnt/lustre
+Show grace times for user quotas on /mnt/lustre
+.TP
 .B $ lfs check servers 
 Check the status of all servers (MDT, OST)
 .TP
index a6f2ebb..d29e62e 100644 (file)
@@ -144,6 +144,13 @@ setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> <inode-softlimit>
 
 \series bold
 lfs\InsetSpace ~
+setquota -t [-u|-g] <block-grace> <inode-grace> <filesystem>
+\end_layout
+
+\begin_layout Standard
+
+\series bold
+lfs\InsetSpace ~
 quota [-o obd_uuid] [-u|-g] <name> <filesystem>
 \end_layout
 
@@ -528,6 +535,32 @@ quota
 \end_layout
 
 \begin_layout Description
+Set\InsetSpace ~
+grace\InsetSpace ~
+times\InsetSpace ~
+for\InsetSpace ~
+user\InsetSpace ~
+quotas:\InsetSpace ~
+1000\InsetSpace ~
+seconds\InsetSpace ~
+for\InsetSpace ~
+block\InsetSpace ~
+quotas,\InsetSpace ~
+1\InsetSpace ~
+week\InsetSpace ~
+and\InsetSpace ~
+4\InsetSpace ~
+days\InsetSpace ~
+for\InsetSpace ~
+inode\InsetSpace ~
+quotas
+\end_layout
+
+\begin_layout LyX-Code
+   $lfs setquota -t -u 1000 1w4d /mnt/lustre
+\end_layout
+
+\begin_layout Description
 List\InsetSpace ~
 quotas\InsetSpace ~
 of\InsetSpace ~
index 9e84a37..2747ea4 100644 (file)
@@ -476,13 +476,39 @@ test_4() {
 
        test_file_soft $TESTFILE $LIMIT $GRACE
        $LFS setquota -g $TSTUSR 0 0 0 0 $MOUNT
-       
+
        # cleanup
        $LFS setquota -t -u $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT
        $LFS setquota -t -g $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT
 }
 run_test 4 "File soft limit (start timer, timer goes off, stop timer) ==="
 
+test_4a() {
+        GR_STR1="1w3d"
+        GR_STR2="1000s"
+        GR_STR3="5s"
+        GR_STR4="1w2d3h4m5s"
+        GR_STR5="5c"
+        GR_STR6="1111111111111111"
+
+        # test of valid grace strings handling
+        echo "  Valid grace strings test"
+        $LFS setquota -t -u $GR_STR1 $GR_STR2 $MOUNT
+        $LFS quota -u -t $MOUNT | grep "Block grace time: $GR_STR1"
+        $LFS setquota -t -g $GR_STR3 $GR_STR4 $MOUNT
+        $LFS quota -g -t $MOUNT | grep "Inode grace time: $GR_STR4"
+
+        # test of invalid grace strings handling
+        echo "  Invalid grace strings test"
+        ! $LFS setquota -t -u $GR_STR4 $GR_STR5 $MOUNT
+        ! $LFS setquota -t -g $GR_STR4 $GR_STR6 $MOUNT
+
+        # cleanup
+        $LFS setquota -t -u $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT
+        $LFS setquota -t -g $MAX_DQ_TIME $MAX_IQ_TIME $MOUNT
+}
+run_test 4a "Grace time strings handling ==="
+
 # chown & chgrp (chown & chgrp successfully even out of block/file quota)
 test_5() {
        BLIMIT=$(( $BUNIT_SZ * $((OSTCOUNT + 1)) * 10)) # 10 bunits on each server
@@ -500,7 +526,7 @@ test_5() {
        dd if=/dev/zero of=$TSTDIR/quota_tst50_1 bs=$BLK_SZ count=$((BLIMIT+1)) || error "write failure, expect success"
 
        echo "  Chown files to $TSTUSR.$TSTUSR ..."
-       for i in `seq 0 ILIMIT`; do
+       for i in `seq 0 $ILIMIT`; do
                chown $TSTUSR.$TSTUSR $TSTDIR/quota_tst50_$i || \
                        error "chown failure, but expect success"
        done
index 4f18d25..315cb7d 100644 (file)
@@ -1268,6 +1268,65 @@ do {                                                                    \
         }                                                               \
 } while (0)
 
+#define ADD_OVERFLOW(a,b) ((a + b) < a) ? (a = ULONG_MAX) : (a = a + b)
+
+/* Convert format time string "XXwXXdXXhXXmXXs" into seconds value
+ * returns the value or ULONG_MAX on integer overflow or incorrect format
+ * Notes:
+ *        1. the order of specifiers is arbitrary (may be: 5w3s or 3s5w)
+ *        2. specifiers may be encountered multiple times (2s3s is 5 seconds)
+ *        3. empty integer value is interpreted as 0
+ */
+static unsigned long str2sec(const char* timestr) {
+        const char spec[] = "smhdw";
+        const unsigned long mult[] = {1, 60, 60*60, 24*60*60, 7*24*60*60};
+        unsigned long val = 0;
+        char *tail;
+
+        if (strpbrk(timestr, spec) == NULL) {
+                /* no specifiers inside the time string,
+                   should treat it as an integer value */
+                val = strtoul(timestr, &tail, 10);
+                return *tail ? ULONG_MAX : val;
+        }
+
+        /* format string is XXwXXdXXhXXmXXs */
+        while (*timestr) {
+                unsigned long v;
+                int ind;
+                char* ptr;
+
+                v = strtoul(timestr, &tail, 10);
+                if (v == ULONG_MAX || *tail == '\0')
+                        /* value too large (ULONG_MAX or more) 
+                           or missing specifier */
+                        goto error;
+
+                ptr = strchr(spec, *tail);
+                if (ptr == NULL)
+                        /* unknown specifier */
+                        goto error;
+
+                ind = ptr - spec;
+
+                /* check if product will overflow the type */
+                if (!(v < ULONG_MAX / mult[ind]))
+                        goto error;
+
+                ADD_OVERFLOW(val, mult[ind] * v);
+                if (val == ULONG_MAX)
+                        goto error;
+
+                timestr = tail + 1;
+        }
+
+        return val;
+
+error:
+        return ULONG_MAX;
+}
+
 int lfs_setquota(int argc, char **argv)
 {
         int c;
@@ -1333,8 +1392,14 @@ int lfs_setquota(int argc, char **argv)
                 if (optind + 3 != argc)
                         return CMD_HELP;
 
-                ARG2INT(dqi->dqi_bgrace, argv[optind++], "block-grace");
-                ARG2INT(dqi->dqi_igrace, argv[optind++], "inode-grace");
+                if ((dqi->dqi_bgrace = str2sec(argv[optind++])) == ULONG_MAX) {
+                        fprintf(stderr, "error: bad %s: %s\n", "block-grace", argv[optind - 1]);
+                        return CMD_HELP;
+                }
+                if ((dqi->dqi_igrace = str2sec(argv[optind++])) == ULONG_MAX) {
+                        fprintf(stderr, "error: bad %s: %s\n", "inode-grace", argv[optind - 1]);
+                        return CMD_HELP;
+                }
         }
 
         mnt = argv[optind];
@@ -1361,19 +1426,29 @@ static inline char *type2name(int check_type)
 }
 
 
-static void grace2str(time_t seconds,char *buf)
+/* Converts seconds value into format string
+ * result is returned in buf
+ * Notes:
+ *        1. result is in descenting order: 1w2d3h4m5s
+ *        2. zero fields are not filled (except for p. 3): 5d1s
+ *        3. zero seconds value is presented as "0s"
+ */
+static void sec2str(time_t seconds, char *buf)
 {
-        uint minutes, hours, days;
-
-        minutes = (seconds + 30) / 60;
-        hours = minutes / 60;
-        minutes %= 60;
-        days = hours / 24;
-        hours %= 24;
-        if (days >= 2)
-                snprintf(buf, 40, "%ddays", days);
-        else
-                snprintf(buf, 40, "%02d:%02d", hours + days * 24, minutes);
+        const char spec[] = "smhdw";
+        const unsigned long mult[] = {1, 60, 60*60, 24*60*60, 7*24*60*60};
+        unsigned long c;
+        char* tail = buf;
+        int i;
+
+        for (i = sizeof(mult) / sizeof(mult[0]) - 1 ; i >= 0; i--) {
+                c = seconds / mult[i];
+
+                if (c > 0 || (i == 0 && buf == tail))
+                        tail += snprintf(tail, 40-(tail-buf), "%lu%c", c, spec[i]);
+
+                seconds %= mult[i];
+        }
 }
 
 
@@ -1387,7 +1462,7 @@ static void diff2str(time_t seconds, char *buf, time_t now)
                 strcpy(buf, "none");
                 return;
         }
-        grace2str(seconds - now, buf);
+        sec2str(seconds - now, buf);
 }
 
 static void print_quota_title(char *name, struct if_quotactl *qctl)
@@ -1474,8 +1549,8 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
                 char bgtimebuf[40];
                 char igtimebuf[40];
 
-                grace2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf);
-                grace2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf);
+                sec2str(qctl->qc_dqinfo.dqi_bgrace, bgtimebuf);
+                sec2str(qctl->qc_dqinfo.dqi_igrace, igtimebuf);
                 printf("Block grace time: %s; Inode grace time: %s\n",
                        bgtimebuf, igtimebuf);
         }