linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/12] enhance btrfs qgroup show command
@ 2013-10-07  7:21 Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 01/12] Btrfs-progs: restructure show_qgroups Wang Shilong
                   ` (11 more replies)
  0 siblings, 12 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

The patchset enhanced btrfs qgroup show command.

Firstly, we restructure show_qgroups, make it easy to add new features.
And then we add '-p' '-c', '-r',and '-e' options to print the parent
qgroup id, child qgroup id, max referenced size and max exclusive size
of qgroup respectively, add '-F' and '-f' option to list qgroups that
impact the given path.

Besides that, the users may want to sort qgroups according to some items.
For this case, we introduce '--sort' option. With this option, we can sort
the qgroup by qgroupid, rfer, excl, max_rfer and max_excl.

Notice, we force to print result as a table(as david suggest this dosen't matter
for now), and with option '--block-size', user can control to print result,for example,
k,K,m,M,etc.What's more '-h' gives a short cut to allow people to print result in
human readable format size.

You can pull this patchset from the URL:
	git://github.com/wangshilong/Btrfs-progs.git qgroup_v2

This patchset is rebased on david's intergration-20130924.

Changelog:
v2->v3:
	mainly address comments from david.
	1)print result as table in default.
	2)add '--block-size' option
	3)add '-h' option to print size in human readable format.
	4)replace '-l' with '-r' to print max referenced size.
	5)some codes cleanups.
v1->v2:
	rebase the patchset on david's integration-20130920

Wang Shilong (12):
  Btrfs-progs: restructure show_qgroups
  Btrfs-progs: introduces '-p' option to print the ID of the parent
    qgroups
  Btrfs-progs: introduces '-c' option to print the ID of the child
    qgroups
  Btrfs-progs: introduce '-r' option to print max referenced size of
    qgroups
  Btrfs-progs: introduce '-e' option to print max exclusive size of
    qgroups
  Btrfs-progs: list all qgroups impact given path(include ancestral
    qgroups)
  Btrfs-progs: list all qgroups impact given path(exclude ancestral
    qgroups)
  Btrfs-progs: enhance btrfs qgroup show to sort qgroups
  Btrfs-progs: enhance btrfs qgroup to print the result as a table
  Btrfs-progs: add '--block-size' option to control print result
  Btrfs-progs: make pretty_size_snprintf() return len
  Btrfs-progs: add '-h' options to print sizes in human readable format

 cmds-qgroup.c |  197 ++++-----
 ctree.h       |   11 +
 qgroup.c      | 1286 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qgroup.h      |   73 ++++
 utils.c       |   59 ++-
 utils.h       |    6 +-
 6 files changed, 1532 insertions(+), 100 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v3 01/12] Btrfs-progs: restructure show_qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups Wang Shilong
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

The current show_qgroups() just shows a little information, and it is hard to
add some functions which the users need in the future, so i restructure it, make
it easy to add new functions.

In order to improve the scalability of show_qgroups(), i add some important
structures:

	struct qgroup_lookup {
		struct rb_root root;
	}
 	/*
	*store qgroup's information
	*/
	struct btrfs_qgroup {
		struct rb_node  rb_node;
		u64 qgroupid;

		u64 generation;
		u64 rfer;
		u64 rfer_cmpr;
		u64 excl_cmpr;

		u64 flags;
		u64 max_rfer;
		u64 max_excl;
		u64 rsv_rfer;
		u64 rsv_excl;

		struct list_head qgroups;
		struct list_head members;
	}
	/*
	*glue structure to represent the relations
	*between qgroups
	*/
	struct btrfs_qgroup_list {
		struct list_head next_qgroups;
		struct list_head next_member;
		struct btrfs_qgroup *qgroup;
		struct btrfs_qgroup *member;
	}
The above 3 structures are used to manage all the information
of qgroups.

	struct {
		char *name;
		char *column_name;
		int need_print;
	} btrfs_qgroup_columns[]

We define a arrary to manage all the columns that can be
outputed, and use a member variant(->need_print) to control
the output of the relative column. Some columns are outputed
by default. But we can change it according to the requirement
of the users.

For example:
	if outputing max referenced size of qgroup is needed,the function
'btrfs_qgroup_setup_column()' will be called, and the parameter 'BTRFS_QGROUP_MAX_RFER'
(extend in the future) will be passsed to the function. After the function is done,
when showing qgroups, max referenced size of qgroup will be output.

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c |  91 +----------
 ctree.h       |  11 ++
 qgroup.c      | 509 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qgroup.h      |  10 ++
 4 files changed, 531 insertions(+), 90 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index ff2a1fa..d3c699f 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -106,95 +106,6 @@ static int qgroup_create(int create, int argc, char **argv)
 	return 0;
 }
 
-static void print_qgroup_info(u64 objectid, struct btrfs_qgroup_info_item *info)
-{
-	printf("%llu/%llu %lld %lld\n", objectid >> 48,
-		objectid & ((1ll << 48) - 1),
-		btrfs_stack_qgroup_info_referenced(info),
-		btrfs_stack_qgroup_info_exclusive(info));
-}
-
-static int list_qgroups(int fd)
-{
-	int ret;
-	struct btrfs_ioctl_search_args args;
-	struct btrfs_ioctl_search_key *sk = &args.key;
-	struct btrfs_ioctl_search_header *sh;
-	unsigned long off = 0;
-	unsigned int i;
-	struct btrfs_qgroup_info_item *info;
-
-	memset(&args, 0, sizeof(args));
-
-	/* search in the quota tree */
-	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
-
-	/*
-	 * set the min and max to backref keys.  The search will
-	 * only send back this type of key now.
-	 */
-	sk->max_type = BTRFS_QGROUP_INFO_KEY;
-	sk->min_type = BTRFS_QGROUP_INFO_KEY;
-	sk->max_objectid = 0;
-	sk->max_offset = (u64)-1;
-	sk->max_transid = (u64)-1;
-
-	/* just a big number, doesn't matter much */
-	sk->nr_items = 4096;
-
-	while (1) {
-		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-		if (ret < 0)
-			return ret;
-
-		/* the ioctl returns the number of item it found in nr_items */
-		if (sk->nr_items == 0)
-			break;
-
-		off = 0;
-
-		/*
-		 * for each item, pull the key out of the header and then
-		 * read the root_ref item it contains
-		 */
-		for (i = 0; i < sk->nr_items; i++) {
-			sh = (struct btrfs_ioctl_search_header *)(args.buf +
-								  off);
-			off += sizeof(*sh);
-
-			if (sh->objectid != 0)
-				goto done;
-
-			if (sh->type != BTRFS_QGROUP_INFO_KEY)
-				goto done;
-
-			info = (struct btrfs_qgroup_info_item *)
-					(args.buf + off);
-			print_qgroup_info(sh->offset, info);
-
-			off += sh->len;
-
-			/*
-			 * record the mins in sk so we can make sure the
-			 * next search doesn't repeat this root
-			 */
-			sk->min_offset = sh->offset;
-		}
-		sk->nr_items = 4096;
-		/*
-		 * this iteration is done, step forward one qgroup for the next
-		 * ioctl
-		 */
-		if (sk->min_offset < (u64)-1)
-			sk->min_offset++;
-		else
-			break;
-	}
-
-done:
-	return ret;
-}
-
 static int parse_limit(const char *p, unsigned long long *s)
 {
 	char *endptr;
@@ -313,7 +224,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 		return 1;
 	}
 
-	ret = list_qgroups(fd);
+	ret = btrfs_show_qgroups(fd);
 	e = errno;
 	close_file_or_dir(fd, dirstream);
 	if (ret < 0)
diff --git a/ctree.h b/ctree.h
index 5b4c859..c90581a 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2059,6 +2059,17 @@ BTRFS_SETGET_FUNCS(qgroup_limit_rsv_referenced, struct btrfs_qgroup_limit_item,
 BTRFS_SETGET_FUNCS(qgroup_limit_rsv_exclusive, struct btrfs_qgroup_limit_item,
 		   rsv_exclusive, 64);
 
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_flags,
+			 struct btrfs_qgroup_limit_item, flags, 64);
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_max_referenced,
+			 struct btrfs_qgroup_limit_item, max_referenced, 64);
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_max_exclusive,
+			 struct btrfs_qgroup_limit_item, max_exclusive, 64);
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_rsv_referenced,
+			 struct btrfs_qgroup_limit_item, rsv_referenced, 64);
+BTRFS_SETGET_STACK_FUNCS(stack_qgroup_limit_rsv_exclusive,
+			 struct btrfs_qgroup_limit_item, rsv_exclusive, 64);
+
 /* this returns the number of file bytes represented by the inline item.
  * If an item is compressed, this is the uncompressed size
  */
diff --git a/qgroup.c b/qgroup.c
index 86fe2b2..bd9658e 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -17,7 +17,516 @@
  */
 
 #include "qgroup.h"
+#include <sys/ioctl.h>
 #include "ctree.h"
+#include "ioctl.h"
+
+struct qgroup_lookup {
+	struct rb_root root;
+};
+
+struct btrfs_qgroup {
+	struct rb_node rb_node;
+	u64 qgroupid;
+
+	/*
+	 * info_item
+	 */
+	u64 generation;
+	u64 rfer;	/*referenced*/
+	u64 rfer_cmpr;	/*referenced compressed*/
+	u64 excl;	/*exclusive*/
+	u64 excl_cmpr;	/*exclusive compressed*/
+
+	/*
+	 *limit_item
+	 */
+	u64 flags;	/*which limits are set*/
+	u64 max_rfer;
+	u64 max_excl;
+	u64 rsv_rfer;
+	u64 rsv_excl;
+
+	/*qgroups this group is member of*/
+	struct list_head qgroups;
+	/*qgroups that are members of this group*/
+	struct list_head members;
+};
+
+/*
+ * glue structure to represent the relations
+ * between qgroups
+ */
+struct btrfs_qgroup_list {
+	struct list_head next_qgroup;
+	struct list_head next_member;
+	struct btrfs_qgroup *qgroup;
+	struct btrfs_qgroup *member;
+};
+
+/*
+ * qgroupid,rfer,excl default to set
+ */
+struct {
+	char *name;
+	char *column_name;
+	int need_print;
+} btrfs_qgroup_columns[] = {
+	{
+		.name		= "qgroupid",
+		.column_name	= "Qgroupid",
+		.need_print	= 1,
+	},
+	{
+		.name		= "rfer",
+		.column_name	= "Rfer",
+		.need_print	= 1,
+	},
+	{
+		.name		= "excl",
+		.column_name	= "Excl",
+		.need_print	= 1,
+	},
+	{
+		.name		= NULL,
+		.column_name	= NULL,
+		.need_print	= 0,
+	},
+};
+
+void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
+{
+	int i;
+
+	BUG_ON(column < 0 || column > BTRFS_QGROUP_ALL);
+
+	if (column < BTRFS_QGROUP_ALL) {
+		btrfs_qgroup_columns[column].need_print = 1;
+		return;
+	}
+	for (i = 0; i < BTRFS_QGROUP_ALL; i++)
+		btrfs_qgroup_columns[i].need_print = 1;
+}
+
+static void print_qgroup_column(struct btrfs_qgroup *qgroup,
+				enum btrfs_qgroup_column_enum column)
+{
+	BUG_ON(column >= BTRFS_QGROUP_ALL || column < 0);
+
+	switch (column) {
+
+	case BTRFS_QGROUP_QGROUPID:
+		printf("%llu/%llu", qgroup->qgroupid >> 48,
+		       ((1ll << 48) - 1) & qgroup->qgroupid);
+		break;
+	case BTRFS_QGROUP_RFER:
+		printf("%lld", qgroup->rfer);
+		break;
+	case BTRFS_QGROUP_EXCL:
+		printf("%lld", qgroup->excl);
+		break;
+	default:
+		break;
+	}
+}
+
+static void print_single_qgroup_default(struct btrfs_qgroup *qgroup)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+		if (!btrfs_qgroup_columns[i].need_print)
+			continue;
+		print_qgroup_column(qgroup, i);
+
+		if (i != BTRFS_QGROUP_ALL - 1)
+			printf(" ");
+	}
+	printf("\n");
+}
+
+static void qgroup_lookup_init(struct qgroup_lookup *tree)
+{
+	tree->root.rb_node = NULL;
+}
+
+static int comp_entry_with_qgroupid(struct btrfs_qgroup *entry1,
+				    struct btrfs_qgroup *entry2,
+				    int is_descending)
+{
+
+	int ret;
+
+	if (entry1->qgroupid > entry2->qgroupid)
+		ret = 1;
+	else if (entry1->qgroupid < entry2->qgroupid)
+		ret = -1;
+	else
+		ret = 0;
+
+	return is_descending ? -ret : ret;
+}
+
+/*
+ * insert a new root into the tree.  returns the existing root entry
+ * if one is already there.  qgroupid is used
+ * as the key
+ */
+static int qgroup_tree_insert(struct qgroup_lookup *root_tree,
+			      struct btrfs_qgroup *ins)
+{
+
+	struct rb_node **p = &root_tree->root.rb_node;
+	struct rb_node *parent = NULL;
+	struct btrfs_qgroup *curr;
+	int ret;
+
+	while (*p) {
+		parent = *p;
+		curr = rb_entry(parent, struct btrfs_qgroup, rb_node);
+
+		ret = comp_entry_with_qgroupid(ins, curr, 0);
+		if (ret < 0)
+			p = &(*p)->rb_left;
+		else if (ret > 0)
+			p = &(*p)->rb_right;
+		else
+			return -EEXIST;
+	}
+	rb_link_node(&ins->rb_node, parent, p);
+	rb_insert_color(&ins->rb_node, &root_tree->root);
+	return 0;
+}
+
+/*
+ *find a given qgroupid in the tree. We return the smallest one,
+ *rb_next can be used to move forward looking for more if required
+ */
+static struct btrfs_qgroup *qgroup_tree_search(struct qgroup_lookup *root_tree,
+					       u64 qgroupid)
+{
+	struct rb_node *n = root_tree->root.rb_node;
+	struct btrfs_qgroup *entry;
+	struct btrfs_qgroup tmp;
+	int ret;
+
+	tmp.qgroupid = qgroupid;
+
+	while (n) {
+		entry = rb_entry(n, struct btrfs_qgroup, rb_node);
+
+		ret = comp_entry_with_qgroupid(&tmp, entry, 0);
+		if (ret < 0)
+			n = n->rb_left;
+		else if (ret > 0)
+			n = n->rb_right;
+		else
+			return entry;
+
+	}
+	return NULL;
+}
+
+static int update_qgroup(struct qgroup_lookup *qgroup_lookup, u64 qgroupid,
+			 u64 generation, u64 rfer, u64 rfer_cmpr, u64 excl,
+			 u64 excl_cmpr, u64 flags, u64 max_rfer, u64 max_excl,
+			 u64 rsv_rfer, u64 rsv_excl, struct btrfs_qgroup *pa,
+			 struct btrfs_qgroup *child)
+{
+	struct btrfs_qgroup *bq;
+	struct btrfs_qgroup_list *list;
+
+	bq = qgroup_tree_search(qgroup_lookup, qgroupid);
+	if (!bq || bq->qgroupid != qgroupid)
+		return -ENOENT;
+
+	if (generation)
+		bq->generation = generation;
+	if (rfer)
+		bq->rfer = rfer;
+	if (rfer_cmpr)
+		bq->rfer_cmpr = rfer_cmpr;
+	if (excl)
+		bq->excl = excl;
+	if (excl_cmpr)
+		bq->excl_cmpr = excl_cmpr;
+	if (flags)
+		bq->flags = flags;
+	if (max_rfer)
+		bq->max_rfer = max_rfer;
+	if (max_excl)
+		bq->max_excl = max_excl;
+	if (rsv_rfer)
+		bq->rsv_rfer = rsv_rfer;
+	if (pa && child) {
+		list = malloc(sizeof(*list));
+		if (!list) {
+			fprintf(stderr, "memory allocation failed\n");
+			exit(1);
+		}
+		list->qgroup = pa;
+		list->member = child;
+		list_add_tail(&list->next_qgroup, &child->qgroups);
+		list_add_tail(&list->next_member, &pa->members);
+	}
+	return 0;
+}
+
+static int add_qgroup(struct qgroup_lookup *qgroup_lookup, u64 qgroupid,
+		      u64 generation, u64 rfer, u64 rfer_cmpr, u64 excl,
+		      u64 excl_cmpr, u64 flags, u64 max_rfer, u64 max_excl,
+		      u64 rsv_rfer, u64 rsv_excl, struct btrfs_qgroup *parent,
+		      struct btrfs_qgroup *child)
+{
+	struct btrfs_qgroup *bq;
+	struct btrfs_qgroup_list *list;
+	int ret;
+
+	ret = update_qgroup(qgroup_lookup, qgroupid, generation, rfer,
+			    rfer_cmpr, excl, excl_cmpr, flags, max_rfer,
+			    max_excl, rsv_rfer, rsv_excl, parent, child);
+	if (!ret)
+		return 0;
+
+	bq = malloc(sizeof(*bq));
+	if (!bq) {
+		printf("memory allocation failed\n");
+		exit(1);
+	}
+	memset(bq, 0, sizeof(*bq));
+	if (qgroupid) {
+		bq->qgroupid = qgroupid;
+		INIT_LIST_HEAD(&bq->qgroups);
+		INIT_LIST_HEAD(&bq->members);
+	}
+	if (generation)
+		bq->generation = generation;
+	if (rfer)
+		bq->rfer = rfer;
+	if (rfer_cmpr)
+		bq->rfer_cmpr = rfer_cmpr;
+	if (excl)
+		bq->excl = excl;
+	if (excl_cmpr)
+		bq->excl_cmpr = excl_cmpr;
+	if (flags)
+		bq->flags = flags;
+	if (max_rfer)
+		bq->max_rfer = max_rfer;
+	if (max_excl)
+		bq->max_excl = max_excl;
+	if (rsv_rfer)
+		bq->rsv_rfer = rsv_rfer;
+	if (parent && child) {
+		list = malloc(sizeof(*list));
+		if (!list) {
+			fprintf(stderr, "memory allocation failed\n");
+			exit(1);
+		}
+		list->qgroup = parent;
+		list->member = child;
+		list_add_tail(&list->next_qgroup, &child->qgroups);
+		list_add_tail(&list->next_member, &parent->members);
+	}
+	ret = qgroup_tree_insert(qgroup_lookup, bq);
+	if (ret) {
+		printf("failed to insert tree %llu\n",
+		       bq->qgroupid);
+		exit(1);
+	}
+	return ret;
+}
+
+void __free_btrfs_qgroup(struct btrfs_qgroup *bq)
+{
+	struct btrfs_qgroup_list *list;
+	while (!list_empty(&bq->qgroups)) {
+		list = list_entry((&bq->qgroups)->next,
+				  struct btrfs_qgroup_list,
+				  next_qgroup);
+		list_del(&list->next_qgroup);
+		list_del(&list->next_member);
+		free(list);
+	}
+	while (!list_empty(&bq->members)) {
+		list = list_entry((&bq->members)->next,
+				  struct btrfs_qgroup_list,
+				  next_member);
+		list_del(&list->next_qgroup);
+		list_del(&list->next_member);
+		free(list);
+	}
+	free(bq);
+}
+
+void __free_all_qgroups(struct qgroup_lookup *root_tree)
+{
+	struct btrfs_qgroup *entry;
+	struct rb_node *n;
+
+	n = rb_first(&root_tree->root);
+	while (n) {
+		entry = rb_entry(n, struct btrfs_qgroup, rb_node);
+		rb_erase(n, &root_tree->root);
+		__free_btrfs_qgroup(entry);
+
+		n = rb_first(&root_tree->root);
+	}
+}
+
+static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
+{
+	int ret;
+	struct btrfs_ioctl_search_args args;
+	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_ioctl_search_header *sh;
+	unsigned long off = 0;
+	unsigned int i;
+	int e;
+	struct btrfs_qgroup_info_item *info;
+	struct btrfs_qgroup_limit_item *limit;
+	struct btrfs_qgroup *bq;
+	struct btrfs_qgroup *bq1;
+	u64 a1;
+	u64 a2;
+	u64 a3;
+	u64 a4;
+	u64 a5;
+
+	memset(&args, 0, sizeof(args));
+
+	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
+	sk->max_type = BTRFS_QGROUP_RELATION_KEY;
+	sk->min_type = BTRFS_QGROUP_INFO_KEY;
+	sk->max_objectid = (u64)-1;
+	sk->max_offset = (u64)-1;
+	sk->max_transid = (u64)-1;
+	sk->nr_items = 4096;
+
+	qgroup_lookup_init(qgroup_lookup);
+
+	while (1) {
+		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+		e = errno;
+		if (ret < 0) {
+			fprintf(stderr,
+				"ERROR: can't perform the search - %s\n",
+				strerror(e));
+			return ret;
+		}
+		/* the ioctl returns the number of item it found in nr_items */
+		if (sk->nr_items == 0)
+			break;
+
+		off = 0;
+		/*
+		 * for each item, pull the key out of the header and then
+		 * read the root_ref item it contains
+		 */
+		for (i = 0; i < sk->nr_items; i++) {
+			sh = (struct btrfs_ioctl_search_header *)(args.buf +
+								  off);
+			off += sizeof(*sh);
+
+			if (sh->type == BTRFS_QGROUP_INFO_KEY) {
+				info = (struct btrfs_qgroup_info_item *)
+				       (args.buf + off);
+				a1 = btrfs_stack_qgroup_info_generation(info);
+				a2 = btrfs_stack_qgroup_info_referenced(info);
+				a3 =
+				  btrfs_stack_qgroup_info_referenced_compressed
+				  (info);
+				a4 = btrfs_stack_qgroup_info_exclusive(info);
+				a5 =
+				  btrfs_stack_qgroup_info_exclusive_compressed
+				  (info);
+				add_qgroup(qgroup_lookup, sh->offset, a1, a2,
+					   a3, a4, a5, 0, 0, 0, 0, 0, 0, 0);
+			} else if (sh->type == BTRFS_QGROUP_LIMIT_KEY) {
+				limit = (struct btrfs_qgroup_limit_item *)
+				    (args.buf + off);
+
+				a1 = btrfs_stack_qgroup_limit_flags(limit);
+				a2 = btrfs_stack_qgroup_limit_max_referenced
+				     (limit);
+				a3 = btrfs_stack_qgroup_limit_max_exclusive
+				     (limit);
+				a4 = btrfs_stack_qgroup_limit_rsv_referenced
+				     (limit);
+				a5 = btrfs_stack_qgroup_limit_rsv_exclusive
+				     (limit);
+				add_qgroup(qgroup_lookup, sh->offset, 0, 0,
+					   0, 0, 0, a1, a2, a3, a4, a5, 0, 0);
+			} else if (sh->type == BTRFS_QGROUP_RELATION_KEY) {
+				if (sh->offset < sh->objectid)
+					goto skip;
+				bq = qgroup_tree_search(qgroup_lookup,
+							sh->offset);
+				if (!bq)
+					goto skip;
+				bq1 = qgroup_tree_search(qgroup_lookup,
+							 sh->objectid);
+				if (!bq1)
+					goto skip;
+				add_qgroup(qgroup_lookup, sh->offset, 0, 0,
+					   0, 0, 0, 0, 0, 0, 0, 0, bq, bq1);
+			} else
+				goto done;
+skip:
+			off += sh->len;
+
+			/*
+			 * record the mins in sk so we can make sure the
+			 * next search doesn't repeat this root
+			 */
+			sk->min_type = sh->type;
+			sk->min_offset = sh->offset;
+			sk->min_objectid = sh->objectid;
+		}
+		sk->nr_items = 4096;
+		/*
+		 * this iteration is done, step forward one qgroup for the next
+		 * ioctl
+		 */
+		if (sk->min_offset < (u64)-1)
+			sk->min_offset++;
+		else
+			break;
+	}
+
+done:
+	return ret;
+}
+
+static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
+{
+
+	struct rb_node *n;
+	struct btrfs_qgroup *entry;
+
+	n = rb_first(&qgroup_lookup->root);
+	while (n) {
+		entry = rb_entry(n, struct btrfs_qgroup, rb_node);
+		print_single_qgroup_default(entry);
+		n = rb_next(n);
+	}
+}
+
+int btrfs_show_qgroups(int fd)
+{
+
+	struct qgroup_lookup qgroup_lookup;
+	int ret;
+
+	ret = __qgroups_search(fd, &qgroup_lookup);
+	if (ret)
+		return ret;
+
+	print_all_qgroups(&qgroup_lookup);
+	__free_all_qgroups(&qgroup_lookup);
+
+	return ret;
+}
 
 u64 parse_qgroupid(char *p)
 {
diff --git a/qgroup.h b/qgroup.h
index da6d113..8b34cd7 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -22,6 +22,16 @@
 #include "ioctl.h"
 #include "kerncompat.h"
 
+enum btrfs_qgroup_column_enum {
+	BTRFS_QGROUP_QGROUPID,
+	BTRFS_QGROUP_RFER,
+	BTRFS_QGROUP_EXCL,
+	BTRFS_QGROUP_ALL,
+};
+
+int  btrfs_show_qgroups(int fd);
+void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
+
 u64 parse_qgroupid(char *p);
 int qgroup_inherit_size(struct btrfs_qgroup_inherit *p);
 int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 01/12] Btrfs-progs: restructure show_qgroups Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-08 15:06   ` David Sterba
  2013-10-07  7:21 ` [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups Wang Shilong
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduces '-p' option to print the ID of the parent qgroups.
You may use it like:

	btrfs qgroup show -p <path>
For Example:
                qgroupid(2/0)
                /         \
               /           \
              /             \
        qgroupid(1/0)  qgroupid(1/1)
              \              /
               \            /
                qgroupid(0/1)

If we use the command:

	btrfs qgroup show -p <path>
The result will output
	0/1 -- -- 1/0,1/1
	1/0 -- -- 2/0
	1/1 -- -- 2/0
	2/0 -- -- --

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c | 23 ++++++++++++++++++++---
 qgroup.c      | 22 ++++++++++++++++++++++
 qgroup.h      |  1 +
 3 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index d3c699f..96098c1 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,22 +202,39 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show <path>",
+	"btrfs qgroup show -p <path>",
 	"Show all subvolume quota groups.",
+	"-p		print parent qgroup id",
 	NULL
 };
 
 static int cmd_qgroup_show(int argc, char **argv)
 {
+	char *path;
 	int ret = 0;
 	int fd;
 	int e;
-	char *path = argv[1];
 	DIR *dirstream = NULL;
+	int c;
 
-	if (check_argc_exact(argc, 2))
+	optind = 1;
+	while (1) {
+		c = getopt(argc, argv, "p");
+		if (c < 0)
+			break;
+		switch (c) {
+		case 'p':
+			btrfs_qgroup_setup_print_column(
+				BTRFS_QGROUP_PARENT);
+			break;
+		default:
+			usage(cmd_qgroup_show_usage);
+		}
+	}
+	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_qgroup_show_usage);
 
+	path = argv[optind];
 	fd = open_file_or_dir(path, &dirstream);
 	if (fd < 0) {
 		fprintf(stderr, "ERROR: can't access '%s'\n", path);
diff --git a/qgroup.c b/qgroup.c
index bd9658e..0dbf28c 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -88,6 +88,11 @@ struct {
 		.need_print	= 1,
 	},
 	{
+		.name		= "parent",
+		.column_name	= "Parent",
+		.need_print	= 0,
+	},
+	{
 		.name		= NULL,
 		.column_name	= NULL,
 		.need_print	= 0,
@@ -108,6 +113,20 @@ void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
 		btrfs_qgroup_columns[i].need_print = 1;
 }
 
+static void print_parent_column(struct btrfs_qgroup *qgroup)
+{
+	struct btrfs_qgroup_list *list = NULL;
+
+	list_for_each_entry(list, &qgroup->qgroups, next_qgroup) {
+		printf("%llu/%llu", (list->qgroup)->qgroupid >> 48,
+		      ((1ll << 48) - 1) & (list->qgroup)->qgroupid);
+		if (!list_is_last(&list->next_qgroup, &qgroup->qgroups))
+			printf(",");
+	}
+	if (list_empty(&qgroup->qgroups))
+		printf("---");
+}
+
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 				enum btrfs_qgroup_column_enum column)
 {
@@ -125,6 +144,9 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 	case BTRFS_QGROUP_EXCL:
 		printf("%lld", qgroup->excl);
 		break;
+	case BTRFS_QGROUP_PARENT:
+		print_parent_column(qgroup);
+		break;
 	default:
 		break;
 	}
diff --git a/qgroup.h b/qgroup.h
index 8b34cd7..cefdfe1 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -26,6 +26,7 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_QGROUPID,
 	BTRFS_QGROUP_RFER,
 	BTRFS_QGROUP_EXCL,
+	BTRFS_QGROUP_PARENT,
 	BTRFS_QGROUP_ALL,
 };
 
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 01/12] Btrfs-progs: restructure show_qgroups Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-08 15:08   ` David Sterba
  2013-10-07  7:21 ` [PATCH v3 04/12] Btrfs-progs: introduce '-r' option to print max referenced size of qgroups Wang Shilong
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduces '-c' option to print the ID of the child qgroups.
You may use it like:
	btrfs qgroup show -c <path>

For Example:

                qgroupid(2/0)
                 /       \
                /         \
               /           \
            qgroupid(1/0) qgroupid(1/1)
               \            /
                \          /
		 qgroupid(0/1)

If we use the command:

	btrfs qgroup show -c <path>
The result will output
	0/1 -- -- --
	1/0 -- -- 0/1
	1/1 -- -- 0/1
	2/0 -- -- 1/0,1/1

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c |  9 +++++++--
 qgroup.c      | 22 ++++++++++++++++++++++
 qgroup.h      |  1 +
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 96098c1..147bedc 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,9 +202,10 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -p <path>",
+	"btrfs qgroup show -pc <path>",
 	"Show all subvolume quota groups.",
 	"-p		print parent qgroup id",
+	"-c		print child qgroup id",
 	NULL
 };
 
@@ -219,7 +220,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "p");
+		c = getopt(argc, argv, "pc");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -227,6 +228,10 @@ static int cmd_qgroup_show(int argc, char **argv)
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_PARENT);
 			break;
+		case 'c':
+			btrfs_qgroup_setup_print_column(
+				BTRFS_QGROUP_CHILD);
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
diff --git a/qgroup.c b/qgroup.c
index 0dbf28c..1592dd4 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -93,6 +93,11 @@ struct {
 		.need_print	= 0,
 	},
 	{
+		.name		= "child",
+		.column_name	= "Child",
+		.need_print	= 0,
+	},
+	{
 		.name		= NULL,
 		.column_name	= NULL,
 		.need_print	= 0,
@@ -127,6 +132,20 @@ static void print_parent_column(struct btrfs_qgroup *qgroup)
 		printf("---");
 }
 
+static void print_child_column(struct btrfs_qgroup *qgroup)
+{
+	struct btrfs_qgroup_list *list = NULL;
+
+	list_for_each_entry(list, &qgroup->members, next_member) {
+		printf("%llu/%llu", (list->member)->qgroupid >> 48,
+		      ((1ll << 48) - 1) & (list->member)->qgroupid);
+		if (!list_is_last(&list->next_member, &qgroup->members))
+			printf(",");
+	}
+	if (list_empty(&qgroup->members))
+		printf("---");
+}
+
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 				enum btrfs_qgroup_column_enum column)
 {
@@ -147,6 +166,9 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 	case BTRFS_QGROUP_PARENT:
 		print_parent_column(qgroup);
 		break;
+	case BTRFS_QGROUP_CHILD:
+		print_child_column(qgroup);
+		break;
 	default:
 		break;
 	}
diff --git a/qgroup.h b/qgroup.h
index cefdfe1..33682ae 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -27,6 +27,7 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_RFER,
 	BTRFS_QGROUP_EXCL,
 	BTRFS_QGROUP_PARENT,
+	BTRFS_QGROUP_CHILD,
 	BTRFS_QGROUP_ALL,
 };
 
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 04/12] Btrfs-progs: introduce '-r' option to print max referenced size of qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (2 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 05/12] Btrfs-progs: introduce '-e' option to print max exclusive " Wang Shilong
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduces '-r' option to print max referenced size of qgroups.
You may use it like:

		btrfs qgroup show -r <path>

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c | 9 +++++++--
 qgroup.c      | 7 +++++++
 qgroup.h      | 1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 147bedc..213cbde 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,10 +202,11 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pc <path>",
+	"btrfs qgroup show -pcr <path>",
 	"Show all subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
+	"-r		print max referenced size of qgroup",
 	NULL
 };
 
@@ -220,7 +221,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "pc");
+		c = getopt(argc, argv, "pcr");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -232,6 +233,10 @@ static int cmd_qgroup_show(int argc, char **argv)
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_CHILD);
 			break;
+		case 'r':
+			btrfs_qgroup_setup_print_column(
+				BTRFS_QGROUP_MAX_RFER);
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
diff --git a/qgroup.c b/qgroup.c
index 1592dd4..f9eb52d 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -87,6 +87,10 @@ struct {
 		.column_name	= "Excl",
 		.need_print	= 1,
 	},
+	{	.name		= "max_rfer",
+		.column_name	= "Max_rfer",
+		.need_print	= 0,
+	},
 	{
 		.name		= "parent",
 		.column_name	= "Parent",
@@ -166,6 +170,9 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 	case BTRFS_QGROUP_PARENT:
 		print_parent_column(qgroup);
 		break;
+	case BTRFS_QGROUP_MAX_RFER:
+		printf("%llu", qgroup->max_rfer);
+		break;
 	case BTRFS_QGROUP_CHILD:
 		print_child_column(qgroup);
 		break;
diff --git a/qgroup.h b/qgroup.h
index 33682ae..168fac0 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -26,6 +26,7 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_QGROUPID,
 	BTRFS_QGROUP_RFER,
 	BTRFS_QGROUP_EXCL,
+	BTRFS_QGROUP_MAX_RFER,
 	BTRFS_QGROUP_PARENT,
 	BTRFS_QGROUP_CHILD,
 	BTRFS_QGROUP_ALL,
-- 
1.8.3.1

--
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-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 05/12] Btrfs-progs: introduce '-e' option to print max exclusive size of qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (3 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 04/12] Btrfs-progs: introduce '-r' option to print max referenced size of qgroups Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 06/12] Btrfs-progs: list all qgroups impact given path(include ancestral qgroups) Wang Shilong
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduce '-e' option to print max exclusive size of qgroups.
You may use it like this:
		btrfs qgroup -e <path>

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c | 9 +++++++--
 qgroup.c      | 8 ++++++++
 qgroup.h      | 1 +
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 213cbde..fc9ad2f 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,11 +202,12 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pcr <path>",
+	"btrfs qgroup show -pcre <path>",
 	"Show all subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
 	"-r		print max referenced size of qgroup",
+	"-e		print max exclusive size of qgroup",
 	NULL
 };
 
@@ -221,7 +222,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "pcr");
+		c = getopt(argc, argv, "pcre");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -237,6 +238,10 @@ static int cmd_qgroup_show(int argc, char **argv)
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_MAX_RFER);
 			break;
+		case 'e':
+			btrfs_qgroup_setup_print_column(
+				BTRFS_QGROUP_MAX_EXCL);
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
diff --git a/qgroup.c b/qgroup.c
index f9eb52d..2cd37b1 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -92,6 +92,11 @@ struct {
 		.need_print	= 0,
 	},
 	{
+		.name		= "max_excl",
+		.column_name	= "Max_excl",
+		.need_print	= 0,
+	},
+	{
 		.name		= "parent",
 		.column_name	= "Parent",
 		.need_print	= 0,
@@ -173,6 +178,9 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 	case BTRFS_QGROUP_MAX_RFER:
 		printf("%llu", qgroup->max_rfer);
 		break;
+	case BTRFS_QGROUP_MAX_EXCL:
+		printf("%llu", qgroup->max_excl);
+		break;
 	case BTRFS_QGROUP_CHILD:
 		print_child_column(qgroup);
 		break;
diff --git a/qgroup.h b/qgroup.h
index 168fac0..e7a65ba 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -27,6 +27,7 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_RFER,
 	BTRFS_QGROUP_EXCL,
 	BTRFS_QGROUP_MAX_RFER,
+	BTRFS_QGROUP_MAX_EXCL,
 	BTRFS_QGROUP_PARENT,
 	BTRFS_QGROUP_CHILD,
 	BTRFS_QGROUP_ALL,
-- 
1.8.3.1

--
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-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 06/12] Btrfs-progs: list all qgroups impact given path(include ancestral qgroups)
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (4 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 05/12] Btrfs-progs: introduce '-e' option to print max exclusive " Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 07/12] Btrfs-progs: list all qgroups impact given path(exclude " Wang Shilong
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduces '-F' option which can help you filter the qgroups
by the path name, you may use it like:

	btrfs qgroup show -F <path>
For example:

                         qgroupid(2/0)
                          /     \
                         /       \
                        qgroupid(1/0)
                        /         \
                       /           \
                      /             \
                  qgroupid(0/1)   qgroupid(0/2)
                  sub1              sub2
                  /  \
                 /    \
		dir1  file1

If we use the command:
	btrfs qgroup show -F sub1/dir1
The result will output
	0/1	--	--
	1/0	--	--
	2/0	--	--

'-F' option help you list all qgroups impact given path.
(include ancestral qgroups).

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c |  24 +++++-
 qgroup.c      | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 qgroup.h      |  28 ++++++-
 3 files changed, 281 insertions(+), 10 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index fc9ad2f..7c6c917 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,12 +202,14 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pcre <path>",
-	"Show all subvolume quota groups.",
+	"btrfs qgroup show -pcreF <path>",
+	"Show subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
 	"-r		print max referenced size of qgroup",
 	"-e		print max exclusive size of qgroup",
+	"-F		list all qgroups which impact the given path"
+	"(include ancestral qgroups)",
 	NULL
 };
 
@@ -219,10 +221,15 @@ static int cmd_qgroup_show(int argc, char **argv)
 	int e;
 	DIR *dirstream = NULL;
 	int c;
+	u64 qgroupid;
+	int filter_flag = 0;
+
+	struct btrfs_qgroup_filter_set *filter_set;
+	filter_set = btrfs_qgroup_alloc_filter_set();
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "pcre");
+		c = getopt(argc, argv, "pcreF");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -242,6 +249,9 @@ static int cmd_qgroup_show(int argc, char **argv)
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_MAX_EXCL);
 			break;
+		case 'F':
+			filter_flag |= 0x1;
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
@@ -256,7 +266,13 @@ static int cmd_qgroup_show(int argc, char **argv)
 		return 1;
 	}
 
-	ret = btrfs_show_qgroups(fd);
+	if (filter_flag) {
+		qgroupid = btrfs_get_path_rootid(fd);
+		btrfs_qgroup_setup_filter(&filter_set,
+				BTRFS_QGROUP_FILTER_ALL_PARENT,
+				qgroupid);
+	}
+	ret = btrfs_show_qgroups(fd, filter_set);
 	e = errno;
 	close_file_or_dir(fd, dirstream);
 	if (ret < 0)
diff --git a/qgroup.c b/qgroup.c
index 2cd37b1..306b638 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -21,12 +21,20 @@
 #include "ctree.h"
 #include "ioctl.h"
 
+#define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)
+
 struct qgroup_lookup {
 	struct rb_root root;
 };
 
 struct btrfs_qgroup {
 	struct rb_node rb_node;
+	struct rb_node sort_node;
+	/*
+	 *all_parent_node is used to
+	 *filter a qgroup's all parent
+	 */
+	struct rb_node all_parent_node;
 	u64 qgroupid;
 
 	/*
@@ -113,6 +121,8 @@ struct {
 	},
 };
 
+static btrfs_qgroup_filter_func all_filter_funcs[];
+
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
 {
 	int i;
@@ -433,6 +443,205 @@ void __free_all_qgroups(struct qgroup_lookup *root_tree)
 	}
 }
 
+static int filter_all_parent_insert(struct qgroup_lookup *sort_tree,
+				    struct btrfs_qgroup *bq)
+{
+	struct rb_node **p = &sort_tree->root.rb_node;
+	struct rb_node *parent = NULL;
+	struct btrfs_qgroup *curr;
+	int ret;
+
+	while (*p) {
+		parent = *p;
+		curr = rb_entry(parent, struct btrfs_qgroup, all_parent_node);
+
+		ret = comp_entry_with_qgroupid(bq, curr, 0);
+		if (ret < 0)
+			p = &(*p)->rb_left;
+		else if (ret > 0)
+			p = &(*p)->rb_right;
+		else
+			return -EEXIST;
+	}
+	rb_link_node(&bq->all_parent_node, parent, p);
+	rb_insert_color(&bq->all_parent_node, &sort_tree->root);
+	return 0;
+}
+
+static int filter_by_all_parent(struct btrfs_qgroup *bq, u64 data)
+{
+	struct qgroup_lookup lookup;
+	struct qgroup_lookup *ql = &lookup;
+	struct btrfs_qgroup_list *list;
+	struct rb_node *n;
+	struct btrfs_qgroup *qgroup =
+			 (struct btrfs_qgroup *)(unsigned long)data;
+
+	if (data == 0)
+		return 0;
+	if (bq->qgroupid == qgroup->qgroupid)
+		return 1;
+
+	qgroup_lookup_init(ql);
+	filter_all_parent_insert(ql, qgroup);
+	n = rb_first(&ql->root);
+	while (n) {
+		qgroup = rb_entry(n, struct btrfs_qgroup, all_parent_node);
+		if (!list_empty(&qgroup->qgroups)) {
+			list_for_each_entry(list, &qgroup->qgroups,
+					    next_qgroup) {
+				if ((list->qgroup)->qgroupid == bq->qgroupid)
+					return 1;
+				filter_all_parent_insert(ql, list->qgroup);
+			}
+		}
+		rb_erase(n, &ql->root);
+		n = rb_first(&ql->root);
+	}
+	return 0;
+}
+
+static btrfs_qgroup_filter_func all_filter_funcs[] = {
+	[BTRFS_QGROUP_FILTER_ALL_PARENT]	= filter_by_all_parent,
+};
+
+struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void)
+{
+	struct btrfs_qgroup_filter_set *set;
+	int size;
+
+	size = sizeof(struct btrfs_qgroup_filter_set) +
+	       BTRFS_QGROUP_NFILTERS_INCREASE *
+	       sizeof(struct btrfs_qgroup_filter);
+	set = malloc(size);
+	if (!set) {
+		fprintf(stderr, "memory allocation failed\n");
+		exit(1);
+	}
+	memset(set, 0, size);
+	set->total = BTRFS_QGROUP_NFILTERS_INCREASE;
+
+	return set;
+}
+
+void btrfs_qgroup_free_filter_set(struct btrfs_qgroup_filter_set *filter_set)
+{
+	free(filter_set);
+}
+
+int btrfs_qgroup_setup_filter(struct btrfs_qgroup_filter_set **filter_set,
+			      enum btrfs_qgroup_filter_enum filter, u64 data)
+{
+	struct btrfs_qgroup_filter_set *set = *filter_set;
+	int size;
+
+	BUG_ON(!set);
+	BUG_ON(filter >= BTRFS_QGROUP_FILTER_MAX);
+	BUG_ON(set->nfilters > set->total);
+
+	if (set->nfilters == set->total) {
+		size = set->total + BTRFS_QGROUP_NFILTERS_INCREASE;
+		size = sizeof(*set) + size * sizeof(struct btrfs_qgroup_filter);
+
+		set = realloc(set, size);
+		if (!set) {
+			fprintf(stderr, "memory allocation failed\n");
+			exit(1);
+		}
+		memset(&set->filters[set->total], 0,
+		       BTRFS_QGROUP_NFILTERS_INCREASE *
+		       sizeof(struct btrfs_qgroup_filter));
+		set->total += BTRFS_QGROUP_NFILTERS_INCREASE;
+		*filter_set = set;
+	}
+	BUG_ON(set->filters[set->nfilters].filter_func);
+	set->filters[set->nfilters].filter_func = all_filter_funcs[filter];
+	set->filters[set->nfilters].data = data;
+	set->nfilters++;
+	return 0;
+}
+
+static int filter_qgroup(struct btrfs_qgroup *bq,
+			 struct btrfs_qgroup_filter_set *set)
+{
+	int i, ret;
+
+	if (!set || !set->nfilters)
+		return 1;
+	for (i = 0; i < set->nfilters; i++) {
+		if (!set->filters[i].filter_func)
+			break;
+		ret = set->filters[i].filter_func(bq, set->filters[i].data);
+		if (!ret)
+			return 0;
+	}
+	return 1;
+}
+
+static void pre_process_filter_set(struct qgroup_lookup *lookup,
+				   struct btrfs_qgroup_filter_set *set)
+{
+	int i;
+	struct btrfs_qgroup *qgroup_for_filter = NULL;
+
+	for (i = 0; i < set->nfilters; i++) {
+
+		if (set->filters[i].filter_func == filter_by_all_parent) {
+			qgroup_for_filter = qgroup_tree_search(lookup,
+					    set->filters[i].data);
+			set->filters[i].data =
+				 (u64)(unsigned long)qgroup_for_filter;
+		}
+	}
+}
+
+static int sort_tree_insert(struct qgroup_lookup *sort_tree,
+			    struct btrfs_qgroup *bq)
+{
+	struct rb_node **p = &sort_tree->root.rb_node;
+	struct rb_node *parent = NULL;
+	struct btrfs_qgroup *curr;
+	int ret;
+
+	while (*p) {
+		parent = *p;
+		curr = rb_entry(parent, struct btrfs_qgroup, sort_node);
+
+		ret = comp_entry_with_qgroupid(bq, curr, 0);
+		if (ret < 0)
+			p = &(*p)->rb_left;
+		else if (ret > 0)
+			p = &(*p)->rb_right;
+		else
+			return -EEXIST;
+	}
+	rb_link_node(&bq->sort_node, parent, p);
+	rb_insert_color(&bq->sort_node, &sort_tree->root);
+	return 0;
+}
+
+static void __filter_all_qgroups(struct qgroup_lookup *all_qgroups,
+				 struct qgroup_lookup *sort_tree,
+				 struct btrfs_qgroup_filter_set *filter_set)
+{
+	struct rb_node *n;
+	struct btrfs_qgroup *entry;
+	int ret;
+
+	qgroup_lookup_init(sort_tree);
+	pre_process_filter_set(all_qgroups, filter_set);
+
+	n = rb_last(&all_qgroups->root);
+	while (n) {
+		entry = rb_entry(n, struct btrfs_qgroup, rb_node);
+
+		ret = filter_qgroup(entry, filter_set);
+		if (ret)
+			sort_tree_insert(sort_tree, entry);
+
+		n = rb_prev(n);
+	}
+}
 static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 {
 	int ret;
@@ -565,28 +774,50 @@ 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, rb_node);
+		entry = rb_entry(n, struct btrfs_qgroup, sort_node);
 		print_single_qgroup_default(entry);
 		n = rb_next(n);
 	}
 }
 
-int btrfs_show_qgroups(int fd)
+int btrfs_show_qgroups(int fd,
+		       struct btrfs_qgroup_filter_set *filter_set)
 {
 
 	struct qgroup_lookup qgroup_lookup;
+	struct qgroup_lookup sort_tree;
 	int ret;
 
 	ret = __qgroups_search(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
+	__filter_all_qgroups(&qgroup_lookup, &sort_tree,
+			     filter_set);
+	print_all_qgroups(&sort_tree);
 
-	print_all_qgroups(&qgroup_lookup);
 	__free_all_qgroups(&qgroup_lookup);
-
+	btrfs_qgroup_free_filter_set(filter_set);
 	return ret;
 }
 
+u64 btrfs_get_path_rootid(int fd)
+{
+	int  ret;
+	struct btrfs_ioctl_ino_lookup_args args;
+
+	memset(&args, 0, sizeof(args));
+	args.objectid = BTRFS_FIRST_FREE_OBJECTID;
+
+	ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
+	if (ret < 0) {
+		fprintf(stderr,
+			"ERROR: can't perform the search -%s\n",
+			strerror(errno));
+		return ret;
+	}
+	return args.treeid;
+}
+
 u64 parse_qgroupid(char *p)
 {
 	char *s = strchr(p, '/');
diff --git a/qgroup.h b/qgroup.h
index e7a65ba..bcc2b4b 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -22,6 +22,21 @@
 #include "ioctl.h"
 #include "kerncompat.h"
 
+struct btrfs_qgroup;
+
+typedef int (*btrfs_qgroup_filter_func)(struct btrfs_qgroup *, u64);
+
+struct btrfs_qgroup_filter {
+	btrfs_qgroup_filter_func filter_func;
+	u64 data;
+};
+
+struct btrfs_qgroup_filter_set {
+	int total;
+	int nfilters;
+	struct btrfs_qgroup_filter filters[0];
+};
+
 enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_QGROUPID,
 	BTRFS_QGROUP_RFER,
@@ -33,9 +48,18 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_ALL,
 };
 
-int  btrfs_show_qgroups(int fd);
-void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
+enum btrfs_qgroup_filter_enum {
+	BTRFS_QGROUP_FILTER_ALL_PARENT,
+	BTRFS_QGROUP_FILTER_MAX,
+};
 
+u64 btrfs_get_path_rootid(int fd);
+int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *);
+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);
+int btrfs_qgroup_setup_filter(struct btrfs_qgroup_filter_set **filter_set,
+			      enum btrfs_qgroup_filter_enum, u64 data);
 u64 parse_qgroupid(char *p);
 int qgroup_inherit_size(struct btrfs_qgroup_inherit *p);
 int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 07/12] Btrfs-progs: list all qgroups impact given path(exclude ancestral qgroups)
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (5 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 06/12] Btrfs-progs: list all qgroups impact given path(include ancestral qgroups) Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 08/12] Btrfs-progs: enhance btrfs qgroup show to sort qgroups Wang Shilong
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch introduces '-f' option which can help you filter the qgroups
by the path name, you may use it like:

	btrfs qgroup show -f <path>
For example:

                         qgroupid(2/0)
                          /     \
                         /       \
                        qgroupid(1/0)
                        /         \
                       /           \
                      /             \
                  qgroupid(0/1)   qgroupid(0/2)
                  sub1              sub2
                  /  \
                 /    \
		dir1  file1

If we use the command:
	btrfs qgroup show -f sub1/dir1
The result will output
	0/1	--	--

'-f' option helps you list all qgroups impact given path.
(exclude ancestral qgroups)

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c | 20 +++++++++++++++-----
 qgroup.c      | 16 +++++++++++++++-
 qgroup.h      |  1 +
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 7c6c917..5f1550a 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,7 +202,7 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pcreF <path>",
+	"btrfs qgroup show -pcreFf <path>",
 	"Show subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
@@ -210,6 +210,8 @@ static const char * const cmd_qgroup_show_usage[] = {
 	"-e		print max exclusive size of qgroup",
 	"-F		list all qgroups which impact the given path"
 	"(include ancestral qgroups)",
+	"-f		list all qgroups which impact the given path"
+	"(exclude ancestral qgroups)",
 	NULL
 };
 
@@ -229,7 +231,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "pcreF");
+		c = getopt(argc, argv, "pcreFf");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -252,6 +254,9 @@ static int cmd_qgroup_show(int argc, char **argv)
 		case 'F':
 			filter_flag |= 0x1;
 			break;
+		case 'f':
+			filter_flag |= 0x2;
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
@@ -268,9 +273,14 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	if (filter_flag) {
 		qgroupid = btrfs_get_path_rootid(fd);
-		btrfs_qgroup_setup_filter(&filter_set,
-				BTRFS_QGROUP_FILTER_ALL_PARENT,
-				qgroupid);
+		if (filter_flag & 0x1)
+			btrfs_qgroup_setup_filter(&filter_set,
+					BTRFS_QGROUP_FILTER_ALL_PARENT,
+					qgroupid);
+		if (filter_flag & 0x2)
+			btrfs_qgroup_setup_filter(&filter_set,
+					BTRFS_QGROUP_FILTER_PARENT,
+					qgroupid);
 	}
 	ret = btrfs_show_qgroups(fd, filter_set);
 	e = errno;
diff --git a/qgroup.c b/qgroup.c
index 306b638..28772d6 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -468,6 +468,18 @@ static int filter_all_parent_insert(struct qgroup_lookup *sort_tree,
 	return 0;
 }
 
+static int filter_by_parent(struct btrfs_qgroup *bq, u64 data)
+{
+	struct btrfs_qgroup *qgroup =
+		(struct btrfs_qgroup *)(unsigned long)data;
+
+	if (data == 0)
+		return 0;
+	if (qgroup->qgroupid == bq->qgroupid)
+		return 1;
+	return 0;
+}
+
 static int filter_by_all_parent(struct btrfs_qgroup *bq, u64 data)
 {
 	struct qgroup_lookup lookup;
@@ -502,6 +514,7 @@ static int filter_by_all_parent(struct btrfs_qgroup *bq, u64 data)
 }
 
 static btrfs_qgroup_filter_func all_filter_funcs[] = {
+	[BTRFS_QGROUP_FILTER_PARENT]		= filter_by_parent,
 	[BTRFS_QGROUP_FILTER_ALL_PARENT]	= filter_by_all_parent,
 };
 
@@ -586,7 +599,8 @@ static void pre_process_filter_set(struct qgroup_lookup *lookup,
 
 	for (i = 0; i < set->nfilters; i++) {
 
-		if (set->filters[i].filter_func == filter_by_all_parent) {
+		if (set->filters[i].filter_func == filter_by_all_parent
+		    || set->filters[i].filter_func == filter_by_parent) {
 			qgroup_for_filter = qgroup_tree_search(lookup,
 					    set->filters[i].data);
 			set->filters[i].data =
diff --git a/qgroup.h b/qgroup.h
index bcc2b4b..5fcdd8a 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -49,6 +49,7 @@ enum btrfs_qgroup_column_enum {
 };
 
 enum btrfs_qgroup_filter_enum {
+	BTRFS_QGROUP_FILTER_PARENT,
 	BTRFS_QGROUP_FILTER_ALL_PARENT,
 	BTRFS_QGROUP_FILTER_MAX,
 };
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 08/12] Btrfs-progs: enhance btrfs qgroup show to sort qgroups
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (6 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 07/12] Btrfs-progs: list all qgroups impact given path(exclude " Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 09/12] Btrfs-progs: enhance btrfs qgroup to print the result as a table Wang Shilong
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

You might want to list qgroups in order of some items, such as 'qgroupid', 'rfer'
and so on, you can use '--sort'. Now you can sort the qgroups by 'qgroupid',
'rfer','excl','max_rfer' and 'max_excl'.

For example:
	If you want to list qgroups in order of 'qgroupid'.
You can use the option like that:

	btrfs qgroup show --sort=+/-qgroupid <path>
Here, '+' means the result is sorted by ascending order. '-' is by descending
order. If you don't specify either '+' nor '-', the result is sorted by
default - ascending order.

If you want to combine sort items, you do it like that:
	btrfs qgroup show  --sort=-qgroupid,+rfer,max_rfer,excl <path>

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 cmds-qgroup.c |  25 +++++-
 qgroup.c      | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 qgroup.h      |  33 +++++++-
 3 files changed, 302 insertions(+), 12 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 5f1550a..4fe776c 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -202,7 +202,8 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 }
 
 static const char * const cmd_qgroup_show_usage[] = {
-	"btrfs qgroup show -pcreFf <path>",
+	"btrfs qgroup show -pcreFf "
+	"[--sort=qgroupid,rfer,excl,max_rfer,max_excl] <path>",
 	"Show subvolume quota groups.",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
@@ -212,6 +213,11 @@ static const char * const cmd_qgroup_show_usage[] = {
 	"(include ancestral qgroups)",
 	"-f		list all qgroups which impact the given path"
 	"(exclude ancestral qgroups)",
+	"--sort=qgroupid,rfer,excl,max_rfer,max_excl",
+	"		list qgroups in order of qgroupid,"
+	"rfer,max_rfer or max_excl",
+	"		you can use '+' or '-' in front of each item.",
+	"		(+:ascending, -:descending, ascending default)",
 	NULL
 };
 
@@ -226,12 +232,19 @@ static int cmd_qgroup_show(int argc, char **argv)
 	u64 qgroupid;
 	int filter_flag = 0;
 
+	struct btrfs_qgroup_comparer_set *comparer_set;
 	struct btrfs_qgroup_filter_set *filter_set;
 	filter_set = btrfs_qgroup_alloc_filter_set();
+	comparer_set = btrfs_qgroup_alloc_comparer_set();
+	struct option long_options[] = {
+		{"sort", 1, NULL, 'S'},
+		{0, 0, 0, 0}
+	};
 
 	optind = 1;
 	while (1) {
-		c = getopt(argc, argv, "pcreFf");
+		c = getopt_long(argc, argv, "pcreFf",
+				long_options, NULL);
 		if (c < 0)
 			break;
 		switch (c) {
@@ -257,6 +270,12 @@ static int cmd_qgroup_show(int argc, char **argv)
 		case 'f':
 			filter_flag |= 0x2;
 			break;
+		case 'S':
+			ret = btrfs_qgroup_parse_sort_string(optarg,
+							     &comparer_set);
+			if (ret)
+				usage(cmd_qgroup_show_usage);
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
@@ -282,7 +301,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 					BTRFS_QGROUP_FILTER_PARENT,
 					qgroupid);
 	}
-	ret = btrfs_show_qgroups(fd, filter_set);
+	ret = btrfs_show_qgroups(fd, filter_set, comparer_set);
 	e = errno;
 	close_file_or_dir(fd, dirstream);
 	if (ret < 0)
diff --git a/qgroup.c b/qgroup.c
index 28772d6..84f5fc1 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -22,6 +22,7 @@
 #include "ioctl.h"
 
 #define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)
+#define BTRFS_QGROUP_NCOMPS_INCREASE (2 * BTRFS_QGROUP_COMP_MAX)
 
 struct qgroup_lookup {
 	struct rb_root root;
@@ -122,6 +123,7 @@ struct {
 };
 
 static btrfs_qgroup_filter_func all_filter_funcs[];
+static btrfs_qgroup_comp_func all_comp_funcs[];
 
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
 {
@@ -236,6 +238,188 @@ static int comp_entry_with_qgroupid(struct btrfs_qgroup *entry1,
 	return is_descending ? -ret : ret;
 }
 
+static int comp_entry_with_rfer(struct btrfs_qgroup *entry1,
+				struct btrfs_qgroup *entry2,
+				int is_descending)
+{
+	int ret;
+
+	if (entry1->rfer > entry2->rfer)
+		ret = 1;
+	else if (entry1->rfer < entry2->rfer)
+		ret = -1;
+	else
+		ret = 0;
+
+	return is_descending ? -ret : ret;
+}
+
+static int comp_entry_with_excl(struct btrfs_qgroup *entry1,
+				struct btrfs_qgroup *entry2,
+				int is_descending)
+{
+	int ret;
+
+	if (entry1->excl > entry2->excl)
+		ret = 1;
+	else if (entry1->excl < entry2->excl)
+		ret = -1;
+	else
+		ret = 0;
+
+	return is_descending ? -ret : ret;
+}
+
+static int comp_entry_with_max_rfer(struct btrfs_qgroup *entry1,
+				    struct btrfs_qgroup *entry2,
+				    int is_descending)
+{
+	int ret;
+
+	if (entry1->max_rfer > entry2->max_rfer)
+		ret = 1;
+	else if (entry1->max_rfer < entry2->max_rfer)
+		ret = -1;
+	else
+		ret = 0;
+
+	return is_descending ? -ret : ret;
+}
+
+static int comp_entry_with_max_excl(struct btrfs_qgroup *entry1,
+				    struct btrfs_qgroup *entry2,
+				    int is_descending)
+{
+	int ret;
+
+	if (entry1->max_excl > entry2->max_excl)
+		ret = 1;
+	else if (entry1->max_excl < entry2->max_excl)
+		ret = -1;
+	else
+		ret = 0;
+
+	return is_descending ? -ret : ret;
+}
+
+static btrfs_qgroup_comp_func all_comp_funcs[] = {
+	[BTRFS_QGROUP_COMP_QGROUPID]	= comp_entry_with_qgroupid,
+	[BTRFS_QGROUP_COMP_RFER]	= comp_entry_with_rfer,
+	[BTRFS_QGROUP_COMP_EXCL]	= comp_entry_with_excl,
+	[BTRFS_QGROUP_COMP_MAX_RFER]	= comp_entry_with_max_rfer,
+	[BTRFS_QGROUP_COMP_MAX_EXCL]	= comp_entry_with_max_excl
+};
+
+static char *all_sort_items[] = {
+	[BTRFS_QGROUP_COMP_QGROUPID]	= "qgroupid",
+	[BTRFS_QGROUP_COMP_RFER]	= "rfer",
+	[BTRFS_QGROUP_COMP_EXCL]	= "excl",
+	[BTRFS_QGROUP_COMP_MAX_RFER]	= "max_rfer",
+	[BTRFS_QGROUP_COMP_MAX_EXCL]	= "max_excl",
+	[BTRFS_QGROUP_COMP_MAX]		= NULL,
+};
+
+static int  btrfs_qgroup_get_sort_item(char *sort_name)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_QGROUP_COMP_MAX; i++) {
+		if (strcmp(sort_name, all_sort_items[i]) == 0)
+			return i;
+	}
+	return -1;
+}
+
+struct btrfs_qgroup_comparer_set *btrfs_qgroup_alloc_comparer_set(void)
+{
+	struct btrfs_qgroup_comparer_set *set;
+	int size;
+	size = sizeof(struct btrfs_qgroup_comparer_set) +
+	       BTRFS_QGROUP_NCOMPS_INCREASE *
+	       sizeof(struct btrfs_qgroup_comparer);
+	set = malloc(size);
+	if (!set) {
+		fprintf(stderr, "memory allocation failed\n");
+		exit(1);
+	}
+
+	memset(set, 0, size);
+	set->total = BTRFS_QGROUP_NCOMPS_INCREASE;
+
+	return set;
+}
+
+void btrfs_qgroup_free_comparer_set(struct btrfs_qgroup_comparer_set *comp_set)
+{
+	free(comp_set);
+}
+
+int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set  **comp_set,
+				enum btrfs_qgroup_comp_enum comparer,
+				int is_descending)
+{
+	struct btrfs_qgroup_comparer_set *set = *comp_set;
+	int size;
+
+	BUG_ON(!set);
+	BUG_ON(comparer >= BTRFS_QGROUP_COMP_MAX);
+	BUG_ON(set->ncomps > set->total);
+
+	if (set->ncomps == set->total) {
+		size = set->total + BTRFS_QGROUP_NCOMPS_INCREASE;
+		size = sizeof(*set) +
+		       size * sizeof(struct btrfs_qgroup_comparer);
+		set = realloc(set, size);
+		if (!set) {
+			fprintf(stderr, "memory allocation failed\n");
+			exit(1);
+		}
+
+		memset(&set->comps[set->total], 0,
+		       BTRFS_QGROUP_NCOMPS_INCREASE *
+		       sizeof(struct btrfs_qgroup_comparer));
+		set->total += BTRFS_QGROUP_NCOMPS_INCREASE;
+		*comp_set = set;
+	}
+
+	BUG_ON(set->comps[set->ncomps].comp_func);
+
+	set->comps[set->ncomps].comp_func = all_comp_funcs[comparer];
+	set->comps[set->ncomps].is_descending = is_descending;
+	set->ncomps++;
+	return 0;
+}
+
+static int sort_comp(struct btrfs_qgroup *entry1, struct btrfs_qgroup *entry2,
+		     struct btrfs_qgroup_comparer_set *set)
+{
+	int qgroupid_compared = 0;
+	int i, ret = 0;
+
+	if (!set || !set->ncomps)
+		goto comp_qgroupid;
+
+	for (i = 0; i < set->ncomps; i++) {
+		if (!set->comps[i].comp_func)
+			break;
+
+		ret = set->comps[i].comp_func(entry1, entry2,
+					      set->comps[i].is_descending);
+		if (ret)
+			return ret;
+
+		if (set->comps[i].comp_func == comp_entry_with_qgroupid)
+			qgroupid_compared = 1;
+	}
+
+	if (!qgroupid_compared) {
+comp_qgroupid:
+		ret = comp_entry_with_qgroupid(entry1, entry2, 0);
+	}
+
+	return ret;
+}
+
 /*
  * insert a new root into the tree.  returns the existing root entry
  * if one is already there.  qgroupid is used
@@ -610,7 +794,8 @@ static void pre_process_filter_set(struct qgroup_lookup *lookup,
 }
 
 static int sort_tree_insert(struct qgroup_lookup *sort_tree,
-			    struct btrfs_qgroup *bq)
+			    struct btrfs_qgroup *bq,
+			    struct btrfs_qgroup_comparer_set *comp_set)
 {
 	struct rb_node **p = &sort_tree->root.rb_node;
 	struct rb_node *parent = NULL;
@@ -621,7 +806,7 @@ static int sort_tree_insert(struct qgroup_lookup *sort_tree,
 		parent = *p;
 		curr = rb_entry(parent, struct btrfs_qgroup, sort_node);
 
-		ret = comp_entry_with_qgroupid(bq, curr, 0);
+		ret = sort_comp(bq, curr, comp_set);
 		if (ret < 0)
 			p = &(*p)->rb_left;
 		else if (ret > 0)
@@ -634,9 +819,10 @@ static int sort_tree_insert(struct qgroup_lookup *sort_tree,
 	return 0;
 }
 
-static void __filter_all_qgroups(struct qgroup_lookup *all_qgroups,
+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_filter_set *filter_set,
+				 struct btrfs_qgroup_comparer_set *comp_set)
 {
 	struct rb_node *n;
 	struct btrfs_qgroup *entry;
@@ -651,7 +837,7 @@ static void __filter_all_qgroups(struct qgroup_lookup *all_qgroups,
 
 		ret = filter_qgroup(entry, filter_set);
 		if (ret)
-			sort_tree_insert(sort_tree, entry);
+			sort_tree_insert(sort_tree, entry, comp_set);
 
 		n = rb_prev(n);
 	}
@@ -795,7 +981,8 @@ static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
 }
 
 int btrfs_show_qgroups(int fd,
-		       struct btrfs_qgroup_filter_set *filter_set)
+		       struct btrfs_qgroup_filter_set *filter_set,
+		       struct btrfs_qgroup_comparer_set *comp_set)
 {
 
 	struct qgroup_lookup qgroup_lookup;
@@ -805,8 +992,8 @@ int btrfs_show_qgroups(int fd,
 	ret = __qgroups_search(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
-	__filter_all_qgroups(&qgroup_lookup, &sort_tree,
-			     filter_set);
+	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
+				  filter_set, comp_set);
 	print_all_qgroups(&sort_tree);
 
 	__free_all_qgroups(&qgroup_lookup);
@@ -832,6 +1019,59 @@ u64 btrfs_get_path_rootid(int fd)
 	return args.treeid;
 }
 
+int btrfs_qgroup_parse_sort_string(char *opt_arg,
+				   struct btrfs_qgroup_comparer_set **comps)
+{
+	int order;
+	int flag;
+	char *p;
+	char **ptr_argv;
+	int what_to_sort;
+
+	while ((p = strtok(opt_arg, ",")) != NULL) {
+		flag = 0;
+		ptr_argv = all_sort_items;
+
+		while (*ptr_argv) {
+			if (strcmp(*ptr_argv, p) == 0) {
+				flag = 1;
+				break;
+			} else {
+				p++;
+				if (strcmp(*ptr_argv, p) == 0) {
+					flag = 1;
+					p--;
+					break;
+				}
+				p--;
+			}
+			ptr_argv++;
+		}
+
+		if (flag == 0)
+			return -1;
+
+		else {
+			if (*p == '+') {
+				order = 0;
+				p++;
+			} else if (*p == '-') {
+				order = 1;
+				p++;
+			} else
+				order = 0;
+
+			what_to_sort = btrfs_qgroup_get_sort_item(p);
+			if (what_to_sort < 0)
+				return -1;
+			btrfs_qgroup_setup_comparer(comps, what_to_sort, order);
+		}
+		opt_arg = NULL;
+	}
+
+	return 0;
+}
+
 u64 parse_qgroupid(char *p)
 {
 	char *s = strchr(p, '/');
diff --git a/qgroup.h b/qgroup.h
index 5fcdd8a..653cf1c 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -25,18 +25,32 @@
 struct btrfs_qgroup;
 
 typedef int (*btrfs_qgroup_filter_func)(struct btrfs_qgroup *, u64);
+typedef int (*btrfs_qgroup_comp_func)(struct btrfs_qgroup *,
+				      struct btrfs_qgroup *, int);
+
 
 struct btrfs_qgroup_filter {
 	btrfs_qgroup_filter_func filter_func;
 	u64 data;
 };
 
+struct btrfs_qgroup_comparer {
+	btrfs_qgroup_comp_func comp_func;
+	int is_descending;
+};
+
 struct btrfs_qgroup_filter_set {
 	int total;
 	int nfilters;
 	struct btrfs_qgroup_filter filters[0];
 };
 
+struct btrfs_qgroup_comparer_set {
+	int total;
+	int ncomps;
+	struct btrfs_qgroup_comparer comps[0];
+};
+
 enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_QGROUPID,
 	BTRFS_QGROUP_RFER,
@@ -48,19 +62,36 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_ALL,
 };
 
+enum btrfs_qgroup_comp_enum {
+	BTRFS_QGROUP_COMP_QGROUPID,
+	BTRFS_QGROUP_COMP_RFER,
+	BTRFS_QGROUP_COMP_EXCL,
+	BTRFS_QGROUP_COMP_MAX_RFER,
+	BTRFS_QGROUP_COMP_MAX_EXCL,
+	BTRFS_QGROUP_COMP_MAX
+};
+
 enum btrfs_qgroup_filter_enum {
 	BTRFS_QGROUP_FILTER_PARENT,
 	BTRFS_QGROUP_FILTER_ALL_PARENT,
 	BTRFS_QGROUP_FILTER_MAX,
 };
 
+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 *);
+int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
+		       struct btrfs_qgroup_comparer_set *);
 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);
 int btrfs_qgroup_setup_filter(struct btrfs_qgroup_filter_set **filter_set,
 			      enum btrfs_qgroup_filter_enum, u64 data);
+struct btrfs_qgroup_comparer_set *btrfs_qgroup_alloc_comparer_set(void);
+void btrfs_qgroup_free_comparer_set(struct btrfs_qgroup_comparer_set *comp_set);
+int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set **comp_set,
+				enum btrfs_qgroup_comp_enum comparer,
+				int is_descending);
 u64 parse_qgroupid(char *p);
 int qgroup_inherit_size(struct btrfs_qgroup_inherit *p);
 int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 09/12] Btrfs-progs: enhance btrfs qgroup to print the result as a table
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (7 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 08/12] Btrfs-progs: enhance btrfs qgroup show to sort qgroups Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result Wang Shilong
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>

This patch enhance to print the result as a table.

You can use it like:
	btrfs qgroup show <path>
However, to table the result better, we make '-p' and '-c' not present
at the same time.

For example:

	btrfs qgroup show -pr <path>
The result will output as the follow format:

qgroupid rfer       excl       max_excl       parent
-------- ----       ----       --------       ------
0/265    1289752576 1289752576 0              ---
1/0      0          0          10999511627776 2/0,3/0
2/0      0          0          0              ---
3/0      0          0          0              ---

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 qgroup.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 189 insertions(+), 22 deletions(-)

diff --git a/qgroup.c b/qgroup.c
index 84f5fc1..fa905fa 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -80,40 +80,48 @@ struct {
 	char *name;
 	char *column_name;
 	int need_print;
+	int max_len;
 } btrfs_qgroup_columns[] = {
 	{
 		.name		= "qgroupid",
 		.column_name	= "Qgroupid",
 		.need_print	= 1,
+		.max_len	= 8,
 	},
 	{
 		.name		= "rfer",
 		.column_name	= "Rfer",
 		.need_print	= 1,
+		.max_len	= 4,
 	},
 	{
 		.name		= "excl",
 		.column_name	= "Excl",
 		.need_print	= 1,
+		.max_len	= 4,
 	},
 	{	.name		= "max_rfer",
 		.column_name	= "Max_rfer",
 		.need_print	= 0,
+		.max_len	= 8,
 	},
 	{
 		.name		= "max_excl",
 		.column_name	= "Max_excl",
 		.need_print	= 0,
+		.max_len	= 8,
 	},
 	{
 		.name		= "parent",
 		.column_name	= "Parent",
 		.need_print	= 0,
+		.max_len	= 7,
 	},
 	{
 		.name		= "child",
 		.column_name	= "Child",
 		.need_print	= 0,
+		.max_len	= 5,
 	},
 	{
 		.name		= NULL,
@@ -139,69 +147,91 @@ void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column)
 		btrfs_qgroup_columns[i].need_print = 1;
 }
 
-static void print_parent_column(struct btrfs_qgroup *qgroup)
+static int print_parent_column(struct btrfs_qgroup *qgroup)
 {
 	struct btrfs_qgroup_list *list = NULL;
+	int len = 0;
 
 	list_for_each_entry(list, &qgroup->qgroups, next_qgroup) {
-		printf("%llu/%llu", (list->qgroup)->qgroupid >> 48,
-		      ((1ll << 48) - 1) & (list->qgroup)->qgroupid);
+		len += printf("%llu/%llu", (list->qgroup)->qgroupid >> 48,
+			((1ll << 48) - 1) & (list->qgroup)->qgroupid);
 		if (!list_is_last(&list->next_qgroup, &qgroup->qgroups))
-			printf(",");
+			len += printf(",");
 	}
 	if (list_empty(&qgroup->qgroups))
-		printf("---");
+		len += printf("---");
+
+	return len;
 }
 
-static void print_child_column(struct btrfs_qgroup *qgroup)
+static int print_child_column(struct btrfs_qgroup *qgroup)
 {
 	struct btrfs_qgroup_list *list = NULL;
+	int len = 0;
 
 	list_for_each_entry(list, &qgroup->members, next_member) {
-		printf("%llu/%llu", (list->member)->qgroupid >> 48,
-		      ((1ll << 48) - 1) & (list->member)->qgroupid);
+		len += printf("%llu/%llu", (list->member)->qgroupid >> 48,
+				((1ll << 48) - 1) & (list->member)->qgroupid);
 		if (!list_is_last(&list->next_member, &qgroup->members))
-			printf(",");
+			len += printf(",");
 	}
 	if (list_empty(&qgroup->members))
-		printf("---");
+		len += printf("---");
+
+	return len;
+}
+
+static void print_qgroup_column_add_blank(enum btrfs_qgroup_column_enum column,
+					  int len)
+{
+	len = btrfs_qgroup_columns[column].max_len - len;
+	while (len--)
+		printf(" ");
 }
 
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 				enum btrfs_qgroup_column_enum column)
 {
 	BUG_ON(column >= BTRFS_QGROUP_ALL || column < 0);
+	int len;
 
 	switch (column) {
 
 	case BTRFS_QGROUP_QGROUPID:
-		printf("%llu/%llu", qgroup->qgroupid >> 48,
-		       ((1ll << 48) - 1) & qgroup->qgroupid);
+		len = printf("%llu/%llu", qgroup->qgroupid >> 48,
+				((1ll << 48) - 1) & qgroup->qgroupid);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
 		break;
 	case BTRFS_QGROUP_RFER:
-		printf("%lld", qgroup->rfer);
+		len = printf("%lld", qgroup->rfer);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_RFER, len);
 		break;
 	case BTRFS_QGROUP_EXCL:
-		printf("%lld", qgroup->excl);
+		len = printf("%lld", qgroup->excl);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_EXCL, len);
 		break;
 	case BTRFS_QGROUP_PARENT:
-		print_parent_column(qgroup);
+		len = print_parent_column(qgroup);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_PARENT, len);
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		printf("%llu", qgroup->max_rfer);
+		len = printf("%llu", qgroup->max_rfer);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_MAX_RFER, len);
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		printf("%llu", qgroup->max_excl);
+		len = printf("%llu", qgroup->max_excl);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_MAX_EXCL, len);
 		break;
 	case BTRFS_QGROUP_CHILD:
-		print_child_column(qgroup);
+		len = print_child_column(qgroup);
+		print_qgroup_column_add_blank(BTRFS_QGROUP_CHILD, len);
 		break;
 	default:
 		break;
 	}
 }
 
-static void print_single_qgroup_default(struct btrfs_qgroup *qgroup)
+static void print_single_qgroup_table(struct btrfs_qgroup *qgroup)
 {
 	int i;
 
@@ -210,7 +240,39 @@ static void print_single_qgroup_default(struct btrfs_qgroup *qgroup)
 			continue;
 		print_qgroup_column(qgroup, i);
 
-		if (i != BTRFS_QGROUP_ALL - 1)
+		if (i != BTRFS_QGROUP_CHILD)
+			printf(" ");
+	}
+	printf("\n");
+}
+
+static void print_table_head()
+{
+	int i;
+	int len;
+
+	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+		if (!btrfs_qgroup_columns[i].need_print)
+			continue;
+		printf("%s", btrfs_qgroup_columns[i].name);
+		len = btrfs_qgroup_columns[i].max_len -
+		      strlen(btrfs_qgroup_columns[i].name);
+		while (len--)
+			printf(" ");
+		printf(" ");
+	}
+	printf("\n");
+	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+		if (!btrfs_qgroup_columns[i].need_print)
+			continue;
+
+		len = strlen(btrfs_qgroup_columns[i].name);
+		while (len--)
+			printf("-");
+		len = btrfs_qgroup_columns[i].max_len -
+		      strlen(btrfs_qgroup_columns[i].name);
+		printf(" ");
+		while (len--)
 			printf(" ");
 	}
 	printf("\n");
@@ -819,6 +881,107 @@ static int sort_tree_insert(struct qgroup_lookup *sort_tree,
 	return 0;
 }
 
+static void __update_columns_max_len(struct btrfs_qgroup *bq,
+				     enum btrfs_qgroup_column_enum column)
+{
+	BUG_ON(column >= BTRFS_QGROUP_ALL || column < 0);
+	struct btrfs_qgroup_list *list = NULL;
+	char tmp[100];
+	char *tmp1;
+	int len;
+
+	switch (column) {
+
+	case BTRFS_QGROUP_QGROUPID:
+		sprintf(tmp, "%llu/%llu", (bq->qgroupid >> 48),
+			bq->qgroupid & ((1ll << 48) - 1));
+		len = strlen(tmp);
+		if (btrfs_qgroup_columns[column].max_len < len)
+			btrfs_qgroup_columns[column].max_len = len;
+		break;
+	case BTRFS_QGROUP_RFER:
+		sprintf(tmp, "%llu", bq->rfer);
+		len = strlen(tmp);
+		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);
+		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);
+		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);
+		if (btrfs_qgroup_columns[column].max_len < len)
+			btrfs_qgroup_columns[column].max_len = len;
+		break;
+	case BTRFS_QGROUP_PARENT:
+		len = 0;
+		list_for_each_entry(list, &bq->qgroups, next_qgroup)
+			len++;
+		tmp1 = calloc(1, 22 * len + 1);
+		if (!tmp1) {
+			perror("malloc fails");
+			exit(1);
+		}
+		list_for_each_entry(list, &bq->qgroups, next_qgroup) {
+			sprintf(tmp, "%llu/%llu", (list->qgroup)->qgroupid >> 48,
+				((1ll << 48) - 1) & (list->qgroup)->qgroupid);
+			strcat(tmp1, tmp);
+			if (!list_is_last(&list->next_qgroup, &bq->qgroups))
+				strcat(tmp1, ",");
+		}
+		len = strlen(tmp1);
+		if (btrfs_qgroup_columns[column].max_len < len)
+			btrfs_qgroup_columns[column].max_len = len;
+		free(tmp1);
+		break;
+	case BTRFS_QGROUP_CHILD:
+		len = 0;
+		list_for_each_entry(list, &bq->members, next_member)
+			len++;
+		tmp1 = calloc(1, 22 * len + 1);
+		if (!tmp1) {
+			perror("malloc fails");
+			exit(1);
+		}
+		list_for_each_entry(list, &bq->members, next_member) {
+			sprintf(tmp, "%llu/%llu", (list->qgroup)->qgroupid >> 48,
+				((1ll << 48) - 1) & (list->qgroup)->qgroupid);
+			strcat(tmp1, tmp);
+			if (!list_is_last(&list->next_member, &bq->members))
+				strcat(tmp1, ",");
+		}
+		len = strlen(tmp1);
+		if (btrfs_qgroup_columns[column].max_len < len)
+			btrfs_qgroup_columns[column].max_len = len;
+		free(tmp1);
+		break;
+	default:
+		break;
+	}
+
+}
+
+static void update_columns_max_len(struct btrfs_qgroup *bq)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+		if (!btrfs_qgroup_columns[i].need_print)
+			continue;
+		__update_columns_max_len(bq, i);
+	}
+}
+
 static void __filter_and_sort_qgroups(struct qgroup_lookup *all_qgroups,
 				 struct qgroup_lookup *sort_tree,
 				 struct btrfs_qgroup_filter_set *filter_set,
@@ -836,9 +999,11 @@ static void __filter_and_sort_qgroups(struct qgroup_lookup *all_qgroups,
 		entry = rb_entry(n, struct btrfs_qgroup, rb_node);
 
 		ret = filter_qgroup(entry, filter_set);
-		if (ret)
+		if (ret) {
 			sort_tree_insert(sort_tree, entry, comp_set);
 
+			update_columns_max_len(entry);
+		}
 		n = rb_prev(n);
 	}
 }
@@ -972,10 +1137,12 @@ static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
 	struct rb_node *n;
 	struct btrfs_qgroup *entry;
 
+	print_table_head();
+
 	n = rb_first(&qgroup_lookup->root);
 	while (n) {
 		entry = rb_entry(n, struct btrfs_qgroup, sort_node);
-		print_single_qgroup_default(entry);
+		print_single_qgroup_table(entry);
 		n = rb_next(n);
 	}
 }
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (8 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 09/12] Btrfs-progs: enhance btrfs qgroup to print the result as a table Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-08 15:34   ` David Sterba
  2013-10-07  7:21 ` [PATCH v3 11/12] Btrfs-progs: make pretty_size_snprintf() return len Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 12/12] Btrfs-progs: add '-h' options to print sizes in human readable format Wang Shilong
  11 siblings, 1 reply; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

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(-)

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);
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 11/12] Btrfs-progs: make pretty_size_snprintf() return len
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (9 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  2013-10-07  7:21 ` [PATCH v3 12/12] Btrfs-progs: add '-h' options to print sizes in human readable format Wang Shilong
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Sometimes, we need to catch length of snprintf() in pretty_size_snprintf().

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
---
 utils.c | 9 +++++----
 utils.h | 4 ++--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/utils.c b/utils.c
index 4ed7405..7b42022 100644
--- a/utils.c
+++ b/utils.c
@@ -1190,13 +1190,13 @@ out:
 }
 
 static char *size_strs[] = { "", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
-void pretty_size_snprintf(u64 size, char *str, size_t str_bytes)
+int pretty_size_snprintf(double size, char *str, size_t str_bytes)
 {
 	int num_divs = 0;
 	float fraction;
 
 	if (str_bytes == 0)
-		return;
+		return 0;
 
 	if( size < 1024 ){
 		fraction = size;
@@ -1212,11 +1212,12 @@ void pretty_size_snprintf(u64 size, char *str, size_t str_bytes)
 
 		if (num_divs >= ARRAY_SIZE(size_strs)) {
 			str[0] = '\0';
-			return;
+			return -1;
 		}
 		fraction = (float)last_size / 1024;
 	}
-	snprintf(str, str_bytes, "%.2f%s", fraction, size_strs[num_divs]);
+	return snprintf(str, str_bytes, "%.2f%s", fraction,
+			size_strs[num_divs]);
 }
 
 int parse_block_size(const char *ch)
diff --git a/utils.h b/utils.h
index 40b662d..240b590 100644
--- a/utils.h
+++ b/utils.h
@@ -48,11 +48,11 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
 int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
 				 int super_offset);
 
-void pretty_size_snprintf(u64 size, char *str, size_t str_bytes);
+int pretty_size_snprintf(double size, char *str, size_t str_bytes);
 #define pretty_size(size) 						\
 	({								\
 		static __thread char _str[24];				\
-		pretty_size_snprintf((size), _str, sizeof(_str));	\
+		(void)pretty_size_snprintf((size), _str, sizeof(_str));	\
 		_str;							\
 	})
 
-- 
1.8.3.1

--
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-

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 12/12] Btrfs-progs: add '-h' options to print sizes in human readable format
  2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
                   ` (10 preceding siblings ...)
  2013-10-07  7:21 ` [PATCH v3 11/12] Btrfs-progs: make pretty_size_snprintf() return len Wang Shilong
@ 2013-10-07  7:21 ` Wang Shilong
  11 siblings, 0 replies; 22+ messages in thread
From: Wang Shilong @ 2013-10-07  7:21 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This is a short cut for people who don't want to use '--block-size',it
will print sizes in human readable format.

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
---
 cmds-qgroup.c | 17 +++++++++++++---
 qgroup.c      | 62 +++++++++++++++++++++++++++++++++++++++++++++++------------
 qgroup.h      |  2 ++
 3 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/cmds-qgroup.c b/cmds-qgroup.c
index 912cc42..7ea752b 100644
--- a/cmds-qgroup.c
+++ b/cmds-qgroup.c
@@ -204,6 +204,7 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 static const char * const cmd_qgroup_show_usage[] = {
 	"btrfs qgroup show [options] <path>",
 	"Show subvolume quota groups.",
+	"-h		print size in human readable format",
 	"-p		print parent qgroup id",
 	"-c		print child qgroup id",
 	"-r		print max referenced size of qgroup",
@@ -246,7 +247,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 
 	optind = 1;
 	while (1) {
-		c = getopt_long(argc, argv, "pcreFf",
+		c = getopt_long(argc, argv, "pcreFfh",
 				long_options, NULL);
 		if (c < 0)
 			break;
@@ -280,11 +281,21 @@ static int cmd_qgroup_show(int argc, char **argv)
 				usage(cmd_qgroup_show_usage);
 			break;
 		case 'B':
-			block_size = parse_block_size(optarg);
-			if (block_size < 0) {
+			ret = parse_block_size(optarg);
+			if (ret < 0) {
 				fprintf(stderr, "Invalid block size\n");
 				usage(cmd_qgroup_show_usage);
 			}
+			/* force to print in human readable format
+			 * if -h is given
+			 */
+			if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+				break;
+			else
+				block_size = ret;
+			break;
+		case 'h':
+			block_size = BTRFS_QGROUP_PRINT_HUMAN_READABLE;
 			break;
 		default:
 			usage(cmd_qgroup_show_usage);
diff --git a/qgroup.c b/qgroup.c
index 0de6c7d..b1b7cef 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -206,15 +206,27 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 		print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = block_size_snprintf((signed long long)qgroup->rfer, tmp,
-					sizeof(tmp), block_size);
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(
+					(signed long long)qgroup->rfer,
+					tmp, sizeof(tmp));
+		else
+			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 = block_size_snprintf((signed long long)qgroup->excl, tmp,
-					sizeof(tmp), block_size);
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(
+					(signed long long)qgroup->excl,
+					tmp, sizeof(tmp));
+		else
+			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);
@@ -224,14 +236,22 @@ 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 = block_size_snprintf(qgroup->max_rfer, tmp,
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(qgroup->max_rfer, tmp,
+					sizeof(tmp));
+		else
+			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 = block_size_snprintf(qgroup->max_excl, tmp,
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(qgroup->max_excl, tmp,
+					sizeof(tmp));
+		else
+			len = block_size_snprintf(qgroup->max_excl, tmp,
 					sizeof(tmp), block_size);
 		BUG_ON(len < 0);
 		printf("%s", tmp);
@@ -917,28 +937,46 @@ static void __update_columns_max_len(struct btrfs_qgroup *bq,
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = block_size_snprintf((signed long long)bq->rfer, tmp,
-					sizeof(tmp), block_size);
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(
+					(signed long long)bq->rfer,
+					tmp, sizeof(tmp));
+		else
+			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:
-		len = block_size_snprintf((signed long long)bq->excl, tmp,
-					sizeof(tmp), block_size);
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(
+					(signed long long)bq->excl,
+					tmp, sizeof(tmp));
+		else
+			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:
-		len = block_size_snprintf(bq->max_rfer, tmp,
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(bq->max_rfer, tmp,
+					sizeof(tmp));
+		else
+			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:
-		len = block_size_snprintf(bq->max_excl, tmp,
+		if (block_size == BTRFS_QGROUP_PRINT_HUMAN_READABLE)
+			len = pretty_size_snprintf(bq->max_excl, tmp,
+					sizeof(tmp));
+		else
+			len = block_size_snprintf(bq->max_excl, tmp,
 					sizeof(tmp), block_size);
 		BUG_ON(len < 0);
 		if (btrfs_qgroup_columns[column].max_len < len)
diff --git a/qgroup.h b/qgroup.h
index 1113a24..aa05de5 100644
--- a/qgroup.h
+++ b/qgroup.h
@@ -22,6 +22,8 @@
 #include "ioctl.h"
 #include "kerncompat.h"
 
+#define BTRFS_QGROUP_PRINT_HUMAN_READABLE (-1)
+
 struct btrfs_qgroup;
 
 typedef int (*btrfs_qgroup_filter_func)(struct btrfs_qgroup *, u64);
-- 
1.8.3.1

--
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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups
  2013-10-07  7:21 ` [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups Wang Shilong
@ 2013-10-08 15:06   ` David Sterba
  0 siblings, 0 replies; 22+ messages in thread
From: David Sterba @ 2013-10-08 15:06 UTC (permalink / raw)
  To: Wang Shilong; +Cc: linux-btrfs, dsterba

On Mon, Oct 07, 2013 at 03:21:38PM +0800, Wang Shilong wrote:
> +static void print_parent_column(struct btrfs_qgroup *qgroup)
> +{
> +	struct btrfs_qgroup_list *list = NULL;
> +
> +	list_for_each_entry(list, &qgroup->qgroups, next_qgroup) {
> +		printf("%llu/%llu", (list->qgroup)->qgroupid >> 48,
> +		      ((1ll << 48) - 1) & (list->qgroup)->qgroupid);

Please use a wrapper for the >> 48 calculations everywhere (another
patch).

thanks,
david

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups
  2013-10-07  7:21 ` [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups Wang Shilong
@ 2013-10-08 15:08   ` David Sterba
  0 siblings, 0 replies; 22+ messages in thread
From: David Sterba @ 2013-10-08 15:08 UTC (permalink / raw)
  To: Wang Shilong; +Cc: linux-btrfs, dsterba

On Mon, Oct 07, 2013 at 03:21:39PM +0800, Wang Shilong wrote:
> From: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
> 
> This patch introduces '-c' option to print the ID of the child qgroups.
> You may use it like:
> 	btrfs qgroup show -c <path>

I haven't looked closely, but using -c leads probably to a infinite loop
somewhere. The screen scrolls away quickly filled with spaces after it
prints the table:

qgroupid rfer        excl        child
-------- ----        ----        -----
0/5      921600      921600      ---
0/267    704512      12288       ---
0/268    700416      8192        ---
0/269    7206805504  4096        ---
0/277    7206805504  4096        ---
0/278    36884398080 36884398080 ---
1/1      7206809600  7206809600  0/269,0/277

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-07  7:21 ` [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result Wang Shilong
@ 2013-10-08 15:34   ` David Sterba
  2013-10-08 16:27     ` Shilong Wang
  2013-10-08 16:54     ` Shilong Wang
  0 siblings, 2 replies; 22+ messages in thread
From: David Sterba @ 2013-10-08 15:34 UTC (permalink / raw)
  To: Wang Shilong; +Cc: linux-btrfs, dsterba

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 15:34   ` David Sterba
@ 2013-10-08 16:27     ` Shilong Wang
  2013-10-08 16:34       ` Shilong Wang
  2013-10-08 16:34       ` David Sterba
  2013-10-08 16:54     ` Shilong Wang
  1 sibling, 2 replies; 22+ messages in thread
From: Shilong Wang @ 2013-10-08 16:27 UTC (permalink / raw)
  To: David Sterba, Wang Shilong, linux-btrfs

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 16:27     ` Shilong Wang
@ 2013-10-08 16:34       ` Shilong Wang
  2013-10-08 16:34       ` David Sterba
  1 sibling, 0 replies; 22+ messages in thread
From: Shilong Wang @ 2013-10-08 16:34 UTC (permalink / raw)
  To: David Sterba, Wang Shilong, linux-btrfs

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 16:27     ` Shilong Wang
  2013-10-08 16:34       ` Shilong Wang
@ 2013-10-08 16:34       ` David Sterba
  1 sibling, 0 replies; 22+ messages in thread
From: David Sterba @ 2013-10-08 16:34 UTC (permalink / raw)
  To: Shilong Wang; +Cc: David Sterba, Wang Shilong, linux-btrfs

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.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 15:34   ` David Sterba
  2013-10-08 16:27     ` Shilong Wang
@ 2013-10-08 16:54     ` Shilong Wang
  2013-10-08 17:01       ` Hugo Mills
  1 sibling, 1 reply; 22+ messages in thread
From: Shilong Wang @ 2013-10-08 16:54 UTC (permalink / raw)
  To: David Sterba, Wang Shilong, linux-btrfs

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 16:54     ` Shilong Wang
@ 2013-10-08 17:01       ` Hugo Mills
  2013-10-08 17:10         ` Hugo Mills
  0 siblings, 1 reply; 22+ messages in thread
From: Hugo Mills @ 2013-10-08 17:01 UTC (permalink / raw)
  To: Shilong Wang; +Cc: David Sterba, Wang Shilong, linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 2352 bytes --]

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: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk ===
  PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk
  --- I'll take your bet, but make it ten thousand francs. I'm only ---  
                       a _poor_ corrupt official.                        

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result
  2013-10-08 17:01       ` Hugo Mills
@ 2013-10-08 17:10         ` Hugo Mills
  0 siblings, 0 replies; 22+ messages in thread
From: Hugo Mills @ 2013-10-08 17:10 UTC (permalink / raw)
  To: Shilong Wang, David Sterba, Wang Shilong, linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 885 bytes --]

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. :)

-- 
=== Hugo Mills: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk ===
  PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk
   --- I spent most of my money on drink, women and fast cars. The ---   
                      rest I wasted.  -- James Hunt                      

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-10-08 17:10 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-07  7:21 [PATCH v3 00/12] enhance btrfs qgroup show command Wang Shilong
2013-10-07  7:21 ` [PATCH v3 01/12] Btrfs-progs: restructure show_qgroups Wang Shilong
2013-10-07  7:21 ` [PATCH v3 02/12] Btrfs-progs: introduces '-p' option to print the ID of the parent qgroups Wang Shilong
2013-10-08 15:06   ` David Sterba
2013-10-07  7:21 ` [PATCH v3 03/12] Btrfs-progs: introduces '-c' option to print the ID of the child qgroups Wang Shilong
2013-10-08 15:08   ` David Sterba
2013-10-07  7:21 ` [PATCH v3 04/12] Btrfs-progs: introduce '-r' option to print max referenced size of qgroups Wang Shilong
2013-10-07  7:21 ` [PATCH v3 05/12] Btrfs-progs: introduce '-e' option to print max exclusive " Wang Shilong
2013-10-07  7:21 ` [PATCH v3 06/12] Btrfs-progs: list all qgroups impact given path(include ancestral qgroups) Wang Shilong
2013-10-07  7:21 ` [PATCH v3 07/12] Btrfs-progs: list all qgroups impact given path(exclude " Wang Shilong
2013-10-07  7:21 ` [PATCH v3 08/12] Btrfs-progs: enhance btrfs qgroup show to sort qgroups Wang Shilong
2013-10-07  7:21 ` [PATCH v3 09/12] Btrfs-progs: enhance btrfs qgroup to print the result as a table Wang Shilong
2013-10-07  7:21 ` [PATCH v3 10/12] Btrfs-progs: add '--block-size' option to control print result Wang Shilong
2013-10-08 15:34   ` David Sterba
2013-10-08 16:27     ` Shilong Wang
2013-10-08 16:34       ` Shilong Wang
2013-10-08 16:34       ` David Sterba
2013-10-08 16:54     ` Shilong Wang
2013-10-08 17:01       ` Hugo Mills
2013-10-08 17:10         ` Hugo Mills
2013-10-07  7:21 ` [PATCH v3 11/12] Btrfs-progs: make pretty_size_snprintf() return len Wang Shilong
2013-10-07  7:21 ` [PATCH v3 12/12] Btrfs-progs: add '-h' options to print sizes in human readable format Wang Shilong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).