Whamcloud - gitweb
b=22194 lfs quota output refinement
authorAndrew Perepechko <Andrew.Perepechko@sun.com>
Fri, 4 Jun 2010 20:39:32 +0000 (00:39 +0400)
committerRobert Read <robert.read@oracle.com>
Fri, 4 Jun 2010 23:38:52 +0000 (16:38 -0700)
Added more dashes to lfs quota output to make it parseable with scripts.
Added -q option to lfs quota.
sanity-quota "lfs quota" calls were compactified.

a=Joseph Herring
a=Christopher Morrone
a=Andrew Perepechko
i=Johann Lombardi
i=ZhiYong Tian
i=Andrew Perepechko

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

index c82f012..efdb304 100644 (file)
@@ -12,6 +12,14 @@ tbd  Sun Microsystems, Inc.
         2.6.29.4-167.fc11 (FC11)
        * Recommended e2fsprogs version: 1.41.10-sun2
 
+Severity   : enhancement
+Bugzilla   : 22194
+Description: lfs quota output is not very convenient for awk/sed-parsing
+Details    : Some positions in lfs quota output table could be empty or
+            non-empty which made it hard to parse it with scripts, now
+            a dash is put instead of space where there is not supposed
+            to be any data.
+
 Severity   : normal
 Bugzilla   : 22787
 Description: Update to OFED 1.5.1
index 55d2e83..882f1bb 100644 (file)
@@ -36,7 +36,7 @@ lfs \- Lustre utility to create a file with specific striping pattern, find the
 .br
 .B lfs poollist <filesystem>[.<pool>] | <pathname>
 .br
-.B lfs quota [-v] [-o obd_uuid|-I ost_idx|-i mdt_idx] [-u <uname>| -u <uid>|-g <gname>| -g <gid>] <filesystem>
+.B lfs quota [-q] [-v] [-o obd_uuid|-I ost_idx|-i mdt_idx] [-u <uname>| -u <uid>|-g <gname>| -g <gid>] <filesystem>
 .br
 .B lfs quota -t <-u|-g> <filesystem>
 .br
@@ -144,8 +144,8 @@ Delete the default striping on the specified directory.
 .B poollist <filesystem>[.<pool>] | <pathname>
 List the pools in \fBfilesystem\fR or \fBpathname\fR, or the OSTs in \fBfilesystem.pool\fR
 .TP
-.B quota [-v] [-o obd_uuid|-i mdt_idx|-I ost_idx] [-u|-g <uname>|<uid>|<gname>|<gid>] <filesystem>
-To display disk usage and limits, either for the full filesystem, or for objects on a specific obd. A user or group name or an ID can be specified. If both user and group are omitted quotas for current uid/gid are shown. -v provides more verbose (with per-obd statistics) output.
+.B quota [-q] [-v] [-o obd_uuid|-i mdt_idx|-I ost_idx] [-u|-g <uname>|<uid>|<gname>|<gid>] <filesystem>
+To display disk usage and limits, either for the full filesystem, or for objects on a specific obd. A user or group name or an ID can be specified. If both user and group are omitted quotas for current uid/gid are shown. -v provides more verbose (with per-obd statistics) output. -q disables printing of additional descriptions (including column titles).
 .TP
 .B quota -t <-u|-g> <filesystem>
 To display block and inode grace times for user (-u) or group (-g) quotas
index 876d2f3..6d9f8aa 100644 (file)
@@ -233,6 +233,36 @@ quota_log() {
         log "$*"
 }
 
+#
+# get quota info for a user or a group
+# usage: getquota -u|-g <username>|<groupname> global|<obd_uuid> bhardlimit|bsoftlimit|bgrace|ihardlimit|isoftlimit|igrace
+#
+getquota() {
+        local spec
+        local uuid
+
+        [ "$#" != 4 ] && error "getquota: wrong number of arguments: $#"
+        [ "$1" != "-u" -a "$1" != "-g" ] && error "getquota: wrong u/g specifier $1 passed"
+
+        uuid="$3"
+
+        case "$4" in
+                curspace)   spec=1;;
+                bsoftlimit) spec=2;;
+                bhardlimit) spec=3;;
+                bgrace)     spec=4;;
+                curinodes)  spec=5;;
+                isoftlimit) spec=6;;
+                ihardlimit) spec=7;;
+                igrace)     spec=8;;
+                *)          error "unknown quota parameter $4";;
+        esac
+
+        [ "$uuid" = "global" ] && uuid=$DIR
+
+        $LFS quota -v "$1" "$2" $DIR | awk 'BEGIN { num='$spec' } { if ($1 == "'$uuid'") { if (NF == 1) { getline } else { num++ } ; print $num;} }'
+}
+
 quota_show_check() {
         LOCAL_BF=$1
         LOCAL_UG=$2
@@ -242,7 +272,7 @@ quota_show_check() {
         $LFS quota -v -$LOCAL_UG $LOCAL_ID $DIR
 
         if [ "$LOCAL_BF" == "a" -o "$LOCAL_BF" == "b" ]; then
-               USAGE="`$LFS quota -$LOCAL_UG $LOCAL_ID $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $2 }'`"
+                USAGE=`getquota -$LOCAL_UG $LOCAL_ID global curspace`
                 if [ -z $USAGE ]; then
                         quota_error $LOCAL_UG $LOCAL_ID "System is error when query quota for block ($LOCAL_UG:$LOCAL_ID)."
                 else
@@ -251,7 +281,7 @@ quota_show_check() {
         fi
 
         if [ "$LOCAL_BF" == "a" -o "$LOCAL_BF" == "f" ]; then
-               USAGE="`$LFS quota -$LOCAL_UG $LOCAL_ID $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $5 }'`"
+                USAGE=`getquota -$LOCAL_UG $LOCAL_ID global curinodes`
                 if [ -z $USAGE ]; then
                         quota_error $LOCAL_UG $LOCAL_ID "System is error when query quota for file ($LOCAL_UG:$LOCAL_ID)."
                 else
@@ -309,7 +339,7 @@ test_1_sub() {
         rm -f $TESTFILE
        sync; sleep 1; sync;
        OST0_UUID=`do_facet ost1 $LCTL dl | grep -m1 obdfilter | awk '{print $((NF-1))}'`
-       OST0_QUOTA_USED=`$LFS quota -o $OST0_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED=`getquota -u $TSTUSR $OST0_UUID curspace`
        echo $OST0_QUOTA_USED
        [ $OST0_QUOTA_USED -ne 0 ] && \
            ($SHOW_QUOTA_USER; quota_error u $TSTUSR "(usr) quota deleted isn't released")
@@ -347,7 +377,7 @@ test_1_sub() {
         rm -f $TESTFILE
        sync; sleep 1; sync;
        OST0_UUID=`do_facet ost1 $LCTL dl | grep -m1 obdfilter | awk '{print $((NF-1))}'`
-       OST0_QUOTA_USED=`$LFS quota -o $OST0_UUID -g $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED=`getquota -g $TSTUSR $OST0_UUID curspace`
        echo $OST0_QUOTA_USED
        [ $OST0_QUOTA_USED -ne 0 ] && \
            ($SHOW_QUOTA_GROUP; quota_error g $TSTUSR "(grp) quota deleted isn't released")
@@ -402,7 +432,7 @@ test_2_sub() {
        sync; sleep 1; sync;
 
        MDS_UUID=`do_facet $SINGLEMDS $LCTL dl | grep -m1 " mdt " | awk '{print $((NF-1))}'`
-       MDS_QUOTA_USED=`$LFS quota -o $MDS_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
+        MDS_QUOTA_USED=`getquota -u $TSTUSR $MDS_UUID curinodes`
        echo $MDS_QUOTA_USED
        [ $MDS_QUOTA_USED -ne 0 ] && \
            ($SHOW_QUOTA_USER; quota_error u $TSTUSR "(usr) quota deleted isn't released")
@@ -430,7 +460,7 @@ test_2_sub() {
        sync; sleep 1; sync;
 
        MDS_UUID=`do_facet $SINGLEMDS $LCTL dl | grep -m1 " mdt " | awk '{print $((NF-1))}'`
-       MDS_QUOTA_USED=`$LFS quota -o $MDS_UUID -g $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
+        MDS_QUOTA_USED=`getquota -g $TSTUSR $MDS_UUID curinodes`
        echo $MDS_QUOTA_USED
        [ $MDS_QUOTA_USED -ne 0 ] && \
            ($SHOW_QUOTA_GROUP; quota_error g $TSTUSR "(grp) quota deleted isn't released")
@@ -778,7 +808,7 @@ test_6() {
         while [ $((count--)) -gt 0 ]; do
                 sync && sleep 5
 
-               OST0_QUOTA_HOLD=`$LFS quota -o $OST0_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $3 }'`
+                OST0_QUOTA_HOLD=`getquota -u $TSTUSR $OST0_UUID bhardlimit`
                 if [ -z $OST0_QUOTA_HOLD ]; then
                         error "System is error when query quota for block (U:$TSTUSR)."
                 else
@@ -794,7 +824,7 @@ test_6() {
         while [ $((count--)) -gt 0 ]; do
                 sync && sleep 5
 
-               OST0_QUOTA_HOLD=`$LFS quota -o $OST0_UUID -g $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $3 }'`
+                OST0_QUOTA_HOLD=`getquota -g $TSTUSR $OST0_UUID bhardlimit`
                 if [ -z $OST0_QUOTA_HOLD ]; then
                         error "System is error when query quota for block (G:$TSTUSR)."
                 else
@@ -859,13 +889,13 @@ test_7()
 
        # check limits
        PATTERN="`echo $DIR | sed 's/\//\\\\\//g'`"
-       TOTAL_LIMIT="`$LFS quota -v -u $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
+        TOTAL_LIMIT=`getquota -u $TSTUSR global bhardlimit`
        [ $TOTAL_LIMIT -eq $LIMIT ] || error "total limits not recovery!"
        echo "  total limits = $TOTAL_LIMIT"
 
         OST0_UUID=`do_facet ost1 "$LCTL dl | grep -m1 obdfilter" | awk '{print $((NF-1))}'`
         [ -z "$OST0_UUID" ] && OST0_UUID=`do_facet ost1 "$LCTL dl | grep -m1 obdfilter" | awk '{print $((NF-1))}'`
-       OST0_LIMIT="`$LFS quota -o $OST0_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $3 }'`"
+        OST0_LIMIT=`getquota  -u $TSTUSR $OST0_UUID bhardlimit`
        [ $OST0_LIMIT -eq $BUNIT_SZ ] || error "high limits not released!"
        echo "  limits on $OST0_UUID = $OST0_LIMIT"
 
@@ -1172,9 +1202,9 @@ check_if_quota_zero(){
         line=`$LFS quota -v -$1 $2 $DIR | wc -l`
        for i in `seq 3 $line`; do
            if [ $i -eq 3 ]; then
-               field="3 4 6 7"
+               field="3 4 7 8"
            else
-               field="3 5"
+               field="3 6"
            fi
            for j in $field; do
                tmp=`$LFS quota -v -$1 $2 $DIR | sed -n ${i}p |
@@ -1231,14 +1261,14 @@ test_15(){
 
         # test for user
         $LFS setquota -u $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR
-        TOTAL_LIMIT="`$LFS quota -v -u $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
+        TOTAL_LIMIT=`getquota -u $TSTUSR global bhardlimit`
         [ $TOTAL_LIMIT -eq $LIMIT ] || error "  (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!"
         echo "  (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!"
         resetquota -u $TSTUSR
 
         # test for group
         $LFS setquota -g $TSTUSR -b 0 -B $LIMIT -i 0 -I 0 $DIR
-        TOTAL_LIMIT="`$LFS quota -v -g $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
+        TOTAL_LIMIT=`getquota -g $TSTUSR global bhardlimit`
         [ $TOTAL_LIMIT -eq $LIMIT ] || error "  (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!"
         echo "  (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!"
         resetquota -g $TSTUSR
@@ -1658,9 +1688,10 @@ test_20()
                                  --inode-hardlimit ${LSTR[3]} \
                                  $MOUNT || error "could not set quota limits"
 
-        ($LFS quota -v -u $TSTUSR $MOUNT  | \
-            grep -E '^ *'$MOUNT' *[0-9]+\** *'${LVAL[0]}' *'${LVAL[1]}' *[0-9]+\** *'${LVAL[2]}' *'${LVAL[3]}) \
-                 || error "lfs quota output is unexpected"
+        [ "`getquota -u $TSTUSR global bsoftlimit`" = "${LVAL[0]}" ] || error "bsoftlimit was not set properly"
+        [ "`getquota -u $TSTUSR global bhardlimit`" = "${LVAL[1]}" ] || error "bhardlimit was not set properly"
+        [ "`getquota -u $TSTUSR global isoftlimit`" = "${LVAL[2]}" ] || error "isoftlimit was not set properly"
+        [ "`getquota -u $TSTUSR global ihardlimit`" = "${LVAL[3]}" ] || error "ihardlimit was not set properly"
 
         resetquota -u $TSTUSR
 }
@@ -1796,7 +1827,7 @@ test_23_sub() {
        rm -f $TESTFILE
        wait_delete_completed
        OST0_UUID=`do_facet ost1 $LCTL dl | grep -m1 obdfilter | awk '{print $((NF-1))}'`
-       OST0_QUOTA_USED=`$LFS quota -o $OST0_UUID -u $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED=`getquota -u $TSTUSR $OST0_UUID curspace`
        echo $OST0_QUOTA_USED
        [ $OST0_QUOTA_USED -ne 0 ] && \
            ($SHOW_QUOTA_USER; quota_error u $TSTUSR "quota deleted isn't released")
@@ -1882,10 +1913,10 @@ test_25_sub() {
        $LFS setstripe $DIR/$tdir -c 1 -i 0
        MDS_UUID=`do_facet $SINGLEMDS $LCTL dl | grep -m1 " mdt " | awk '{print $((NF-1))}'`
        OST0_UUID=`do_facet ost1 $LCTL dl | grep -m1 obdfilter | awk '{print $((NF-1))}'`
-       MDS_QUOTA_USED_OLD=`$LFS quota -o $MDS_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
-       OST0_QUOTA_USED_OLD=`$LFS quota -o $OST0_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
-       MDS_QUOTA_USED2_OLD=`$LFS quota -o $MDS_UUID $1 $TSTUSR2 $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
-       OST0_QUOTA_USED2_OLD=`$LFS quota -o $OST0_UUID $1 $TSTUSR2 $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        MDS_QUOTA_USED_OLD=`getquota $1 $TSTUSR $MDS_UUID curinodes`
+        OST0_QUOTA_USED_OLD=`getquota $1 $TSTUSR $OST0_UUID curspace`
+        MDS_QUOTA_USED2_OLD=`getquota $1 $TSTUSR2 $MDS_UUID curinodes`
+        OST0_QUOTA_USED2_OLD=`getquota $1 $TSTUSR2 $OST0_UUID curspace`
 
         # TSTUSR write 4M
         log "$TSTUSR write 4M to $TESTFILE"
@@ -1893,10 +1924,10 @@ test_25_sub() {
         sync
        show_quota $1 $TSTUSR
        show_quota $1 $TSTUSR2
-       MDS_QUOTA_USED_NEW=`$LFS quota -o $MDS_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
+        MDS_QUOTA_USED_NEW=`getquota  $1 $TSTUSR $MDS_UUID curinodes`
         [ $MDS_QUOTA_USED_NEW -ne $((MDS_QUOTA_USED_OLD + 1)) ] && \
                 quota_error a $TSTUSR "$TSTUSR inode quota usage error: [$MDS_QUOTA_USED_OLD|$MDS_QUOTA_USED_NEW]"
-       OST0_QUOTA_USED_NEW=`$LFS quota -o $OST0_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED_NEW=`getquota   $1 $TSTUSR $OST0_UUID curspace`
         OST0_QUOTA_USED_DELTA=$((OST0_QUOTA_USED_NEW - OST0_QUOTA_USED_OLD))
         [ $OST0_QUOTA_USED_DELTA -lt 4096 ] && \
                 quota_error a $TSTUSR "$TSTUSR block quota usage error: [$OST0_QUOTA_USED_OLD|$OST0_QUOTA_USED_NEW]"
@@ -1912,19 +1943,19 @@ test_25_sub() {
         sync
        show_quota $1 $TSTUSR
        show_quota $1 $TSTUSR2
-       MDS_QUOTA_USED2_NEW=`$LFS quota -o $MDS_UUID $1 $TSTUSR2 $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
+        MDS_QUOTA_USED2_NEW=`getquota $1 $TSTUSR2 $MDS_UUID curinodes`
         [ $MDS_QUOTA_USED2_NEW -ne $((MDS_QUOTA_USED2_OLD + 1)) ] && \
                 quota_error a $TSTUSR2 "$TSTUSR2 inode quota usage transfer from $TSTUSR to $TSTUSR2 failed: [$MDS_QUOTA_USED2_OLD|$MDS_QUOTA_USED2_NEW]"
-       OST0_QUOTA_USED2_NEW=`$LFS quota -o $OST0_UUID $1 $TSTUSR2 $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED2_NEW=`getquota  $1 $TSTUSR2 $OST0_UUID curspace`
        # when chown, the quota on ost could be displayed out of quota temporarily. Delete the '*' in this situation. b=20433
        OST0_QUOTA_USED2_NEW=${OST0_QUOTA_USED2_NEW%\*}
         OST0_QUOTA_USED2_DELTA=$((OST0_QUOTA_USED2_NEW - OST0_QUOTA_USED2_OLD))
         [ $OST0_QUOTA_USED2_DELTA -ne $OST0_QUOTA_USED_DELTA ] && \
                 quota_error a $TSTUSR2 "$TSTUSR2 block quota usage transfer from $TSTUSR to $TSTUSR2 failed: [$OST0_QUOTA_USED2_OLD|$OST0_QUOTA_USED2_NEW]"
-       MDS_QUOTA_USED_NEW=`$LFS quota -o $MDS_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $4 }'`
+        MDS_QUOTA_USED_NEW=`getquota  $1 $TSTUSR $MDS_UUID curinodes`
         [ $MDS_QUOTA_USED_NEW -ne $MDS_QUOTA_USED_OLD ] && \
                 quota_error a $TSTUSR "$TSTUSR inode quota usage transfer from $TSTUSR to $TSTUSR2 failed: [$MDS_QUOTA_USED_OLD|$MDS_QUOTA_USED_NEW]"
-       OST0_QUOTA_USED_NEW=`$LFS quota -o $OST0_UUID $1 $TSTUSR $DIR | awk '/^.*[[:digit:]+][[:space:]+]/ { print $1 }'`
+        OST0_QUOTA_USED_NEW=`getquota  $1 $TSTUSR $OST0_UUID curspace`
         [ $OST0_QUOTA_USED_NEW -ne $OST0_QUOTA_USED_OLD ] && \
                 quota_error a $TSTUSR "$TSTUSR block quota usage transfer from $TSTUSR to $TSTUSR2 failed: [$OST0_QUOTA_USED_OLD|$OST0_QUOTA_USED_NEW]"
 
index 5156dec..c069f9f 100644 (file)
@@ -198,7 +198,7 @@ command_t cmdlist[] = {
          "       -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 [-v] [-o obd_uuid|-i mdt_idx|-I ost_idx]\n"
+         "usage: quota [-q] [-v] [-o obd_uuid|-i mdt_idx|-I ost_idx]\n"
          "             [<-u|-g> <uname>|<uid>|<gname>|<gid>] <filesystem>\n"
          "       quota [-o obd_uuid|-i mdt_idx|-I ost_idx] -t <-u|-g> <filesystem>"},
         {"quotainv", lfs_quotainv, 0, "Invalidate quota data.\n"
@@ -1966,12 +1966,12 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int type, int rc)
                                         ? LPU64 : "["LPU64"]",
                                         dqb->dqb_bsoftlimit);
                         else
-                                sprintf(numbuf[1], "%s", "");
+                                sprintf(numbuf[1], "%s", "-");
                         sprintf(numbuf[2], (dqb->dqb_valid & QIF_BLIMITS)
                                 ? LPU64 : "["LPU64"]", dqb->dqb_bhardlimit);
                         printf(" %7s%c %6s %7s %7s",
                                numbuf[0], bover ? '*' : ' ', numbuf[1],
-                               numbuf[2], bover > 1 ? timebuf : "");
+                               numbuf[2], bover > 1 ? timebuf : "-");
 
                         if (iover)
                                 diff2str(dqb->dqb_itime, timebuf, now);
@@ -1983,13 +1983,15 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int type, int rc)
                                         ? LPU64 : "["LPU64"]",
                                         dqb->dqb_isoftlimit);
                         else
-                                sprintf(numbuf[1], "%s", "");
+                                sprintf(numbuf[1], "%s", "-");
                         sprintf(numbuf[2], (dqb->dqb_valid & QIF_ILIMITS) ?
                                 LPU64 : "["LPU64"]", dqb->dqb_ihardlimit);
                         if (type != QC_OSTIDX)
                                 printf(" %7s%c %6s %7s %7s",
                                        numbuf[0], iover ? '*' : ' ', numbuf[1],
-                                       numbuf[2], iover > 1 ? timebuf : "");
+                                       numbuf[2], iover > 1 ? timebuf : "-");
+                        else
+                                printf(" %7s %7s %7s %7s", "-", "-", "-", "-");
                         printf("\n");
                 }
         } else if (qctl->qc_cmd == LUSTRE_Q_GETINFO ||
@@ -2049,12 +2051,12 @@ static int lfs_quota(int argc, char **argv)
                                     .qc_type = UGQUOTA };
         char *obd_type = (char *)qctl.obd_type;
         char *obd_uuid = (char *)qctl.obd_uuid.uuid;
-        int rc, rc1 = 0, rc2 = 0, rc3 = 0, verbose = 0, pass = 0;
+        int rc, rc1 = 0, rc2 = 0, rc3 = 0, verbose = 0, pass = 0, quiet = 0;
         char *endptr;
         __u32 valid = QC_GENERAL, idx = 0;
 
         optind = 0;
-        while ((c = getopt(argc, argv, "ugto:i:I:v")) != -1) {
+        while ((c = getopt(argc, argv, "ugto:i:I:qv")) != -1) {
                 switch (c) {
                 case 'u':
                         if (qctl.qc_type != UGQUOTA) {
@@ -2088,6 +2090,9 @@ static int lfs_quota(int argc, char **argv)
                 case 'v':
                         verbose = 1;
                         break;
+                case 'q':
+                        quiet = 1;
+                        break;
                 default:
                         fprintf(stderr, "error: %s: option '-%c' "
                                         "unrecognized\n", argv[0], c);
@@ -2141,13 +2146,24 @@ ug_output:
         mnt = argv[optind];
 
         rc1 = llapi_quotactl(mnt, &qctl);
-        if (rc1 == -1 && errno == ESRCH) {
-                fprintf(stderr, "\n%s quotas are not enabled.\n",
-                        qctl.qc_type == USRQUOTA ? "user" : "group");
-                goto out;
+        if (rc1 == -1) {
+                switch (errno) {
+                case ESRCH:
+                        fprintf(stderr, "%s quotas are not enabled.\n",
+                                qctl.qc_type == USRQUOTA ? "user" : "group");
+                        goto out;
+                case EPERM:
+                        fprintf(stderr, "Permission denied.\n");
+                case ENOENT:
+                        /* We already got a "No such file..." message. */
+                        goto out;
+                default:
+                        fprintf(stderr, "Unexpected quotactl error: %s\n",
+                                strerror(errno));
+                }
         }
 
-        if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA)
+        if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA && !quiet)
                 print_quota_title(name, &qctl);
 
         if (rc1 && *obd_type)
@@ -2172,7 +2188,7 @@ out:
         if (pass == 1)
                 goto ug_output;
 
-        return 0;
+        return rc1;
 }
 #endif /* HAVE_SYS_QUOTA_H! */