From f6857d08880a4351780e1b95c92927aa871ae134 Mon Sep 17 00:00:00 2001 From: anserper Date: Fri, 23 Nov 2007 13:25:39 +0000 Subject: [PATCH] Branch HEAD b=13915 i=johann i=tianzy implementation of "lfs quota -t" and "lfs setquota -t" time format string --- lustre/doc/lfs.1 | 16 +++++++ lustre/doc/lfs.lyx | 33 +++++++++++++ lustre/tests/sanity-quota.sh | 30 +++++++++++- lustre/utils/lfs.c | 109 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 169 insertions(+), 19 deletions(-) diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index d8f4c76..d8455bb 100644 --- a/lustre/doc/lfs.1 +++ b/lustre/doc/lfs.1 @@ -30,8 +30,12 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the .B lfs setquota [-u|-g] \fB \fR .br +.B lfs setquota -t [-u|-g] +.br .B lfs quota [-o obd_uuid] [-u|-g] .br +.B lfs quota -t [-u|-g] +.br .B lfs check .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] To set filesystem quotas for users or groups. Limits are specific as blocks and inodes, see EXAMPLES .TP +.B setquota -t [-u|-g] +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] 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] +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 diff --git a/lustre/doc/lfs.lyx b/lustre/doc/lfs.lyx index a6f2ebb..d29e62e 100644 --- a/lustre/doc/lfs.lyx +++ b/lustre/doc/lfs.lyx @@ -144,6 +144,13 @@ setquota [-u|-g] \series bold lfs\InsetSpace ~ +setquota -t [-u|-g] +\end_layout + +\begin_layout Standard + +\series bold +lfs\InsetSpace ~ quota [-o obd_uuid] [-u|-g] \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 ~ diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 9e84a37..2747ea4 100644 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -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 diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 4f18d25..315cb7d 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -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); } -- 1.8.3.1