X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=qgroup.c;h=11659e8394dda15fcfac2731de41b23bf7896ed5;hb=fd5767a574958624828149687e76a5f0276f1dc8;hp=5de35e2b65c2e0441eb3f7345af18036676d7443;hpb=85d608f7ecec2317456059199644e9f940a38e5c;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/qgroup.c b/qgroup.c index 5de35e2..11659e8 100644 --- a/qgroup.c +++ b/qgroup.c @@ -480,7 +480,7 @@ int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set **comp_set, *comp_set = set; } - ASSERT(set->comps[set->ncomps].comp_func != NULL); + 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; @@ -578,113 +578,119 @@ static struct btrfs_qgroup *qgroup_tree_search(struct qgroup_lookup *root_tree, 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) { - error("memory allocation failed"); - 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 = calloc(1, sizeof(*bq)); - if (!bq) { - error("memory allocation failed"); - exit(1); - } - 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) { - error("memory allocation failed"); - 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) { - error("failed to insert %llu into tree: %s", - (unsigned long long)bq->qgroupid, strerror(-ret)); - 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) @@ -847,7 +853,7 @@ int btrfs_qgroup_setup_filter(struct btrfs_qgroup_filter_set **filter_set, *filter_set = set; } - ASSERT(set->filters[set->nfilters].filter_func != NULL); + 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++; @@ -1040,15 +1046,12 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) struct btrfs_ioctl_search_header *sh; unsigned long off = 0; unsigned int i; + struct btrfs_qgroup_status_item *si; 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 flags; + u64 qgroupid; + u64 qgroupid1; memset(&args, 0, sizeof(args)); @@ -1065,10 +1068,18 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) while (1) { ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args); if (ret < 0) { - error("cannot perform the search: %s", - strerror(errno)); - return ret; + if (errno == ENOENT) { + error("can't list qgroups: quotas not enabled"); + ret = -ENOTTY; + } else { + error("can't list qgroups: %s", + strerror(errno)); + ret = -errno; + } + + break; } + /* the ioctl returns the number of item it found in nr_items */ if (sk->nr_items == 0) break; @@ -1083,69 +1094,47 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) off); off += sizeof(*sh); - if (btrfs_search_header_type(sh) - == BTRFS_QGROUP_STATUS_KEY) { - struct btrfs_qgroup_status_item *si; - u64 flags; - + switch (btrfs_search_header_type(sh)) { + case BTRFS_QGROUP_STATUS_KEY: 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) { + break; + case 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, - 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) { + + ret = update_qgroup_info(qgroup_lookup, + qgroupid, info); + break; + case 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, - 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, - btrfs_search_header_offset(sh)); - if (!bq) - goto skip; - bq1 = qgroup_tree_search(qgroup_lookup, - btrfs_search_header_objectid(sh)); - if (!bq1) - goto skip; - 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: + (args.buf + off); + + ret = update_qgroup_limit(qgroup_lookup, + qgroupid, limit); + break; + case BTRFS_QGROUP_RELATION_KEY: + qgroupid = btrfs_search_header_offset(sh); + qgroupid1 = btrfs_search_header_objectid(sh); + + if (qgroupid < qgroupid1) + break; + + ret = update_qgroup_relation(qgroup_lookup, + qgroupid, qgroupid1); + break; + default: + return ret; + } + + if (ret) + return ret; + off += btrfs_search_header_len(sh); /* @@ -1167,7 +1156,6 @@ skip: break; } -done: return ret; } @@ -1204,27 +1192,9 @@ int btrfs_show_qgroups(int fd, print_all_qgroups(&sort_tree); __free_all_qgroups(&qgroup_lookup); - 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) { - error("cannot perform the search: %s", strerror(errno)); - return ret; - } - return args.treeid; -} - int btrfs_qgroup_parse_sort_string(const char *opt_arg, struct btrfs_qgroup_comparer_set **comps) { @@ -1240,7 +1210,8 @@ int btrfs_qgroup_parse_sort_string(const char *opt_arg, if (!opt_tmp) return -ENOMEM; - while ((p = strtok(opt_tmp, ",")) != NULL) { + p = strtok(opt_tmp, ","); + while (p) { flag = 0; ptr_argv = all_sort_items; @@ -1280,8 +1251,7 @@ int btrfs_qgroup_parse_sort_string(const char *opt_arg, } btrfs_qgroup_setup_comparer(comps, what_to_sort, order); } - free(opt_tmp); - opt_tmp = NULL; + p = strtok(NULL, ","); } out: