diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index 7f241096388ed069d0960b3df779cfcbac306202..74847b96c3d45a515fcd49adf8650276e24e7a29 100644 --- a/lustre/doc/lfs.1 +++ b/lustre/doc/lfs.1 @@ -33,12 +33,28 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the .br .B lfs quotainv [-ug] <filesystem> .br -.B lfs setquota [-u|-g] <username|groupname> <block-softlimit> - \fB<block-hardlimit> <inode-softlimit> <inode-hardlimit> +.B lfs setquota [-u|--user|-g|--group] <username|groupname> + \fB[--block-softlimit <block-softlimit>] + \fB[--block-hardlimit <block-hardlimit>] + \fB[--inode-softlimit <inode-softlimit>] + \fB[--inode-hardlimit <inode-hardlimit>] \fB<filesystem>\fR .br -.B lfs setquota -t [-u|-g] <block-grace> <inode-grace> <filesystem> +.B lfs setquota [-u|--user|-g|--group] <username|groupname> + \fB[-b <block-softlimit>] [-B <block-hardlimit>] + \fB[-i <inode-softlimit>] [-I <inode-hardlimit>] + \fB<filesystem>\fR +.br +.B lfs setquota -t [-u|-g] + \fB[--block-grace <block-grace>] + \fB[--inode-grace <inode-grace>] + \fB<filesystem>\fR +.br +.B lfs setquota -t [-u|-g] + \fB[-b <block-grace>] [-i <inode-grace>] + \fB<filesystem>\fR .br + .B lfs quota [-o obd_uuid] [-u|-g] <username|groupname> <filesystem> .br .B lfs quota -t [-u|-g] <filesystem> @@ -83,10 +99,10 @@ To turn filesystem quotas off. Options specify quota for users (-u) groups (-g) .B quotainv [-ug] <filesystem> Clear quota files, all of their quota entries, for (-u) users or (-g) groups; after quotainv one must use quotacheck before using quotas. USE THIS COMMAND WITH EXTREME CARE, ITS RESULTS CANNOT BE UNDONE. .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 +.B setquota [-u|-g] <name> [--block-softlimit <block-softlimit>] [--block-hardlimit <block-hardlimit>] [--inode-softlimit <inode-softlimit>] [--inode-hardlimit <inode-hardlimit>] <filesystem> +To set filesystem quotas for users or groups. Limits can be specified with -b, -k, -m, -g, -t, -p suffixes which specify units of 1, 2^10, 2^20, 2^30, 2^40 and 2^50 accordingly. Block limits unit is kilobyte (1024) by default and block limits are always kilobyte-grained (even if specified in bytes), see EXAMPLES .TP -.B setquota -t [-u|-g] <block-grace> <inode-grace> <filesystem> +.B setquota -t [-u|-g] [--block-grace <block-grace>] [--inode-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] <username|groupname> <filesystem> @@ -103,7 +119,7 @@ Quit the interactive lfs session .SH EXAMPLES .TP .B $ lfs setstripe -s 128k -c 2 /mnt/lustre/file1 -This creats a file striped on two OSTs with 128kB on each stripe. +This creates a file striped on two OSTs with 128kB on each stripe. .TP .B $ lfs setstripe -d /mnt/lustre/dir This deletes a default stripe pattern on dir. New files will use the default striping pattern created therein. @@ -144,10 +160,10 @@ Turn quotas of user and group on .B $ lfs quotaoff -ug /mnt/lustre Turn quotas of user and group off .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 +.B $ lfs setquota -u bob --block-softlimit 2000000 --block-hardlimit 1000000 /mnt/lustre +Set quotas of user `bob': 1GB block quota hardlimit and 2 GB block quota softlimit .TP -.B $ lfs setquota -t -u 1000 1w4d /mnt/lustre +.B $ lfs setquota -t -u --block-grace 1000 --inode-grace 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 diff --git a/lustre/include/lustre/liblustreapi.h b/lustre/include/lustre/liblustreapi.h index 4d6c802ae3d102b3fc46e6e118b8d668a0b98e52..544de1df1d3a041e466c4654810e28927d8b3908 100644 --- a/lustre/include/lustre/liblustreapi.h +++ b/lustre/include/lustre/liblustreapi.h @@ -102,7 +102,7 @@ extern int llapi_catinfo(char *dir, char *keyword, char *node_name); extern int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count); extern int llapi_is_lustre_mnttype(const char *type); extern int parse_size(char *optarg, unsigned long long *size, - unsigned long long *size_units); + unsigned long long *size_units, int bytes_spec); struct mntent; #define HAVE_LLAPI_IS_LUSTRE_MNT extern int llapi_is_lustre_mnt(struct mntent *mnt); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index e62a20f67c80bf6f4902b32576f2dacad134f901..0704d89ae68b1a258cd99d865c1454282476ba95 100644 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -143,8 +143,9 @@ test_0() { $LFS quotaoff -ug $DIR $LFS quotacheck -ug $DIR - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR + lctl set_param debug="+quota" do_facet mds "lctl set_param debug=+quota" for num in `seq $OSTCOUNT`; do @@ -164,7 +165,7 @@ test_1_sub() { # test for user log " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR sleep 3 $SHOW_QUOTA_USER @@ -189,12 +190,12 @@ test_1_sub() { [ $OST0_QUOTA_USED -ne 0 ] && \ ($SHOW_QUOTA_USER; error "quota deleted isn't released") $SHOW_QUOTA_USER - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR # test for group log "--------------------------------------" log " Group quota (limit: $LIMIT kbytes)" - $LFS setquota -g $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR sleep 3 $SHOW_QUOTA_GROUP TESTFILE="$DIR/$tdir/$tfile-1" @@ -220,7 +221,7 @@ test_1_sub() { [ $OST0_QUOTA_USED -ne 0 ] && \ ($SHOW_QUOTA_USER; error "quota deleted isn't released") $SHOW_QUOTA_GROUP - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR # clear group limit + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } # block hard limit (normal use and out of quota) @@ -253,7 +254,7 @@ test_2_sub() { # test for user log " User quota (limit: $LIMIT files)" - $LFS setquota -u $TSTUSR 0 0 0 $LIMIT $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR sleep 3 $SHOW_QUOTA_USER @@ -275,12 +276,12 @@ test_2_sub() { [ $MDS_QUOTA_USED -ne 0 ] && \ ($SHOW_QUOTA_USER; error "quota deleted isn't released") $SHOW_QUOTA_USER - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR # test for group log "--------------------------------------" log " Group quota (limit: $LIMIT FILE)" - $LFS setquota -g $TSTUSR 0 0 0 $LIMIT $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $LIMIT $DIR sleep 3 $SHOW_QUOTA_GROUP TESTFILE=$DIR/$tdir/$tfile-1 @@ -303,7 +304,7 @@ test_2_sub() { [ $MDS_QUOTA_USED -ne 0 ] && \ ($SHOW_QUOTA_USER; error "quota deleted isn't released") $SHOW_QUOTA_GROUP - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR # clear user limit + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } # file hard limit (normal use and out of quota) @@ -402,11 +403,11 @@ test_3() { $LFS setstripe $TESTFILE -c 1 chown $TSTUSR.$TSTUSR $TESTFILE - $LFS setquota -t -u $GRACE $MAX_IQ_TIME $DIR - $LFS setquota -u $TSTUSR $LIMIT 0 0 0 $DIR + $LFS setquota -t -u --block-grace $GRACE --inode-grace $MAX_IQ_TIME $DIR + $LFS setquota -u $TSTUSR -b $LIMIT -B 0 -i 0 -I 0 $DIR test_block_soft $TESTFILE $GRACE - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR echo " Group quota (soft limit: $LIMIT kbytes grace: $GRACE seconds)" TESTFILE=$DIR/$tdir/$tfile-1 @@ -414,11 +415,11 @@ test_3() { $LFS setstripe $TESTFILE -c 1 chown $TSTUSR.$TSTUSR $TESTFILE - $LFS setquota -t -g $GRACE $MAX_IQ_TIME $DIR - $LFS setquota -g $TSTUSR $LIMIT 0 0 0 $DIR + $LFS setquota -t -g --block-grace $GRACE --inode-grace $MAX_IQ_TIME $DIR + $LFS setquota -g $TSTUSR -b $LIMIT -B 0 -i 0 -I 0 $DIR test_block_soft $TESTFILE $GRACE - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } run_test 3 "Block soft limit (start timer, timer goes off, stop timer) ===" @@ -482,25 +483,25 @@ test_4a() { # was test_4 GRACE=5 echo " User quota (soft limit: $LIMIT files grace: $GRACE seconds)" - $LFS setquota -t -u $MAX_DQ_TIME $GRACE $DIR - $LFS setquota -u $TSTUSR 0 0 $LIMIT 0 $DIR + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace $GRACE $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR $SHOW_QUOTA_USER test_file_soft $TESTFILE $LIMIT $GRACE - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR echo " Group quota (soft limit: $LIMIT files grace: $GRACE seconds)" - $LFS setquota -t -g $MAX_DQ_TIME $GRACE $DIR - $LFS setquota -g $TSTUSR 0 0 $LIMIT 0 $DIR + $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace $GRACE $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i $LIMIT -I 0 $DIR $SHOW_QUOTA_GROUP TESTFILE=$DIR/$tdir/$tfile-1 test_file_soft $TESTFILE $LIMIT $GRACE - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR # cleanup - $LFS setquota -t -u $MAX_DQ_TIME $MAX_IQ_TIME $DIR - $LFS setquota -t -g $MAX_DQ_TIME $MAX_IQ_TIME $DIR + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR + $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR } run_test 4a "File soft limit (start timer, timer goes off, stop timer) ===" @@ -516,19 +517,19 @@ test_4b() { # was test_4a # test of valid grace strings handling echo " Valid grace strings test" - $LFS setquota -t -u $GR_STR1 $GR_STR2 $DIR + $LFS setquota -t -u --block-grace $GR_STR1 --inode-grace $GR_STR2 $DIR $LFS quota -u -t $DIR | grep "Block grace time: $GR_STR1" - $LFS setquota -t -g $GR_STR3 $GR_STR4 $DIR + $LFS setquota -t -g --block-grace $GR_STR3 --inode-grace $GR_STR4 $DIR $LFS quota -g -t $DIR | 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 $DIR - ! $LFS setquota -t -g $GR_STR4 $GR_STR6 $DIR + ! $LFS setquota -t -u --block-grace $GR_STR4 --inode-grace $GR_STR5 $DIR + ! $LFS setquota -t -g --block-grace $GR_STR4 --inode-grace $GR_STR6 $DIR # cleanup - $LFS setquota -t -u $MAX_DQ_TIME $MAX_IQ_TIME $DIR - $LFS setquota -t -g $MAX_DQ_TIME $MAX_IQ_TIME $DIR + $LFS setquota -t -u --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR + $LFS setquota -t -g --block-grace $MAX_DQ_TIME --inode-grace $MAX_IQ_TIME $DIR } run_test 4b "Grace time strings handling ===" @@ -541,8 +542,8 @@ test_5() { wait_delete_completed echo " Set quota limit (0 $BLIMIT 0 $ILIMIT) for $TSTUSR.$TSTUSR" - $LFS setquota -u $TSTUSR 0 $BLIMIT 0 $ILIMIT $DIR - $LFS setquota -g $TSTUSR 0 $BLIMIT 0 $ILIMIT $DIR + $LFS setquota -u $TSTUSR -b 0 -B $BLIMIT -i 0 -I $ILIMIT $DIR + $LFS setquota -g $TSTUSR -b 0 -B $BLIMIT -i 0 -I $ILIMIT $DIR $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP @@ -561,8 +562,8 @@ test_5() { unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1)) sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } run_test 5 "Chown & chgrp successfully even out of block/file quota ===" @@ -583,8 +584,8 @@ test_6() { FILEB="$DIR/$tdir/$tfile-0_b" echo " Set block limit $LIMIT kbytes to $TSTUSR.$TSTUSR" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR - $LFS setquota -g $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP @@ -628,8 +629,8 @@ test_6() { rm -f $FILEA sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR return 0 } run_test 6 "Block quota acquire & release =========" @@ -646,7 +647,7 @@ test_7() LIMIT=$(( $BUNIT_SZ * $(($OSTCOUNT + 1)) )) TESTFILE="$DIR/$tdir/$tfile-0" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $LFS setstripe $TESTFILE -c 1 chown $TSTUSR.$TSTUSR $TESTFILE @@ -683,7 +684,7 @@ test_7() echo " limits on $OST0_UUID = $OST0_LIMIT" # cleanup - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } run_test 7 "Quota recovery (only block limit) ======" @@ -699,9 +700,9 @@ test_8() { wait_delete_completed echo " Set enough high limit for user: $TSTUSR" - $LFS setquota -u $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR echo " Set enough high limit for group: $TSTUSR" - $LFS setquota -g $USER 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -g $USER -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR TGT=$DIR/$tdir/client.txt SRC=${SRC:-$DBENCH_LIB/client.txt} @@ -763,9 +764,9 @@ test_9() { echo " Set block limit $BLK_LIMIT kbytes to $TSTUSR.$TSTUSR" log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for user: $TSTUSR" - $LFS setquota -u $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for group: $TSTUSR" - $LFS setquota -g $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR echo " Set stripe" $LFS setstripe $TESTFILE -c 1 @@ -818,9 +819,9 @@ test_10() { FILE_LIMIT=1000000 log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for user: $TSTUSR" - $LFS setquota -u $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR log " Set enough high limit(block:$BLK_LIMIT; file: $FILE_LIMIT) for group: $TSTUSR" - $LFS setquota -g $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR + $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I $FILE_LIMIT $DIR echo " Set stripe" $LFS setstripe $TESTFILE -c 1 @@ -946,7 +947,7 @@ test_12() { wait_delete_completed echo " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $LFS setstripe $TESTFILE -i 0 -c 1 chown $TSTUSR.$TSTUSR $TESTFILE @@ -993,7 +994,7 @@ test_12() { rm -f $TESTFILE $TESTFILE2 sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } run_test 12 "test a deadlock between quota and journal ===" @@ -1007,7 +1008,7 @@ test_13() { TESTFILE="$DIR/$tdir/$tfile" echo " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $SHOW_QUOTA_USER $LFS setstripe $TESTFILE -i 0 -c 1 @@ -1057,7 +1058,7 @@ test_13() { rm -f $TESTFILE $TESTFILE.2 sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } run_test 13 "test multiple clients write block quota ===" @@ -1093,7 +1094,7 @@ test_14a() { # was test_14 b=12223 -- setting quota on root mkdir -p $DIR/$tdir # out of root's file and block quota - $LFS setquota -u root 10 10 10 10 $DIR + $LFS setquota -u root -b 10 -B 10 -i 10 -I 10 $DIR createmany -m ${TESTFILE} 20 || \ error "unexpected: user(root) create files failly!" dd if=/dev/zero of=$TESTFILE bs=4k count=4096 || \ @@ -1109,7 +1110,7 @@ test_14a() { # was test_14 b=12223 -- setting quota on root # do the check dmesg | tail | grep "\-122" |grep llog_obd_origin_add && error "err -122 not found in dmesg" - $LFS setquota -u root 0 0 0 0 $DIR + $LFS setquota -u root -b 0 -B 0 -i 0 -I 0 $DIR #check_if_quota_zero u root # clean @@ -1150,7 +1151,7 @@ test_14b() { # was test_14a $LFS quotacheck -ug $DIR for i in `seq 1 30`; do - $LFS setquota -u quota15_$i $i $i $i $i $DIR || error "lfs setquota failed" + $LFS setquota -u quota15_$i -b $i -B $i -i $i -I $i $DIR done $LFS quotaoff -ug $DIR @@ -1162,7 +1163,7 @@ test_14b() { # was test_14a # the format is "mntpnt curspace[*] bsoftlimit bhardlimit [time] curinodes[*] isoftlimit ihardlimit" ($LFS quota -u quota15_$i $DIR | grep -E '^ *'$DIR' *[0-9]+\** *'$i' *'$i' *[0-9]+\** *'$i' *'$i) \ || error "lfs quota output is unexpected" - $LFS setquota -u quota15_$i 0 0 0 0 $DIR || error "ifs setquota clear failed" + $LFS setquota -u quota15_$i -b 0 -B 0 -i 0 -I 0 $DIR done } run_test 14b "setting 30 quota entries in quota v1 file before conversion ===" @@ -1174,24 +1175,24 @@ test_15(){ wait_delete_completed # test for user - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR || error "failed setting user quota limit $LIMIT" + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR TOTAL_LIMIT="`$LFS quota -u $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`" [ $TOTAL_LIMIT -eq $LIMIT ] || error " (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!" echo " (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!" - $LFS setquota -u $TSTUSR 0 0 0 0 $DIR || error "failed removing user quota limit" + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR # test for group - $LFS setquota -g $TSTUSR 0 $LIMIT 0 0 $DIR || error "failed setting group quota limit $LIMIT" + $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR TOTAL_LIMIT="`$LFS quota -g $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`" [ $TOTAL_LIMIT -eq $LIMIT ] || error " (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!" echo " (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!" - $LFS setquota -g $TSTUSR 0 0 0 0 $DIR || error "failed removing group quota limit" + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR $LFS quotaoff -ug $DIR quota_set_version 1 $LFS quotacheck -ug $DIR || error "quotacheck failed" echo "Testing that >4GB quota limits fail on volume with quota v1" - ! $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + ! $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR } run_test 15 "set block quota more than 4T ===" @@ -1205,10 +1206,10 @@ test_16_tub() { echo " User quota (limit: $LIMIT kbytes)" if [ $1 == "u" ]; then - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $SHOW_QUOTA_USER else - $LFS setquota -g $TSTUSR 0 $LIMIT 0 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR $SHOW_QUOTA_GROUP fi @@ -1234,7 +1235,7 @@ test_16_tub() { rm -f $TESTFILE sync; sleep 3; sync; - $LFS setquota -$1 $TSTUSR 0 0 0 0 $DIR + $LFS setquota -$1 $TSTUSR -b 0 -B 0 -i 0 -I 0 $DIR } # test without adjusting qunit @@ -1273,9 +1274,9 @@ test_17() { BLK_LIMIT=$((100 * 1024)) # 100M log " Set enough high limit(block:$BLK_LIMIT) for user: $TSTUSR" - $LFS setquota -u $TSTUSR 0 $BLK_LIMIT 0 0 $DIR + $LFS setquota -u $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I 0 $DIR log " Set enough high limit(block:$BLK_LIMIT) for group: $TSTUSR" - $LFS setquota -g $TSTUSR 0 $BLK_LIMIT 0 0 $DIR + $LFS setquota -g $TSTUSR -b 0 -B $BLK_LIMIT -i 0 -I 0 $DIR touch $TESTFILE chown $TSTUSR.$TSTUSR $TESTFILE @@ -1326,7 +1327,7 @@ test_18() { set_blk_unitsz 1024 log " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $MOUNT + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $MOUNT $SHOW_QUOTA_USER $LFS setstripe $TESTFILE -i 0 -c 1 @@ -1363,7 +1364,7 @@ test_18() { rm -f $TESTFILE sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $MOUNT # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $MOUNT set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) @@ -1382,7 +1383,7 @@ test_18a() { set_blk_unitsz 1024 log " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $MOUNT + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $MOUNT $SHOW_QUOTA_USER $LFS setstripe $TESTFILE -i 0 -c 1 @@ -1420,7 +1421,7 @@ test_18a() { rm -f $TESTFILE sync; sleep 3; sync; - $LFS setquota -u $TSTUSR 0 0 0 0 $MOUNT # clear user limit + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $MOUNT set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) @@ -1444,10 +1445,10 @@ test_19() { chown $TSTUSR.$TSTUSR $TESTFILE echo " User quota (limit: $LIMIT kbytes)" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $MOUNT + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $MOUNT $SHOW_QUOTA_USER echo " Updating quota limits" - $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $MOUNT + $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $MOUNT $SHOW_QUOTA_USER $RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ count=1028 || true @@ -1461,7 +1462,7 @@ test_19() { # cleanup rm -f $TESTFILE - $LFS setquota -u $TSTUSR 0 0 0 0 $MOUNT + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 $MOUNT set_blk_unitsz $((128 * 1024)) set_blk_tunesz $((128 * 1024 / 2)) @@ -1469,6 +1470,29 @@ test_19() { } run_test 19 "test if administrative limits updates do not zero operational limits (14790) ===" +test_20() +{ + LSTR=(1t 2g 3m 4k) # limits strings + LVAL=($[1*1024*1024*1024] $[2*1024*1024] $[3*1024*1024] $[4*1024]) # limits values + + $LFS setquota -u $TSTUSR --block-softlimit ${LSTR[0]} \ + $MOUNT || error "could not set quota limits" + + $LFS setquota -u $TSTUSR --block-hardlimit ${LSTR[1]} \ + --inode-softlimit ${LSTR[2]} \ + --inode-hardlimit ${LSTR[3]} \ + $MOUNT || error "could not set quota limits" + + ($LFS quota -u $TSTUSR $MOUNT | \ + grep -E '^ *'$MOUNT' *[0-9]+\** *'${LVAL[0]}' *'${LVAL[1]}' *[0-9]+\** *'${LVAL[2]}' *'${LVAL[3]}) \ + || error "lfs quota output is unexpected" + + $LFS setquota -u $TSTUSR -b 0 -B 0 -i 0 -I 0 \ + $MOUNT || error "could not reset quota limits" + +} +run_test 20 "test if setquota specifiers work properly (15754)" + # turn off quota test_99() { diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 92eefafd22656e9a317776c270c7bbdcde4d5a5c..a1a5268fb9a9fa52a75f836252b270a50a80285e 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -133,7 +133,19 @@ command_t cmdlist[] = { "usage: quotaoff [ -ug ] <filesystem>"}, {"setquota", lfs_setquota, 0, "Set filesystem quotas.\n" "usage: setquota [ -u | -g ] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>\n" - " setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>"}, + " setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>\n" + " setquota [ -u | --user | -g | --group ] <name>\n" + " [--block-softlimit <block-softlimit>]\n" + " [--block-hardlimit <block-hardlimit>]\n" + " [--inode-softlimit <inode-softlimit>]\n" + " [--inode-hardlimit <inode-hardlimit>] <filesystem>\n" + " setquota [-t] [ -u | --user | -g | --group ]\n" + " [--block-grace <block-grace>]\n" + " [--inode-grace <inode-grace>] <filesystem>\n" + " -b can be used instead of --block-softlimit/--block-grace\n" + " -B can be used instead of --block-hardlimit\n" + " -i can be used instead of --inode-softlimit/--inode-grace\n" + " -I can be used instead of --inode-hardlimit"}, {"quota", lfs_quota, 0, "Display disk usage and limits.\n" "usage: quota [ -o obd_uuid ] [{-u|-g <name>}|-t] <filesystem>"}, {"quotainv", lfs_quotainv, 0, "Invalidate quota data.\n" @@ -242,7 +254,7 @@ static int lfs_setstripe(int argc, char **argv) /* get the stripe size */ if (stripe_size_arg != NULL) { - result = parse_size(stripe_size_arg, &st_size, &size_units); + result = parse_size(stripe_size_arg, &st_size, &size_units, 0); if (result) { fprintf(stderr,"error: bad size '%s'\n", stripe_size_arg); @@ -496,7 +508,8 @@ static int lfs_find(int argc, char **argv) if (param.size_sign) optarg++; - ret = parse_size(optarg, ¶m.size,¶m.size_units); + ret = parse_size(optarg, ¶m.size, + ¶m.size_units, 0); if (ret) { fprintf(stderr,"error: bad size '%s'\n", optarg); @@ -1446,93 +1459,278 @@ error: return ULONG_MAX; } -#define ARG2ULL(nr, str, msg) \ +#define ARG2ULL(nr, str, defscale) \ do { \ - char *endp; \ - nr = strtoull(str, &endp, 0); \ - if (*endp) { \ - fprintf(stderr, "error: bad %s: %s\n", msg, str); \ + unsigned long long limit, units = 0; \ + int rc; \ + \ + rc = parse_size(str, &limit, &units, 1); \ + if (rc < 0) { \ + fprintf(stderr, "error: bad limit value %s\n", str); \ return CMD_HELP; \ } \ + nr = ((units == 0) ? (defscale) : 1) * limit; \ } while (0) +static inline int has_times_option(int argc, char **argv) +{ + int i; -int lfs_setquota(int argc, char **argv) + for (i = 1; i < argc; i++) + if (!strcmp(argv[i], "-t")) + return 1; + + return 0; +} + +int lfs_setquota_times(int argc, char **argv) { - int c; - char *mnt; + int c, rc; struct if_quotactl qctl; - char *obd_type = (char *)qctl.obd_type; - int rc; + char *mnt, *obd_type = (char *)qctl.obd_type; + struct obd_dqblk *dqb = &qctl.qc_dqblk; + struct obd_dqinfo *dqi = &qctl.qc_dqinfo; + struct option long_opts[] = { + {"user", no_argument, 0, 'u'}, + {"group", no_argument, 0, 'g'}, + {"block-grace", required_argument, 0, 'b'}, + {"inode-grace", required_argument, 0, 'i'}, + {"times", no_argument, 0, 't'}, + {0, 0, 0, 0} + }; memset(&qctl, 0, sizeof(qctl)); - qctl.qc_cmd = LUSTRE_Q_SETQUOTA; + qctl.qc_cmd = LUSTRE_Q_SETINFO; + qctl.qc_type = UGQUOTA; + +#if 1 + /* compatibility syntax: setquota -t -[u|g] t1 t2 mnt */ + if (argc == 6 && !strcmp(argv[1], "-t") && + (!strcmp(argv[2], "-u") || !strcmp(argv[2], "-g")) && + argv[3][0] != '-' && argv[4][0] != '-') { + fprintf(stderr, "warning: using compatibility syntax, it may not" + " be available in future releases!\n"); + + qctl.qc_type = !strcmp(argv[2], "-u") ? USRQUOTA : GRPQUOTA; + + if ((dqi->dqi_bgrace = str2sec(argv[3])) == ULONG_MAX) { + fprintf(stderr, "error: bad block-grace: %s\n", optarg); + return CMD_HELP; + } + if ((dqi->dqi_igrace = str2sec(argv[4])) == ULONG_MAX) { + fprintf(stderr, "error: bad inode-grace: %s\n", optarg); + return CMD_HELP; + } + dqb->dqb_valid = QIF_TIMES; + mnt = argv[argc - 1]; + goto quotactl; + } +#endif optind = 0; - while ((c = getopt(argc, argv, "ugt")) != -1) { + while ((c = getopt_long(argc, argv, "ugb:i:t", long_opts, NULL)) != -1) { switch (c) { case 'u': - qctl.qc_type |= 0x01; - break; case 'g': - qctl.qc_type |= 0x02; + if (qctl.qc_type != UGQUOTA) { + fprintf(stderr, "error: -u and -g can't be used " + "more than once\n"); + return CMD_HELP; + } + qctl.qc_type = (c == 'u') ? USRQUOTA : GRPQUOTA; break; - case 't': - qctl.qc_cmd = LUSTRE_Q_SETINFO; + 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; - default: - fprintf(stderr, "error: %s: option '-%c' " - "unrecognized\n", argv[0], c); + 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; } } - if (qctl.qc_type) - qctl.qc_type--; - if (qctl.qc_type == UGQUOTA) { - fprintf(stderr, "error: user and group quotas can't be set " - "both\n"); + fprintf(stderr, "error: neither -u nor -g specified\n"); + return CMD_HELP; + } + + if (optind != argc - 1) { + fprintf(stderr, "error: unexpected parameters encountered\n"); return CMD_HELP; } - if (qctl.qc_cmd == LUSTRE_Q_SETQUOTA) { - struct obd_dqblk *dqb = &qctl.qc_dqblk; + mnt = argv[optind]; - if (optind + 6 != argc) - return CMD_HELP; +#if 1 +quotactl: +#endif + rc = llapi_quotactl(mnt, &qctl); + if (rc) { + if (*obd_type) + fprintf(stderr, "%s %s ", obd_type, + obd_uuid2str(&qctl.obd_uuid)); + fprintf(stderr, "setquota failed: %s\n", strerror(errno)); + return rc; + } + + return 0; +} + +#define BSLIMIT (1 << 0) +#define BHLIMIT (1 << 1) +#define ISLIMIT (1 << 2) +#define IHLIMIT (1 << 3) + +int lfs_setquota(int argc, char **argv) +{ + int c, rc; + struct if_quotactl qctl; + char *mnt, *obd_type = (char *)qctl.obd_type; + struct obd_dqblk *dqb = &qctl.qc_dqblk; + struct option long_opts[] = { + {"user", required_argument, 0, 'u'}, + {"group", required_argument, 0, 'g'}, + {"block-softlimit", required_argument, 0, 'b'}, + {"block-hardlimit", required_argument, 0, 'B'}, + {"inode-softlimit", required_argument, 0, 'i'}, + {"inode-hardlimit", required_argument, 0, 'I'}, + {0, 0, 0, 0} + }; + unsigned limit_mask = 0; + + if (has_times_option(argc, argv)) + return lfs_setquota_times(argc, argv); - rc = name2id(&qctl.qc_id, argv[optind++], qctl.qc_type); + memset(&qctl, 0, sizeof(qctl)); + qctl.qc_cmd = LUSTRE_Q_SETQUOTA; + qctl.qc_type = UGQUOTA; /* UGQUOTA makes no sense for setquota, + * so it can be used as a marker that qc_type + * isn't reinitialized from command line */ + +#if 1 + /* compatibility syntax: [-u|-g] <user|group> b B i I mount + * will be removed in the future */ + if (argc == 8 && (!strcmp(argv[1], "-u") || !strcmp(argv[1], "-g")) && + argv[3][0] != '-' && argv[4][0] != '-' && argv[5][0] != '-' && + argv[6][0] != '-') { + fprintf(stderr, "warning: using compatibility syntax, it may not" + " be available in future releases!\n"); + + qctl.qc_type = !strcmp(argv[1], "-u") ? USRQUOTA : GRPQUOTA; + rc = name2id(&qctl.qc_id, argv[2], qctl.qc_type); if (rc) { - fprintf(stderr, "error: find id for name %s failed: %s\n", - argv[optind - 1], strerror(errno)); + fprintf(stderr, "error: unknown id %s\n", optarg); return CMD_HELP; } - ARG2ULL(dqb->dqb_bsoftlimit, argv[optind++], "block-softlimit"); - ARG2ULL(dqb->dqb_bhardlimit, argv[optind++], "block-hardlimit"); - ARG2ULL(dqb->dqb_isoftlimit, argv[optind++], "inode-softlimit"); - ARG2ULL(dqb->dqb_ihardlimit, argv[optind++], "inode-hardlimit"); + ARG2ULL(dqb->dqb_bsoftlimit, argv[3], 1024); + dqb->dqb_bsoftlimit >>= 10; + ARG2ULL(dqb->dqb_bhardlimit, argv[4], 1024); + dqb->dqb_bhardlimit >>= 10; + ARG2ULL(dqb->dqb_isoftlimit, argv[5], 1); + ARG2ULL(dqb->dqb_ihardlimit, argv[6], 1); dqb->dqb_valid = QIF_LIMITS; - } else { - struct obd_dqinfo *dqi = &qctl.qc_dqinfo; + mnt = argv[argc - 1]; + goto quotactl; + } +#endif - if (optind + 3 != argc) + optind = 0; + while ((c = getopt_long(argc, argv, "u:g:b:B:i:I:", long_opts, NULL)) != -1) { + switch (c) { + case 'u': + case 'g': + if (qctl.qc_type != UGQUOTA) { + fprintf(stderr, "error: -u and -g can't be used" + " more than once\n"); + return CMD_HELP; + } + qctl.qc_type = (c == 'u') ? USRQUOTA : GRPQUOTA; + rc = name2id(&qctl.qc_id, optarg, qctl.qc_type); + if (rc) { + fprintf(stderr, "error: unknown id %s\n", + optarg); + return CMD_HELP; + } + break; + case 'b': + ARG2ULL(dqb->dqb_bsoftlimit, optarg, 1024); + dqb->dqb_bsoftlimit >>= 10; + limit_mask |= BSLIMIT; + break; + case 'B': + ARG2ULL(dqb->dqb_bhardlimit, optarg, 1024); + dqb->dqb_bhardlimit >>= 10; + limit_mask |= BHLIMIT; + break; + case 'i': + ARG2ULL(dqb->dqb_isoftlimit, optarg, 1); + limit_mask |= ISLIMIT; + break; + case 'I': + ARG2ULL(dqb->dqb_ihardlimit, optarg, 1); + limit_mask |= IHLIMIT; + break; + default: /* getopt prints error message for us when opterr != 0 */ return CMD_HELP; + } + } + + if (qctl.qc_type == UGQUOTA) { + fprintf(stderr, "error: neither -u nor -g are specified\n"); + return CMD_HELP; + } + + if (optind != argc - 1) { + fprintf(stderr, "error: unexpected parameters encountered\n"); + return CMD_HELP; + } - if ((dqi->dqi_bgrace = str2sec(argv[optind++])) == ULONG_MAX) { - fprintf(stderr, "error: bad %s: %s\n", "block-grace", argv[optind - 1]); + mnt = argv[optind]; + + if ((!(limit_mask & BHLIMIT) ^ !(limit_mask & BSLIMIT)) || + (!(limit_mask & IHLIMIT) ^ !(limit_mask & ISLIMIT))) { + /* sigh, we can't just set blimits/ilimits */ + struct if_quotactl tmp_qctl = {.qc_cmd = LUSTRE_Q_GETQUOTA, + .qc_type = qctl.qc_type, + .qc_id = qctl.qc_id}; + + rc = llapi_quotactl(mnt, &tmp_qctl); + if (rc < 0) { + fprintf(stderr, "error: getquota failed\n"); 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; - } + + if (!(limit_mask & BHLIMIT)) + dqb->dqb_bhardlimit = tmp_qctl.qc_dqblk.dqb_bhardlimit; + if (!(limit_mask & BSLIMIT)) + dqb->dqb_bsoftlimit = tmp_qctl.qc_dqblk.dqb_bsoftlimit; + if (!(limit_mask & IHLIMIT)) + dqb->dqb_ihardlimit = tmp_qctl.qc_dqblk.dqb_ihardlimit; + if (!(limit_mask & ISLIMIT)) + dqb->dqb_isoftlimit = tmp_qctl.qc_dqblk.dqb_isoftlimit; } - mnt = argv[optind]; + dqb->dqb_valid |= (limit_mask & (BHLIMIT | BSLIMIT)) ? QIF_BLIMITS : 0; + dqb->dqb_valid |= (limit_mask & (IHLIMIT | ISLIMIT)) ? QIF_ILIMITS : 0; +#if 1 +quotactl: +#endif rc = llapi_quotactl(mnt, &qctl); if (rc) { if (*obd_type) diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 40f2f205a40d3c4dd7ef04f55b3cc7ce4e88be23..80ad22d2ef7291b2f5c51a44150130f62f0e47ec 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -143,18 +143,23 @@ void llapi_printf(int level, char *fmt, ...) va_end(args); } +/* size_units is unchanged if no specifier used */ int parse_size(char *optarg, unsigned long long *size, - unsigned long long *size_units) + unsigned long long *size_units, int bytes_spec) { char *end; - *size = strtoul(optarg, &end, 0); + *size = strtoull(optarg, &end, 0); if (*end != '\0') { if ((*end == 'b') && *(end+1) == '\0' && - (*size & (~0ULL << (64 - 9))) == 0) { + (*size & (~0ULL << (64 - 9))) == 0 && + !bytes_spec) { *size <<= 9; *size_units = 1 << 9; + } else if ((*end == 'b') && *(end+1) == '\0' && + bytes_spec) { + *size_units = 1; } else if ((*end == 'k' || *end == 'K') && *(end+1) == '\0' && (*size & (~0ULL << (64 - 10))) == 0) {