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, &param.size,&param.size_units);
+                        ret = parse_size(optarg, &param.size,
+                                         &param.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) {