diff mbox

[v3,10/12] Btrfs-progs: add '--block-size' option to control print result

Message ID 1381130508-8458-11-git-send-email-wangsl.fnst@cn.fujitsu.com (mailing list archive)
State Under Review, archived
Headers show

Commit Message

Wang Shilong Oct. 7, 2013, 7:21 a.m. UTC
You can use it like:
	btrfs qgroup show --block-size=m <mnt>

Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
---
 cmds-qgroup.c | 16 +++++++++---
 qgroup.c      | 78 ++++++++++++++++++++++++++++++++++++++++-------------------
 qgroup.h      |  3 ++-
 utils.c       | 50 ++++++++++++++++++++++++++++++++++++++
 utils.h       |  2 ++
 5 files changed, 120 insertions(+), 29 deletions(-)

Comments

David Sterba Oct. 8, 2013, 3:34 p.m. UTC | #1
On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
> You can use it like:
> 	btrfs qgroup show --block-size=m <mnt>
> 
> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.

There is no distinction between the 1000 and 1024 based prefixes, also
no way to get the raw values in bytes. I don't have a suggestion how to
do that, merely letting you know that this could go separately (this and
the "-h" patch, the rest shall be integrated).

Also, the numbers in the table should be aligned to the right:

$ btrfs qgroup show -h -p /mnt/
qgroupid rfer      excl      parent
-------- ----      ----      ------
0/5      900.00KiB 900.00KiB ---
0/267    688.00KiB 12.00KiB  1/5
0/268    684.00KiB 8.00KiB   1/5
0/269    6.71GiB   4.00KiB   1/1
0/277    6.71GiB   4.00KiB   1/1
0/278    39.74GiB  39.74GiB  1/2
1/1      6.71GiB   6.71GiB   ---
1/2      39.74GiB  39.74GiB  ---
1/5      696.00KiB 696.00KiB ---


david
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wang Shilong Oct. 8, 2013, 4:27 p.m. UTC | #2
Thanks for finding this, the problem comes to patch [v3 9/12].
When updating max columns len of child_qgroup, i miswrite qgroup->member to
qgroup->parent, i have updated this patch and send a v4, it can be
appiled without conflicts with later.

Thanks,
Wang
2013/10/8 David Sterba <dsterba@suse.cz>:
> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
>> You can use it like:
>>       btrfs qgroup show --block-size=m <mnt>
>>
>> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.
>
> There is no distinction between the 1000 and 1024 based prefixes, also
> no way to get the raw values in bytes. I don't have a suggestion how to
> do that, merely letting you know that this could go separately (this and
> the "-h" patch, the rest shall be integrated).
>
> Also, the numbers in the table should be aligned to the right:
>
> $ btrfs qgroup show -h -p /mnt/
> qgroupid rfer      excl      parent
> -------- ----      ----      ------
> 0/5      900.00KiB 900.00KiB ---
> 0/267    688.00KiB 12.00KiB  1/5
> 0/268    684.00KiB 8.00KiB   1/5
> 0/269    6.71GiB   4.00KiB   1/1
> 0/277    6.71GiB   4.00KiB   1/1
> 0/278    39.74GiB  39.74GiB  1/2
> 1/1      6.71GiB   6.71GiB   ---
> 1/2      39.74GiB  39.74GiB  ---
> 1/5      696.00KiB 696.00KiB ---
>
>
> david
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wang Shilong Oct. 8, 2013, 4:34 p.m. UTC | #3
Sorry, This should to reply to the bug that you find, not this thread.
Anyway, you are smart enough to get this .....

2013/10/9 Shilong Wang <wangshilong1991@gmail.com>:
> Thanks for finding this, the problem comes to patch [v3 9/12].
> When updating max columns len of child_qgroup, i miswrite qgroup->member to
> qgroup->parent, i have updated this patch and send a v4, it can be
> appiled without conflicts with later.
>
> Thanks,
> Wang
> 2013/10/8 David Sterba <dsterba@suse.cz>:
>> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
>>> You can use it like:
>>>       btrfs qgroup show --block-size=m <mnt>
>>>
>>> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.
>>
>> There is no distinction between the 1000 and 1024 based prefixes, also
>> no way to get the raw values in bytes. I don't have a suggestion how to
>> do that, merely letting you know that this could go separately (this and
>> the "-h" patch, the rest shall be integrated).
>>
>> Also, the numbers in the table should be aligned to the right:
>>
>> $ btrfs qgroup show -h -p /mnt/
>> qgroupid rfer      excl      parent
>> -------- ----      ----      ------
>> 0/5      900.00KiB 900.00KiB ---
>> 0/267    688.00KiB 12.00KiB  1/5
>> 0/268    684.00KiB 8.00KiB   1/5
>> 0/269    6.71GiB   4.00KiB   1/1
>> 0/277    6.71GiB   4.00KiB   1/1
>> 0/278    39.74GiB  39.74GiB  1/2
>> 1/1      6.71GiB   6.71GiB   ---
>> 1/2      39.74GiB  39.74GiB  ---
>> 1/5      696.00KiB 696.00KiB ---
>>
>>
>> david
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Sterba Oct. 8, 2013, 4:34 p.m. UTC | #4
On Wed, Oct 09, 2013 at 12:27:23AM +0800, Shilong Wang wrote:
> Thanks for finding this, the problem comes to patch [v3 9/12].
> When updating max columns len of child_qgroup, i miswrite qgroup->member to
> qgroup->parent, i have updated this patch and send a v4, it can be
> appiled without conflicts with later.

Works for me, thanks, replaced.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wang Shilong Oct. 8, 2013, 4:54 p.m. UTC | #5
Hi David,

2013/10/8 David Sterba <dsterba@suse.cz>:
> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
>> You can use it like:
>>       btrfs qgroup show --block-size=m <mnt>
>>
>> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.
>
> There is no distinction between the 1000 and 1024 based prefixes, also
> no way to get the raw values in bytes. I don't have a suggestion how to
> do that, merely letting you know that this could go separately (this and
> the "-h" patch, the rest shall be integrated).

I implement this like the command 'du'.

In default, we print result in bytes. And block size don't give a byte
unit implicitly.Aslo i don't know why we need to distinct 1000 and
1024, i don't have any ideas about this.

>
> Also, the numbers in the table should be aligned to the right:

Yes, this should be fixed.

Thanks,
Wang
>
> $ btrfs qgroup show -h -p /mnt/
> qgroupid rfer      excl      parent
> -------- ----      ----      ------
> 0/5      900.00KiB 900.00KiB ---
> 0/267    688.00KiB 12.00KiB  1/5
> 0/268    684.00KiB 8.00KiB   1/5
> 0/269    6.71GiB   4.00KiB   1/1
> 0/277    6.71GiB   4.00KiB   1/1
> 0/278    39.74GiB  39.74GiB  1/2
> 1/1      6.71GiB   6.71GiB   ---
> 1/2      39.74GiB  39.74GiB  ---
> 1/5      696.00KiB 696.00KiB ---
>
>
> david
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hugo Mills Oct. 8, 2013, 5:01 p.m. UTC | #6
On Wed, Oct 09, 2013 at 12:54:03AM +0800, Shilong Wang wrote:
> Hi David,
> 
> 2013/10/8 David Sterba <dsterba@suse.cz>:
> > On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
> >> You can use it like:
> >>       btrfs qgroup show --block-size=m <mnt>
> >>
> >> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.

k = SI prefix, kilo
K = ? (IEEE prefix kibi?)
m = SI prefix, milli
M = SI prefix, mega
g = SI unit, grams
G = SI prefix, giga
t = ?
T = SI prefix, tera
p = SI prefix, pico
P = SI prefix, peta
e = ?
E = SI prefix, exa

   Some confusion here, I think. :)

> > There is no distinction between the 1000 and 1024 based prefixes, also
> > no way to get the raw values in bytes. I don't have a suggestion how to
> > do that, merely letting you know that this could go separately (this and
> > the "-h" patch, the rest shall be integrated).
> 
> I implement this like the command 'du'.
> 
> In default, we print result in bytes. And block size don't give a byte
> unit implicitly.

> Aslo i don't know why we need to distinct 1000 and 1024, i don't
> have any ideas about this.

   Because when you have a terabyte of data, the difference between
the two is 10%. If you're putting in this kind of infrastructure, it's
not much of an addition to report in either SI decimal or IEEE binary
scales.

> > Also, the numbers in the table should be aligned to the right:
> 
> Yes, this should be fixed.
> 
> Thanks,
> Wang
> >
> > $ btrfs qgroup show -h -p /mnt/
> > qgroupid rfer      excl      parent
> > -------- ----      ----      ------
> > 0/5      900.00KiB 900.00KiB ---
> > 0/267    688.00KiB 12.00KiB  1/5
> > 0/268    684.00KiB 8.00KiB   1/5
> > 0/269    6.71GiB   4.00KiB   1/1
> > 0/277    6.71GiB   4.00KiB   1/1
> > 0/278    39.74GiB  39.74GiB  1/2
> > 1/1      6.71GiB   6.71GiB   ---
> > 1/2      39.74GiB  39.74GiB  ---
> > 1/5      696.00KiB 696.00KiB ---

   Note that the SI mandate a space between the value and the unit.
Note also, for future reference, that SI use k for 10^3, whereas IEEE
use Ki for 2^10.

   Hugo.
Hugo Mills Oct. 8, 2013, 5:10 p.m. UTC | #7
On Tue, Oct 08, 2013 at 06:01:57PM +0100, Hugo Mills wrote:
> On Wed, Oct 09, 2013 at 12:54:03AM +0800, Shilong Wang wrote:
> > Hi David,
> > 
> > 2013/10/8 David Sterba <dsterba@suse.cz>:
> > > On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote:
> > >> You can use it like:
> > >>       btrfs qgroup show --block-size=m <mnt>
> > >>
> > >> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E.
> 
> k = SI prefix, kilo
> K = ? (IEEE prefix kibi?)

   ... or SI unit, kelvin

> t = ?

   SI-accepted unit, tonne

> e = ?

   SI-accepted unit, charge on the electron

   Hugo. :)
diff mbox

Patch

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 4fe776c..912cc42 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,8 +202,7 @@  static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pcreFf "
-	"[--sort=qgroupid,rfer,excl,max_rfer,max_excl] <path>",
+	"btrfs qgroup show [options] <path>",
 	"Show subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
@@ -218,6 +217,8 @@  static const char * const cmd_qgroup_show_usage[] = {
 	"rfer,max_rfer or max_excl",
 	"		you can use '+' or '-' in front of each item.",
 	"		(+:ascending, -:descending, ascending default)",
+	"--block-size=BLOCK_SIZE",
+	"		Here BLOCK_SIZE can be k,K,m,M,g,G,t,T,p,P,e,E",
 	NULL
 };
 
@@ -231,6 +232,7 @@  static int cmd_qgroup_show(int argc, char **argv)
 	int c;
 	u64 qgroupid;
 	int filter_flag = 0;
+	int block_size = 0;
 
 	struct btrfs_qgroup_comparer_set *comparer_set;
 	struct btrfs_qgroup_filter_set *filter_set;
@@ -238,6 +240,7 @@  static int cmd_qgroup_show(int argc, char **argv)
 	comparer_set = btrfs_qgroup_alloc_comparer_set();
 	struct option long_options[] = {
 		{"sort", 1, NULL, 'S'},
+		{"block-size", 1, NULL, 'B'},
 		{0, 0, 0, 0}
 	};
 
@@ -276,6 +279,13 @@  static int cmd_qgroup_show(int argc, char **argv)
 			if (ret)
 				usage(cmd_qgroup_show_usage);
 			break;
+		case 'B':
+			block_size = parse_block_size(optarg);
+			if (block_size < 0) {
+				fprintf(stderr, "Invalid block size\n");
+				usage(cmd_qgroup_show_usage);
+			}
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
@@ -301,7 +311,7 @@  static int cmd_qgroup_show(int argc, char **argv)
 					BTRFS_QGROUP_FILTER_PARENT,
 					qgroupid);
 	}
-	ret = btrfs_show_qgroups(fd, filter_set, comparer_set);
+	ret = btrfs_show_qgroups(fd, filter_set, comparer_set, block_size);
 	e = errno;
 	close_file_or_dir(fd, dirstream);
 	if (ret < 0)
diff --git a/qgroup.c b/qgroup.c
index fa905fa..0de6c7d 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -20,6 +20,7 @@ 
 #include <sys/ioctl.h>
 #include "ctree.h"
 #include "ioctl.h"
+#include "utils.h"
 
 #define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)
 #define BTRFS_QGROUP_NCOMPS_INCREASE (2 * BTRFS_QGROUP_COMP_MAX)
@@ -190,10 +191,12 @@  static void print_qgroup_column_add_blank(enum btrfs_qgroup_column_enum column,
 }
 
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
-				enum btrfs_qgroup_column_enum column)
+				enum btrfs_qgroup_column_enum column,
+				int block_size)
 {
 	BUG_ON(column >= BTRFS_QGROUP_ALL || column < 0);
 	int len;
+	char tmp[100];
 
 	switch (column) {
 
@@ -203,11 +206,17 @@  static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 		print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = printf("%lld", qgroup->rfer);
+		len = block_size_snprintf((signed long long)qgroup->rfer, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
+		printf("%s", tmp);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_RFER, len);
 		break;
 	case BTRFS_QGROUP_EXCL:
-		len = printf("%lld", qgroup->excl);
+		len = block_size_snprintf((signed long long)qgroup->excl, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
+		printf("%s", tmp);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_EXCL, len);
 		break;
 	case BTRFS_QGROUP_PARENT:
@@ -215,11 +224,17 @@  static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 		print_qgroup_column_add_blank(BTRFS_QGROUP_PARENT, len);
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		len = printf("%llu", qgroup->max_rfer);
+		len = block_size_snprintf(qgroup->max_rfer, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
+		printf("%s", tmp);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_MAX_RFER, len);
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		len = printf("%llu", qgroup->max_excl);
+		len = block_size_snprintf(qgroup->max_excl, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
+		printf("%s", tmp);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_MAX_EXCL, len);
 		break;
 	case BTRFS_QGROUP_CHILD:
@@ -231,14 +246,15 @@  static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 	}
 }
 
-static void print_single_qgroup_table(struct btrfs_qgroup *qgroup)
+static void print_single_qgroup_table(struct btrfs_qgroup *qgroup,
+				      int block_size)
 {
 	int i;
 
 	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
 		if (!btrfs_qgroup_columns[i].need_print)
 			continue;
-		print_qgroup_column(qgroup, i);
+		print_qgroup_column(qgroup, i, block_size);
 
 		if (i != BTRFS_QGROUP_CHILD)
 			printf(" ");
@@ -882,7 +898,8 @@  static int sort_tree_insert(struct qgroup_lookup *sort_tree,
 }
 
 static void __update_columns_max_len(struct btrfs_qgroup *bq,
-				     enum btrfs_qgroup_column_enum column)
+				     enum btrfs_qgroup_column_enum column,
+				     int block_size)
 {
 	BUG_ON(column >= BTRFS_QGROUP_ALL || column < 0);
 	struct btrfs_qgroup_list *list = NULL;
@@ -900,26 +917,30 @@  static void __update_columns_max_len(struct btrfs_qgroup *bq,
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_RFER:
-		sprintf(tmp, "%llu", bq->rfer);
-		len = strlen(tmp);
+		len = block_size_snprintf((signed long long)bq->rfer, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_EXCL:
-		sprintf(tmp, "%llu", bq->excl);
-		len = strlen(tmp);
+		len = block_size_snprintf((signed long long)bq->excl, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		sprintf(tmp, "%llu", bq->max_rfer);
-		len = strlen(tmp);
+		len = block_size_snprintf(bq->max_rfer, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		sprintf(tmp, "%llu", bq->max_excl);
-		len = strlen(tmp);
+		len = block_size_snprintf(bq->max_excl, tmp,
+					sizeof(tmp), block_size);
+		BUG_ON(len < 0);
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
@@ -971,21 +992,22 @@  static void __update_columns_max_len(struct btrfs_qgroup *bq,
 
 }
 
-static void update_columns_max_len(struct btrfs_qgroup *bq)
+static void update_columns_max_len(struct btrfs_qgroup *bq, int block_size)
 {
 	int i;
 
 	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
 		if (!btrfs_qgroup_columns[i].need_print)
 			continue;
-		__update_columns_max_len(bq, i);
+		__update_columns_max_len(bq, i, block_size);
 	}
 }
 
 static void __filter_and_sort_qgroups(struct qgroup_lookup *all_qgroups,
 				 struct qgroup_lookup *sort_tree,
 				 struct btrfs_qgroup_filter_set *filter_set,
-				 struct btrfs_qgroup_comparer_set *comp_set)
+				 struct btrfs_qgroup_comparer_set *comp_set,
+				 int block_size)
 {
 	struct rb_node *n;
 	struct btrfs_qgroup *entry;
@@ -1002,7 +1024,7 @@  static void __filter_and_sort_qgroups(struct qgroup_lookup *all_qgroups,
 		if (ret) {
 			sort_tree_insert(sort_tree, entry, comp_set);
 
-			update_columns_max_len(entry);
+			update_columns_max_len(entry, block_size);
 		}
 		n = rb_prev(n);
 	}
@@ -1131,7 +1153,8 @@  done:
 	return ret;
 }
 
-static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
+static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup,
+			      int block_size)
 {
 
 	struct rb_node *n;
@@ -1142,14 +1165,15 @@  static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
 	n = rb_first(&qgroup_lookup->root);
 	while (n) {
 		entry = rb_entry(n, struct btrfs_qgroup, sort_node);
-		print_single_qgroup_table(entry);
+		print_single_qgroup_table(entry, block_size);
 		n = rb_next(n);
 	}
 }
 
 int btrfs_show_qgroups(int fd,
 		       struct btrfs_qgroup_filter_set *filter_set,
-		       struct btrfs_qgroup_comparer_set *comp_set)
+		       struct btrfs_qgroup_comparer_set *comp_set,
+		       int block_size)
 {
 
 	struct qgroup_lookup qgroup_lookup;
@@ -1159,9 +1183,13 @@  int btrfs_show_qgroups(int fd,
 	ret = __qgroups_search(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
+	/*
+	 * we pass block_size here because we need it to
+	 * update max columns.
+	 */
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
-				  filter_set, comp_set);
-	print_all_qgroups(&sort_tree);
+				  filter_set, comp_set, block_size);
+	print_all_qgroups(&sort_tree, block_size);
 
 	__free_all_qgroups(&qgroup_lookup);
 	btrfs_qgroup_free_filter_set(filter_set);
diff --git a/qgroup.h b/qgroup.h
index 653cf1c..1113a24 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -81,7 +81,8 @@  int btrfs_qgroup_parse_sort_string(char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 u64 btrfs_get_path_rootid(int fd);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
-		       struct btrfs_qgroup_comparer_set *);
+		       struct btrfs_qgroup_comparer_set *,
+		       int block_size);
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
 struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void);
 void btrfs_qgroup_free_filter_set(struct btrfs_qgroup_filter_set *filter_set);
diff --git a/utils.c b/utils.c
index c6022fc..4ed7405 100644
--- a/utils.c
+++ b/utils.c
@@ -1219,6 +1219,56 @@  void pretty_size_snprintf(u64 size, char *str, size_t str_bytes)
 	snprintf(str, str_bytes, "%.2f%s", fraction, size_strs[num_divs]);
 }
 
+int parse_block_size(const char *ch)
+{
+	int len = strlen(ch);
+	if (len != 1)
+		return -1;
+
+	switch (ch[0]) {
+	case 'k':
+	case 'K':
+		return 1;
+	case 'm':
+	case 'M':
+		return 2;
+	case 'g':
+	case 'G':
+		return 3;
+	case 't':
+	case 'T':
+		return 4;
+	case 'p':
+	case 'P':
+		return 5;
+	case 'e':
+	case 'E':
+		return 6;
+	default:
+		return -1;
+	}
+
+	return -1;
+}
+
+int block_size_snprintf(double size, char *str, size_t str_bytes, int format)
+{
+	double fraction = size;
+	int cnt = format;
+
+	if (str_bytes == 0)
+		return 0;
+	if (format < 0 || format >= ARRAY_SIZE(size_strs))
+		return -1;
+	if (format == 0)
+		return snprintf(str, str_bytes, "%.f", size);
+
+	while (format--)
+		fraction /= 1024;
+
+	return snprintf(str, str_bytes, "%.2f%s", fraction, size_strs[cnt]);
+}
+
 /*
  * __strncpy__null - strncpy with null termination
  * @dest:	the target array
diff --git a/utils.h b/utils.h
index 19f028f..40b662d 100644
--- a/utils.h
+++ b/utils.h
@@ -56,6 +56,8 @@  void pretty_size_snprintf(u64 size, char *str, size_t str_bytes);
 		_str;							\
 	})
 
+int parse_block_size(const char *ch);
+int block_size_snprintf(double size, char *str, size_t str_bytes, int format);
 int get_mountpt(char *dev, char *mntpt, size_t size);
 int btrfs_scan_block_devices(int run_ioctl);
 u64 parse_size(char *s);