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 [-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 [-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]
 .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  [-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 [-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
 .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 -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 -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
 .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 ~
 
 \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
 
 quota [-o obd_uuid] [-u|-g] <name> <filesystem>
 \end_layout
 
@@ -528,6 +535,32 @@ quota
 \end_layout
 
 \begin_layout Description
 \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 ~
 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
 
        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) ==="
 
        # 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
 # 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 ..."
        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
                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)
 
         }                                                               \
 } 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;
 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;
 
                 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];
         }
 
         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;
         }
                 strcpy(buf, "none");
                 return;
         }
-        grace2str(seconds - now, buf);
+        sec2str(seconds - now, buf);
 }
 
 static void print_quota_title(char *name, struct if_quotactl *qctl)
 }
 
 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];
 
                 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);
         }
                 printf("Block grace time: %s; Inode grace time: %s\n",
                        bgtimebuf, igtimebuf);
         }