@@ -1150,11 +1150,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;
@@ -1165,30 +1165,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;
}
@@ -1202,14 +1184,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);
@@ -1217,7 +1199,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);
@@ -1225,7 +1207,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);
@@ -1271,6 +1253,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 */
+ },
+ };
+ 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)
{
@@ -1297,7 +1339,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,
@@ -1500,7 +1542,7 @@ int btrfs_export_qgroups_json(int fd,
struct qgroup_lookup sort_tree;
int ret = 0;
- 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,
@@ -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 *,
@@ -108,4 +114,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