{
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;
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("\n");
}
-static void print_table_head()
+static void print_table_head(void)
{
int i;
int len;
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;
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)
+/*
+ * Lookup or insert btrfs_qgroup into qgroup_lookup.
+ *
+ * Search a btrfs_qgroup with @qgroupid from the @qgroup_lookup. If not found,
+ * initialize a btrfs_qgroup with the given qgroupid and insert it to the
+ * @qgroup_lookup.
+ *
+ * Return the pointer to the btrfs_qgroup if found or if inserted successfully.
+ * Return ERR_PTR if any error occurred.
+ */
+static struct btrfs_qgroup *get_or_add_qgroup(
+ struct qgroup_lookup *qgroup_lookup, u64 qgroupid)
{
struct btrfs_qgroup *bq;
- struct btrfs_qgroup_list *list;
+ int ret;
bq = qgroup_tree_search(qgroup_lookup, qgroupid);
- if (!bq || bq->qgroupid != qgroupid)
- return -ENOENT;
+ if (bq)
+ return bq;
- 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);
+ bq = calloc(1, sizeof(*bq));
+ if (!bq) {
+ error("memory allocation failed");
+ return ERR_PTR(-ENOMEM);
}
+
+ bq->qgroupid = qgroupid;
+ INIT_LIST_HEAD(&bq->qgroups);
+ INIT_LIST_HEAD(&bq->members);
+
+ ret = qgroup_tree_insert(qgroup_lookup, bq);
+ if (ret) {
+ error("failed to insert %llu into tree: %s",
+ (unsigned long long)bq->qgroupid, strerror(-ret));
+ free(bq);
+ return ERR_PTR(ret);
+ }
+
+ return bq;
+}
+
+static int update_qgroup_info(struct qgroup_lookup *qgroup_lookup, u64 qgroupid,
+ struct btrfs_qgroup_info_item *info)
+{
+ struct btrfs_qgroup *bq;
+
+ bq = get_or_add_qgroup(qgroup_lookup, qgroupid);
+ if (IS_ERR_OR_NULL(bq))
+ return PTR_ERR(bq);
+
+ bq->generation = btrfs_stack_qgroup_info_generation(info);
+ bq->rfer = btrfs_stack_qgroup_info_referenced(info);
+ bq->rfer_cmpr = btrfs_stack_qgroup_info_referenced_compressed(info);
+ bq->excl = btrfs_stack_qgroup_info_exclusive(info);
+ bq->excl_cmpr = btrfs_stack_qgroup_info_exclusive_compressed(info);
+
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)
+static int update_qgroup_limit(struct qgroup_lookup *qgroup_lookup,
+ u64 qgroupid,
+ struct btrfs_qgroup_limit_item *limit)
{
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 = get_or_add_qgroup(qgroup_lookup, qgroupid);
+ if (IS_ERR_OR_NULL(bq))
+ return PTR_ERR(bq);
- 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);
+ bq->flags = btrfs_stack_qgroup_limit_flags(limit);
+ bq->max_rfer = btrfs_stack_qgroup_limit_max_referenced(limit);
+ bq->max_excl = btrfs_stack_qgroup_limit_max_exclusive(limit);
+ bq->rsv_rfer = btrfs_stack_qgroup_limit_rsv_referenced(limit);
+ bq->rsv_excl = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
+
+ return 0;
+}
+
+static int update_qgroup_relation(struct qgroup_lookup *qgroup_lookup,
+ u64 child_id, u64 parent_id)
+{
+ struct btrfs_qgroup *child;
+ struct btrfs_qgroup *parent;
+ struct btrfs_qgroup_list *list;
+
+ child = qgroup_tree_search(qgroup_lookup, child_id);
+ if (!child) {
+ error("cannot find the qgroup %llu/%llu",
+ btrfs_qgroup_level(child_id),
+ btrfs_qgroup_subvid(child_id));
+ 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 (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);
+
+ parent = qgroup_tree_search(qgroup_lookup, parent_id);
+ if (!parent) {
+ error("cannot find the qgroup %llu/%llu",
+ btrfs_qgroup_level(parent_id),
+ btrfs_qgroup_subvid(parent_id));
+ return -ENOENT;
}
- ret = qgroup_tree_insert(qgroup_lookup, bq);
- if (ret) {
- printf("failed to insert tree %llu\n",
- bq->qgroupid);
- exit(1);
+
+ list = malloc(sizeof(*list));
+ if (!list) {
+ error("memory allocation failed");
+ return -ENOMEM;
}
- return ret;
+
+ list->qgroup = parent;
+ list->member = child;
+ list_add_tail(&list->next_qgroup, &child->qgroups);
+ list_add_tail(&list->next_member, &parent->members);
+
+ return 0;
}
static void __free_btrfs_qgroup(struct btrfs_qgroup *bq)
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++;
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];
int len;
unsigned unit_mode = btrfs_qgroup_columns[column].unit_mode;
+ ASSERT(0 <= column && column < BTRFS_QGROUP_ALL);
+
switch (column) {
case BTRFS_QGROUP_QGROUPID:
static inline void print_status_flag_warning(u64 flags)
{
if (!(flags & BTRFS_QGROUP_STATUS_FLAG_ON))
- fprintf(stderr,
- "WARNING: Quota disabled, qgroup data may be out of date\n");
+ warning("quota disabled, qgroup data may be out of date");
else if (flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN)
- fprintf(stderr,
- "WARNING: Rescan is running, qgroup data may be incorrect\n");
+ warning("rescan is running, qgroup data may be incorrect");
else if (flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)
- fprintf(stderr,
- "WARNING: Qgroup data inconsistent, rescan recommended\n");
+ warning("qgroup data inconsistent, rescan recommended");
}
static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
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;
+ u64 qgroupid;
+ u64 qgroupid1;
memset(&args, 0, sizeof(args));
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;
- }
+ if (ret < 0)
+ return -errno;
+
/* the ioctl returns the number of item it found in nr_items */
if (sk->nr_items == 0)
break;
off);
off += sizeof(*sh);
- if (sh->type == BTRFS_QGROUP_STATUS_KEY) {
+ if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_STATUS_KEY) {
struct btrfs_qgroup_status_item *si;
u64 flags;
(args.buf + off);
flags = btrfs_stack_qgroup_status_flags(si);
print_status_flag_warning(flags);
- } else if (sh->type == BTRFS_QGROUP_INFO_KEY) {
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_INFO_KEY) {
+ qgroupid = btrfs_search_header_offset(sh);
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) {
+
+ update_qgroup_info(qgroup_lookup, qgroupid,
+ info);
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_LIMIT_KEY) {
+ qgroupid = btrfs_search_header_offset(sh);
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)
+ (args.buf + off);
+
+ update_qgroup_limit(qgroup_lookup, qgroupid,
+ limit);
+ } else if (btrfs_search_header_type(sh)
+ == BTRFS_QGROUP_RELATION_KEY) {
+ qgroupid = btrfs_search_header_offset(sh);
+ qgroupid1 = btrfs_search_header_objectid(sh);
+
+ if (qgroupid < qgroupid1)
goto skip;
- add_qgroup(qgroup_lookup, sh->offset, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, bq, bq1);
+
+ update_qgroup_relation(qgroup_lookup, qgroupid,
+ qgroupid1);
} 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;
/*
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;
+
+ opt_tmp = strdup(opt_arg);
+ if (!opt_tmp)
+ return -ENOMEM;
- while ((p = strtok(opt_arg, ",")) != NULL) {
+ p = strtok(opt_tmp, ",");
+ while (p) {
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;
+ p = strtok(NULL, ",");
}
- return 0;
+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");
+ error("not enough memory");
return -ENOMEM;
}
int pos = 0;
if (qgroupid == 0) {
- fprintf(stderr, "ERROR: bad qgroup specification\n");
+ error("invalid qgroup specification, qgroupid must not 0");
return -EINVAL;
}
p = strchr(arg, ':');
if (!p) {
bad:
- fprintf(stderr, "ERROR: bad copy specification\n");
+ error("invalid copy specification, missing separator :");
return -EINVAL;
}
*p = 0;