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