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 -- 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
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 02/12] Btrfs-progs: introduces ''-p'' option to print the ID of the parent qgroups
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 03/12] Btrfs-progs: introduces ''-c'' option to print the ID of the child qgroups
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 04/12] Btrfs-progs: introduce ''-r'' option to print max referenced size of qgroups
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 05/12] Btrfs-progs: introduce ''-e'' option to print max exclusive size of qgroups
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 06/12] Btrfs-progs: list all qgroups impact given path(include ancestral qgroups)
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 07/12] Btrfs-progs: list all qgroups impact given path(exclude ancestral qgroups)
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 08/12] Btrfs-progs: enhance btrfs qgroup show to sort qgroups
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 09/12] Btrfs-progs: enhance btrfs qgroup to print the result as a table
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 11/12] Btrfs-progs: make pretty_size_snprintf() return len
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-info.html
Wang Shilong
2013-Oct-07 07:21 UTC
[PATCH v3 12/12] Btrfs-progs: add ''-h'' options to print sizes in human readable format
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-info.html
David Sterba
2013-Oct-08 15:06 UTC
Re: [PATCH v3 02/12] Btrfs-progs: introduces ''-p'' option to print the ID of the parent qgroups
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 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Oct-08 15:08 UTC
Re: [PATCH v3 03/12] Btrfs-progs: introduces ''-c'' option to print the ID of the child qgroups
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 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Oct-08 15:34 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
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
Shilong Wang
2013-Oct-08 16:27 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
Thanks for finding this, the problem comes to patch [v3 9/12]. When updating max columns len of child_qgroup, i miswrite qgroup->member to qgroup->parent, i have updated this patch and send a v4, it can be appiled without conflicts with later. Thanks, Wang 2013/10/8 David Sterba <dsterba@suse.cz>:> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote: >> You can use it like: >> btrfs qgroup show --block-size=m <mnt> >> >> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E. > > There is no distinction between the 1000 and 1024 based prefixes, also > no way to get the raw values in bytes. I don''t have a suggestion how to > do that, merely letting you know that this could go separately (this and > the "-h" patch, the rest shall be integrated). > > Also, the numbers in the table should be aligned to the right: > > $ btrfs qgroup show -h -p /mnt/ > qgroupid rfer excl parent > -------- ---- ---- ------ > 0/5 900.00KiB 900.00KiB --- > 0/267 688.00KiB 12.00KiB 1/5 > 0/268 684.00KiB 8.00KiB 1/5 > 0/269 6.71GiB 4.00KiB 1/1 > 0/277 6.71GiB 4.00KiB 1/1 > 0/278 39.74GiB 39.74GiB 1/2 > 1/1 6.71GiB 6.71GiB --- > 1/2 39.74GiB 39.74GiB --- > 1/5 696.00KiB 696.00KiB --- > > > david > -- > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Shilong Wang
2013-Oct-08 16:34 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
Sorry, This should to reply to the bug that you find, not this thread. Anyway, you are smart enough to get this ..... 2013/10/9 Shilong Wang <wangshilong1991@gmail.com>:> Thanks for finding this, the problem comes to patch [v3 9/12]. > When updating max columns len of child_qgroup, i miswrite qgroup->member to > qgroup->parent, i have updated this patch and send a v4, it can be > appiled without conflicts with later. > > Thanks, > Wang > 2013/10/8 David Sterba <dsterba@suse.cz>: >> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote: >>> You can use it like: >>> btrfs qgroup show --block-size=m <mnt> >>> >>> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E. >> >> There is no distinction between the 1000 and 1024 based prefixes, also >> no way to get the raw values in bytes. I don''t have a suggestion how to >> do that, merely letting you know that this could go separately (this and >> the "-h" patch, the rest shall be integrated). >> >> Also, the numbers in the table should be aligned to the right: >> >> $ btrfs qgroup show -h -p /mnt/ >> qgroupid rfer excl parent >> -------- ---- ---- ------ >> 0/5 900.00KiB 900.00KiB --- >> 0/267 688.00KiB 12.00KiB 1/5 >> 0/268 684.00KiB 8.00KiB 1/5 >> 0/269 6.71GiB 4.00KiB 1/1 >> 0/277 6.71GiB 4.00KiB 1/1 >> 0/278 39.74GiB 39.74GiB 1/2 >> 1/1 6.71GiB 6.71GiB --- >> 1/2 39.74GiB 39.74GiB --- >> 1/5 696.00KiB 696.00KiB --- >> >> >> david >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Oct-08 16:34 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
On Wed, Oct 09, 2013 at 12:27:23AM +0800, Shilong Wang wrote:> Thanks for finding this, the problem comes to patch [v3 9/12]. > When updating max columns len of child_qgroup, i miswrite qgroup->member to > qgroup->parent, i have updated this patch and send a v4, it can be > appiled without conflicts with later.Works for me, thanks, replaced. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Shilong Wang
2013-Oct-08 16:54 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
Hi David, 2013/10/8 David Sterba <dsterba@suse.cz>:> On Mon, Oct 07, 2013 at 03:21:46PM +0800, Wang Shilong wrote: >> You can use it like: >> btrfs qgroup show --block-size=m <mnt> >> >> Here, block size supports k/K/m/M/g/G/t/T/p/P/e/E. > > There is no distinction between the 1000 and 1024 based prefixes, also > no way to get the raw values in bytes. I don''t have a suggestion how to > do that, merely letting you know that this could go separately (this and > the "-h" patch, the rest shall be integrated).I implement this like the command ''du''. In default, we print result in bytes. And block size don''t give a byte unit implicitly.Aslo i don''t know why we need to distinct 1000 and 1024, i don''t have any ideas about this.> > Also, the numbers in the table should be aligned to the right:Yes, this should be fixed. Thanks, Wang> > $ btrfs qgroup show -h -p /mnt/ > qgroupid rfer excl parent > -------- ---- ---- ------ > 0/5 900.00KiB 900.00KiB --- > 0/267 688.00KiB 12.00KiB 1/5 > 0/268 684.00KiB 8.00KiB 1/5 > 0/269 6.71GiB 4.00KiB 1/1 > 0/277 6.71GiB 4.00KiB 1/1 > 0/278 39.74GiB 39.74GiB 1/2 > 1/1 6.71GiB 6.71GiB --- > 1/2 39.74GiB 39.74GiB --- > 1/5 696.00KiB 696.00KiB --- > > > david > -- > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2013-Oct-08 17:01 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
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.
Hugo Mills
2013-Oct-08 17:10 UTC
Re: [PATCH v3 10/12] Btrfs-progs: add ''--block-size'' option to control print result
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