On 2018年03月03日 02:47, je...@suse.com wrote: > From: Jeff Mahoney <je...@suse.com> > > The only mechanism we have in the progs for searching qgroups is to load > all of them and filter the results. This works for qgroup show but > to add quota information to 'btrfs subvoluem show' it's pretty wasteful. > > This patch splits out setting up the search and performing the search so > we can search for a single qgroupid more easily. > > Signed-off-by: Jeff Mahoney <je...@suse.com> > --- > qgroup.c | 98 > +++++++++++++++++++++++++++++++++++++++++++++------------------- > qgroup.h | 7 +++++ > 2 files changed, 77 insertions(+), 28 deletions(-) > > diff --git a/qgroup.c b/qgroup.c > index b1be3311..2d0a6947 100644 > --- a/qgroup.c > +++ b/qgroup.c > @@ -1146,11 +1146,11 @@ static inline void print_status_flag_warning(u64 > flags) > warning("qgroup data inconsistent, rescan recommended"); > } > > -static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) > +static int __qgroups_search(int fd, struct btrfs_ioctl_search_args *args, > + 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_key *sk = &args->key; > struct btrfs_ioctl_search_header *sh; > unsigned long off = 0; > unsigned int i; > @@ -1161,30 +1161,12 @@ static int __qgroups_search(int fd, struct > qgroup_lookup *qgroup_lookup) > u64 qgroupid; > u64 qgroupid1; > > - memset(&args, 0, sizeof(args)); > - > - sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID; > - sk->max_type = BTRFS_QGROUP_RELATION_KEY; > - sk->min_type = BTRFS_QGROUP_STATUS_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); > + ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, args); > if (ret < 0) { > - if (errno == ENOENT) { > - error("can't list qgroups: quotas not enabled"); > - ret = -ENOTTY; > - } else { > - error("can't list qgroups: %s", > - strerror(errno)); > - ret = -errno; > - } > - > + ret = -errno; > break; > } > > @@ -1198,14 +1180,14 @@ static int __qgroups_search(int fd, struct > qgroup_lookup *qgroup_lookup) > * read the root_ref item it contains > */ > for (i = 0; i < sk->nr_items; i++) { > - sh = (struct btrfs_ioctl_search_header *)(args.buf + > + sh = (struct btrfs_ioctl_search_header *)(args->buf + > off); > off += sizeof(*sh); > > switch (btrfs_search_header_type(sh)) { > case BTRFS_QGROUP_STATUS_KEY: > si = (struct btrfs_qgroup_status_item *) > - (args.buf + off); > + (args->buf + off); > flags = btrfs_stack_qgroup_status_flags(si); > > print_status_flag_warning(flags); > @@ -1213,7 +1195,7 @@ static int __qgroups_search(int fd, struct > qgroup_lookup *qgroup_lookup) > case BTRFS_QGROUP_INFO_KEY: > qgroupid = btrfs_search_header_offset(sh); > info = (struct btrfs_qgroup_info_item *) > - (args.buf + off); > + (args->buf + off); > > ret = update_qgroup_info(fd, qgroup_lookup, > qgroupid, info); > @@ -1221,7 +1203,7 @@ static int __qgroups_search(int fd, struct > qgroup_lookup *qgroup_lookup) > case BTRFS_QGROUP_LIMIT_KEY: > qgroupid = btrfs_search_header_offset(sh); > limit = (struct btrfs_qgroup_limit_item *) > - (args.buf + off); > + (args->buf + off); > > ret = update_qgroup_limit(fd, qgroup_lookup, > qgroupid, limit); > @@ -1267,6 +1249,66 @@ static int __qgroups_search(int fd, struct > qgroup_lookup *qgroup_lookup) > return ret; > } > > +static int qgroups_search_all(int fd, struct qgroup_lookup *qgroup_lookup) > +{ > + struct btrfs_ioctl_search_args args = { > + .key = { > + .tree_id = BTRFS_QUOTA_TREE_OBJECTID, > + .max_type = BTRFS_QGROUP_RELATION_KEY, > + .min_type = BTRFS_QGROUP_STATUS_KEY, > + .max_objectid = (u64)-1, > + .max_offset = (u64)-1, > + .max_transid = (u64)-1, > + .nr_items = 4096, > + }, > + }; > + int ret; > + > + ret = __qgroups_search(fd, &args, qgroup_lookup); > + if (ret == -ENOTTY) > + error("can't list qgroups: quotas not enabled"); > + else if (ret < 0) > + error("can't list qgroups: %s", strerror(-ret)); > + return ret; > +} > + > +int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats > *stats) > +{ > + struct btrfs_ioctl_search_args args = { > + .key = { > + .tree_id = BTRFS_QUOTA_TREE_OBJECTID, > + .min_type = BTRFS_QGROUP_INFO_KEY, > + .max_type = BTRFS_QGROUP_LIMIT_KEY, > + .max_objectid = 0, > + .max_offset = qgroupid, > + .max_transid = (u64)-1, > + .nr_items = 4096, /* should be 2, i think */
2 is not correct in fact. As QGROUP_INFO is smaller than QGROUP_LIMIT, to get a slice of all what we need, we need to include all other unrelated items. One example will be: item 1 key (0 QGROUP_INFO 0/5) itemoff 16211 itemsize 40 item 2 key (0 QGROUP_INFO 0/257) itemoff 16171 itemsize 40 item 3 key (0 QGROUP_INFO 1/1) itemoff 16131 itemsize 40 item 4 key (0 QGROUP_LIMIT 0/5) itemoff 16091 itemsize 40 item 5 key (0 QGROUP_LIMIT 0/257) itemoff 16051 itemsize 40 item 6 key (0 QGROUP_LIMIT 1/1) itemoff 16011 itemsize 40 To query qgroup info about 0/257, above setup will get the following slice: item 1 key (0 QGROUP_INFO 0/5) itemoff 16211 itemsize 40 item 2 key (0 QGROUP_INFO 0/257) itemoff 16171 itemsize 40 item 3 key (0 QGROUP_INFO 1/1) itemoff 16131 itemsize 40 item 4 key (0 QGROUP_LIMIT 0/5) itemoff 16091 itemsize 40 item 5 key (0 QGROUP_LIMIT 0/257) itemoff 16051 itemsize 40 So we still need that large @nr_items. Despite this comment it looks good. Thanks, Qu > + }, > + }; > + struct qgroup_lookup qgroup_lookup; > + struct btrfs_qgroup *qgroup; > + struct rb_node *n; > + int ret; > + > + ret = __qgroups_search(fd, &args, &qgroup_lookup); > + if (ret < 0) > + return ret; > + > + ret = -ENODATA; > + n = rb_first(&qgroup_lookup.root); > + if (n) { > + qgroup = rb_entry(n, struct btrfs_qgroup, rb_node); > + stats->qgroupid = qgroup->qgroupid; > + stats->info = qgroup->info; > + stats->limit = qgroup->limit; > + > + ret = 0; > + } > + > + __free_all_qgroups(&qgroup_lookup); > + return ret; > +} > + > static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool > verbose) > { > > @@ -1293,7 +1335,7 @@ int btrfs_show_qgroups(int fd, > struct qgroup_lookup sort_tree; > int ret; > > - ret = __qgroups_search(fd, &qgroup_lookup); > + ret = qgroups_search_all(fd, &qgroup_lookup); > if (ret) > return ret; > __filter_and_sort_qgroups(&qgroup_lookup, &sort_tree, > diff --git a/qgroup.h b/qgroup.h > index 5e71349c..688f92b2 100644 > --- a/qgroup.h > +++ b/qgroup.h > @@ -87,6 +87,12 @@ struct btrfs_qgroup_info { > u64 exclusive_compressed; > }; > > +struct btrfs_qgroup_stats { > + u64 qgroupid; > + struct btrfs_qgroup_info info; > + struct btrfs_qgroup_limit limit; > +}; > + > int btrfs_qgroup_parse_sort_string(const char *opt_arg, > struct btrfs_qgroup_comparer_set **comps); > int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *, > @@ -105,4 +111,5 @@ int qgroup_inherit_add_group(struct btrfs_qgroup_inherit > **inherit, char *arg); > int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg, > int type); > > +int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats > *stats); > #endif >
signature.asc
Description: OpenPGP digital signature