#include <sys/ioctl.h>
#include "ctree.h"
#include "ioctl.h"
+#include "utils.h"
+#include <errno.h>
#define BTRFS_QGROUP_NFILTERS_INCREASE (2 * BTRFS_QGROUP_FILTER_MAX)
#define BTRFS_QGROUP_NCOMPS_INCREASE (2 * BTRFS_QGROUP_COMP_MAX)
/*
* qgroupid,rfer,excl default to set
*/
-struct {
+static struct {
char *name;
char *column_name;
int need_print;
+ unsigned unit_mode;
+ int max_len;
} btrfs_qgroup_columns[] = {
{
.name = "qgroupid",
.column_name = "Qgroupid",
.need_print = 1,
+ .unit_mode = 0,
+ .max_len = 8,
},
{
.name = "rfer",
.column_name = "Rfer",
.need_print = 1,
+ .unit_mode = UNITS_DEFAULT,
+ .max_len = 12,
},
{
.name = "excl",
.column_name = "Excl",
.need_print = 1,
+ .unit_mode = UNITS_DEFAULT,
+ .max_len = 12,
},
{ .name = "max_rfer",
.column_name = "Max_rfer",
.need_print = 0,
+ .unit_mode = UNITS_DEFAULT,
+ .max_len = 12,
},
{
.name = "max_excl",
.column_name = "Max_excl",
.need_print = 0,
+ .unit_mode = UNITS_DEFAULT,
+ .max_len = 12,
},
{
.name = "parent",
.column_name = "Parent",
.need_print = 0,
+ .unit_mode = 0,
+ .max_len = 7,
},
{
.name = "child",
.column_name = "Child",
.need_print = 0,
+ .unit_mode = 0,
+ .max_len = 5,
},
{
.name = NULL,
.column_name = NULL,
.need_print = 0,
+ .unit_mode = 0,
},
};
{
int i;
- BUG_ON(column < 0 || column > BTRFS_QGROUP_ALL);
+ ASSERT(0 <= column && column <= BTRFS_QGROUP_ALL);
if (column < BTRFS_QGROUP_ALL) {
btrfs_qgroup_columns[column].need_print = 1;
btrfs_qgroup_columns[i].need_print = 1;
}
-static void print_parent_column(struct btrfs_qgroup *qgroup)
+void btrfs_qgroup_setup_units(unsigned unit_mode)
+{
+ btrfs_qgroup_columns[BTRFS_QGROUP_RFER].unit_mode = unit_mode;
+ btrfs_qgroup_columns[BTRFS_QGROUP_EXCL].unit_mode = unit_mode;
+ btrfs_qgroup_columns[BTRFS_QGROUP_MAX_RFER].unit_mode = unit_mode;
+ btrfs_qgroup_columns[BTRFS_QGROUP_MAX_EXCL].unit_mode = unit_mode;
+}
+
+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",
+ btrfs_qgroup_level(list->qgroup->qgroupid),
+ btrfs_qgroup_subvid(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",
+ btrfs_qgroup_level(list->member->qgroupid),
+ btrfs_qgroup_subvid(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;
+ int unit_mode = btrfs_qgroup_columns[column].unit_mode;
+ int max_len = btrfs_qgroup_columns[column].max_len;
+
+ ASSERT(0 <= column && column < BTRFS_QGROUP_ALL);
switch (column) {
case BTRFS_QGROUP_QGROUPID:
- printf("%llu/%llu", qgroup->qgroupid >> 48,
- ((1ll << 48) - 1) & qgroup->qgroupid);
+ len = printf("%llu/%llu",
+ btrfs_qgroup_level(qgroup->qgroupid),
+ btrfs_qgroup_subvid(qgroup->qgroupid));
+ print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
break;
case BTRFS_QGROUP_RFER:
- printf("%lld", qgroup->rfer);
+ len = printf("%*s", max_len, pretty_size_mode(qgroup->rfer, unit_mode));
break;
case BTRFS_QGROUP_EXCL:
- printf("%lld", qgroup->excl);
+ len = printf("%*s", max_len, pretty_size_mode(qgroup->excl, unit_mode));
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);
+ if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
+ len = printf("%*s", max_len, pretty_size_mode(qgroup->max_rfer, unit_mode));
+ else
+ len = printf("%*s", max_len, "none");
break;
case BTRFS_QGROUP_MAX_EXCL:
- printf("%llu", qgroup->max_excl);
+ if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
+ len = printf("%*s", max_len, pretty_size_mode(qgroup->max_excl, unit_mode));
+ else
+ len = printf("%*s", max_len, "none");
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;
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(void)
+{
+ int i;
+ int len;
+ int max_len;
+
+ for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+ max_len = btrfs_qgroup_columns[i].max_len;
+ if (!btrfs_qgroup_columns[i].need_print)
+ continue;
+ if ((i == BTRFS_QGROUP_QGROUPID) | (i == BTRFS_QGROUP_PARENT) |
+ (i == BTRFS_QGROUP_CHILD))
+ printf("%-*s", max_len, btrfs_qgroup_columns[i].name);
+ else
+ printf("%*s", max_len, btrfs_qgroup_columns[i].name);
+ printf(" ");
+ }
+ printf("\n");
+ for (i = 0; i < BTRFS_QGROUP_ALL; i++) {
+ max_len = btrfs_qgroup_columns[i].max_len;
+ if (!btrfs_qgroup_columns[i].need_print)
+ continue;
+ if ((i == BTRFS_QGROUP_QGROUPID) | (i == BTRFS_QGROUP_PARENT) |
+ (i == BTRFS_QGROUP_CHILD)) {
+ len = strlen(btrfs_qgroup_columns[i].name);
+ while (len--)
+ printf("-");
+ len = max_len - strlen(btrfs_qgroup_columns[i].name);
+ while (len--)
+ printf(" ");
+ } else {
+ len = max_len - strlen(btrfs_qgroup_columns[i].name);
+ while (len--)
+ printf(" ");
+ len = strlen(btrfs_qgroup_columns[i].name);
+ while (len--)
+ printf("-");
+ }
+ printf(" ");
+ }
+ printf("\n");
+}
+
static void qgroup_lookup_init(struct qgroup_lookup *tree)
{
tree->root.rb_node = NULL;
size = sizeof(struct btrfs_qgroup_comparer_set) +
BTRFS_QGROUP_NCOMPS_INCREASE *
sizeof(struct btrfs_qgroup_comparer);
- set = malloc(size);
+ set = calloc(1, size);
if (!set) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
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);
+ ASSERT(set != NULL);
+ ASSERT(comparer < BTRFS_QGROUP_COMP_MAX);
+ ASSERT(set->ncomps <= set->total);
if (set->ncomps == set->total) {
+ void *tmp;
+
size = set->total + BTRFS_QGROUP_NCOMPS_INCREASE;
size = sizeof(*set) +
size * sizeof(struct btrfs_qgroup_comparer);
+ tmp = set;
set = realloc(set, size);
if (!set) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
+ free(tmp);
exit(1);
}
*comp_set = set;
}
- BUG_ON(set->comps[set->ncomps].comp_func);
+ ASSERT(set->comps[set->ncomps].comp_func == NULL);
set->comps[set->ncomps].comp_func = all_comp_funcs[comparer];
set->comps[set->ncomps].is_descending = is_descending;
if (pa && child) {
list = malloc(sizeof(*list));
if (!list) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
exit(1);
}
list->qgroup = pa;
if (!ret)
return 0;
- bq = malloc(sizeof(*bq));
+ bq = calloc(1, sizeof(*bq));
if (!bq) {
- printf("memory allocation failed\n");
+ error("memory allocation failed");
exit(1);
}
- memset(bq, 0, sizeof(*bq));
if (qgroupid) {
bq->qgroupid = qgroupid;
INIT_LIST_HEAD(&bq->qgroups);
if (parent && child) {
list = malloc(sizeof(*list));
if (!list) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
exit(1);
}
list->qgroup = parent;
}
ret = qgroup_tree_insert(qgroup_lookup, bq);
if (ret) {
- printf("failed to insert tree %llu\n",
- bq->qgroupid);
+ error("failed to insert %llu into tree: %s",
+ (unsigned long long)bq->qgroupid, strerror(-ret));
exit(1);
}
return ret;
}
-void __free_btrfs_qgroup(struct btrfs_qgroup *bq)
+static void __free_btrfs_qgroup(struct btrfs_qgroup *bq)
{
struct btrfs_qgroup_list *list;
while (!list_empty(&bq->qgroups)) {
free(bq);
}
-void __free_all_qgroups(struct qgroup_lookup *root_tree)
+static void __free_all_qgroups(struct qgroup_lookup *root_tree)
{
struct btrfs_qgroup *entry;
struct rb_node *n;
size = sizeof(struct btrfs_qgroup_filter_set) +
BTRFS_QGROUP_NFILTERS_INCREASE *
sizeof(struct btrfs_qgroup_filter);
- set = malloc(size);
+ set = calloc(1, size);
if (!set) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
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);
+ ASSERT(set != NULL);
+ ASSERT(filter < BTRFS_QGROUP_FILTER_MAX);
+ ASSERT(set->nfilters <= set->total);
if (set->nfilters == set->total) {
+ void *tmp;
+
size = set->total + BTRFS_QGROUP_NFILTERS_INCREASE;
size = sizeof(*set) + size * sizeof(struct btrfs_qgroup_filter);
+ tmp = set;
set = realloc(set, size);
if (!set) {
- fprintf(stderr, "memory allocation failed\n");
+ error("memory allocation failed");
+ free(tmp);
exit(1);
}
memset(&set->filters[set->total], 0,
set->total += BTRFS_QGROUP_NFILTERS_INCREASE;
*filter_set = set;
}
- BUG_ON(set->filters[set->nfilters].filter_func);
+
+ ASSERT(set->filters[set->nfilters].filter_func == NULL);
set->filters[set->nfilters].filter_func = all_filter_funcs[filter];
set->filters[set->nfilters].data = data;
set->nfilters++;
return 0;
}
+static void __update_columns_max_len(struct btrfs_qgroup *bq,
+ enum btrfs_qgroup_column_enum column)
+{
+ struct btrfs_qgroup_list *list = NULL;
+ char tmp[100];
+ int len;
+ unsigned unit_mode = btrfs_qgroup_columns[column].unit_mode;
+
+ ASSERT(0 <= column && column < BTRFS_QGROUP_ALL);
+
+ switch (column) {
+
+ case BTRFS_QGROUP_QGROUPID:
+ sprintf(tmp, "%llu/%llu",
+ btrfs_qgroup_level(bq->qgroupid),
+ btrfs_qgroup_subvid(bq->qgroupid));
+ len = strlen(tmp);
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ break;
+ case BTRFS_QGROUP_RFER:
+ len = strlen(pretty_size_mode(bq->rfer, unit_mode));
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ break;
+ case BTRFS_QGROUP_EXCL:
+ len = strlen(pretty_size_mode(bq->excl, unit_mode));
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ break;
+ case BTRFS_QGROUP_MAX_RFER:
+ len = strlen(pretty_size_mode(bq->max_rfer, unit_mode));
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ break;
+ case BTRFS_QGROUP_MAX_EXCL:
+ len = strlen(pretty_size_mode(bq->max_excl, unit_mode));
+ 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 += sprintf(tmp, "%llu/%llu",
+ btrfs_qgroup_level(list->qgroup->qgroupid),
+ btrfs_qgroup_subvid(list->qgroup->qgroupid));
+ if (!list_is_last(&list->next_qgroup, &bq->qgroups))
+ len += 1;
+ }
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ break;
+ case BTRFS_QGROUP_CHILD:
+ len = 0;
+ list_for_each_entry(list, &bq->members, next_member) {
+ len += sprintf(tmp, "%llu/%llu",
+ btrfs_qgroup_level(list->member->qgroupid),
+ btrfs_qgroup_subvid(list->member->qgroupid));
+ if (!list_is_last(&list->next_member, &bq->members))
+ len += 1;
+ }
+ if (btrfs_qgroup_columns[column].max_len < len)
+ btrfs_qgroup_columns[column].max_len = len;
+ 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,
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);
}
}
+
+static inline void print_status_flag_warning(u64 flags)
+{
+ if (!(flags & BTRFS_QGROUP_STATUS_FLAG_ON))
+ warning("quota disabled, qgroup data may be out of date");
+ else if (flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN)
+ warning("rescan is running, qgroup data may be incorrect");
+ else if (flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)
+ warning("qgroup data inconsistent, rescan recommended");
+}
+
static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
{
int ret;
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;
sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
sk->max_type = BTRFS_QGROUP_RELATION_KEY;
- sk->min_type = BTRFS_QGROUP_INFO_KEY;
+ sk->min_type = BTRFS_QGROUP_STATUS_KEY;
sk->max_objectid = (u64)-1;
sk->max_offset = (u64)-1;
sk->max_transid = (u64)-1;
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));
+ error("cannot perform the search: %s",
+ strerror(errno));
return ret;
}
/* the ioctl returns the number of item it found in nr_items */
off);
off += sizeof(*sh);
- if (sh->type == BTRFS_QGROUP_INFO_KEY) {
+ if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_STATUS_KEY) {
+ struct btrfs_qgroup_status_item *si;
+ u64 flags;
+
+ si = (struct btrfs_qgroup_status_item *)
+ (args.buf + off);
+ flags = btrfs_stack_qgroup_status_flags(si);
+ print_status_flag_warning(flags);
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_INFO_KEY) {
info = (struct btrfs_qgroup_info_item *)
(args.buf + off);
a1 = btrfs_stack_qgroup_info_generation(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) {
+ add_qgroup(qgroup_lookup,
+ btrfs_search_header_offset(sh), a1,
+ a2, a3, a4, a5, 0, 0, 0, 0, 0, NULL,
+ NULL);
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_LIMIT_KEY) {
limit = (struct btrfs_qgroup_limit_item *)
(args.buf + off);
(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)
+ add_qgroup(qgroup_lookup,
+ btrfs_search_header_offset(sh), 0,
+ 0, 0, 0, 0, a1, a2, a3, a4, a5,
+ NULL, NULL);
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_RELATION_KEY) {
+ if (btrfs_search_header_offset(sh)
+ < btrfs_search_header_objectid(sh))
goto skip;
bq = qgroup_tree_search(qgroup_lookup,
- sh->offset);
+ btrfs_search_header_offset(sh));
if (!bq)
goto skip;
bq1 = qgroup_tree_search(qgroup_lookup,
- sh->objectid);
+ btrfs_search_header_objectid(sh));
if (!bq1)
goto skip;
- add_qgroup(qgroup_lookup, sh->offset, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, bq, bq1);
+ add_qgroup(qgroup_lookup,
+ btrfs_search_header_offset(sh), 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, bq, bq1);
} else
goto done;
skip:
- off += sh->len;
+ off += btrfs_search_header_len(sh);
/*
* 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->min_type = btrfs_search_header_type(sh);
+ sk->min_offset = btrfs_search_header_offset(sh);
+ sk->min_objectid = btrfs_search_header_objectid(sh);
}
sk->nr_items = 4096;
/*
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);
}
}
print_all_qgroups(&sort_tree);
__free_all_qgroups(&qgroup_lookup);
- btrfs_qgroup_free_filter_set(filter_set);
+ free(filter_set);
+ free(comp_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;
-}
-
-int btrfs_qgroup_parse_sort_string(char *opt_arg,
+int btrfs_qgroup_parse_sort_string(const char *opt_arg,
struct btrfs_qgroup_comparer_set **comps)
{
int order;
char *p;
char **ptr_argv;
int what_to_sort;
+ char *opt_tmp;
+ int ret = 0;
- while ((p = strtok(opt_arg, ",")) != NULL) {
+ opt_tmp = strdup(opt_arg);
+ if (!opt_tmp)
+ return -ENOMEM;
+
+ while ((p = strtok(opt_tmp, ",")) != NULL) {
flag = 0;
ptr_argv = all_sort_items;
ptr_argv++;
}
- if (flag == 0)
- return -1;
-
- else {
+ if (flag == 0) {
+ ret = -1;
+ goto out;
+ } else {
if (*p == '+') {
order = 0;
p++;
order = 0;
what_to_sort = btrfs_qgroup_get_sort_item(p);
- if (what_to_sort < 0)
- return -1;
+ if (what_to_sort < 0) {
+ ret = -1;
+ goto out;
+ }
btrfs_qgroup_setup_comparer(comps, what_to_sort, order);
}
- opt_arg = NULL;
+ free(opt_tmp);
+ opt_tmp = NULL;
}
- return 0;
-}
-
-u64 parse_qgroupid(char *p)
-{
- char *s = strchr(p, '/');
- char *ptr_src_end = p + strlen(p);
- char *ptr_parse_end = NULL;
- u64 level;
- u64 id;
-
- if (!s) {
- id = strtoull(p, &ptr_parse_end, 10);
- if (ptr_parse_end != ptr_src_end)
- goto err;
- return id;
- }
- level = strtoull(p, &ptr_parse_end, 10);
- if (ptr_parse_end != s)
- goto err;
-
- id = strtoull(s+1, &ptr_parse_end, 10);
- if (ptr_parse_end != ptr_src_end)
- goto err;
-
- return (level << 48) | id;
-err:
- fprintf(stderr, "ERROR:invalid qgroupid\n");
- exit(-1);
+out:
+ free(opt_tmp);
+ return ret;
}
int qgroup_inherit_size(struct btrfs_qgroup_inherit *p)
out = calloc(sizeof(*out) + sizeof(out->qgroups[0]) * (nitems + n), 1);
if (out == NULL) {
- fprintf(stderr, "ERROR: Not enough memory\n");
- return 13;
+ error("not enough memory");
+ return -ENOMEM;
}
if (*inherit) {
int pos = 0;
if (qgroupid == 0) {
- fprintf(stderr, "ERROR: bad qgroup specification\n");
- return 12;
+ error("invalid qgroup specification, qgroupid must not 0");
+ return -EINVAL;
}
if (*inherit)
p = strchr(arg, ':');
if (!p) {
bad:
- fprintf(stderr, "ERROR: bad copy specification\n");
- return 12;
+ error("invalid copy specification, missing separator :");
+ return -EINVAL;
}
*p = 0;
qgroup_src = parse_qgroupid(arg);