This patch make the qgroup account the information of data or metadata by different infos.
Signed-off-by: Dongsheng Yang <yangds.f...@cn.fujitsu.com> --- fs/btrfs/extent-tree.c | 48 +++++---- fs/btrfs/qgroup.c | 239 ++++++++++++++++++++++++++---------------- fs/btrfs/qgroup.h | 25 ++++- fs/btrfs/tests/qgroup-tests.c | 15 ++- fs/btrfs/transaction.c | 11 +- 5 files changed, 217 insertions(+), 121 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 3f49316..cb27da6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -83,7 +83,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, u64 root_objectid, u64 owner_objectid, u64 owner_offset, int refs_to_drop, struct btrfs_delayed_extent_op *extra_op, - int no_quota); + int no_quota, unsigned int quota_type); static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, struct extent_buffer *leaf, struct btrfs_extent_item *ei); @@ -1971,7 +1971,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, u64 parent, u64 root_objectid, u64 owner, u64 offset, int refs_to_add, int no_quota, - struct btrfs_delayed_extent_op *extent_op) + struct btrfs_delayed_extent_op *extent_op, + unsigned int quota_type) { struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; @@ -2013,7 +2014,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, btrfs_release_path(path); ret = btrfs_qgroup_record_ref(trans, fs_info, root_objectid, - bytenr, num_bytes, type, 0); + bytenr, num_bytes, type, + quota_type, 0); goto out; } @@ -2037,7 +2039,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, if (!no_quota) { ret = btrfs_qgroup_record_ref(trans, fs_info, root_objectid, - bytenr, num_bytes, type, 0); + bytenr, num_bytes, type, + quota_type, 0); if (ret) goto out; } @@ -2091,13 +2094,15 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans, node->num_bytes, parent, ref_root, ref->objectid, ref->offset, node->ref_mod, - node->no_quota, extent_op); + node->no_quota, extent_op, + BTRFS_QGROUP_REF_TYPE_DATA); } else if (node->action == BTRFS_DROP_DELAYED_REF) { ret = __btrfs_free_extent(trans, root, node->bytenr, node->num_bytes, parent, ref_root, ref->objectid, ref->offset, node->ref_mod, - extent_op, node->no_quota); + extent_op, node->no_quota, + BTRFS_QGROUP_REF_TYPE_DATA); } else { BUG(); } @@ -2258,12 +2263,12 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, ret = __btrfs_inc_extent_ref(trans, root, node->bytenr, node->num_bytes, parent, ref_root, ref->level, 0, 1, node->no_quota, - extent_op); + extent_op, BTRFS_QGROUP_REF_TYPE_METADATA); } else if (node->action == BTRFS_DROP_DELAYED_REF) { ret = __btrfs_free_extent(trans, root, node->bytenr, node->num_bytes, parent, ref_root, ref->level, 0, 1, extent_op, - node->no_quota); + node->no_quota, BTRFS_QGROUP_REF_TYPE_METADATA); } else { BUG(); } @@ -3694,7 +3699,7 @@ commit_trans: data_sinfo->flags, bytes, 1); return -ENOSPC; } - ret = btrfs_qgroup_reserve(root, write_bytes); + ret = btrfs_qgroup_reserve(root, write_bytes, BTRFS_QGROUP_REF_TYPE_DATA); if (ret) goto out; data_sinfo->bytes_may_use += bytes; @@ -4929,7 +4934,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, if (root->fs_info->quota_enabled) { /* One for parent inode, two for dir entries */ num_bytes = 3 * root->nodesize; - ret = btrfs_qgroup_reserve(root, num_bytes); + ret = btrfs_qgroup_reserve(root, num_bytes, BTRFS_QGROUP_REF_TYPE_METADATA); if (ret) return ret; } else { @@ -4949,7 +4954,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, if (ret) { if (*qgroup_reserved) - btrfs_qgroup_free(root, *qgroup_reserved); + btrfs_qgroup_free(root, *qgroup_reserved, BTRFS_QGROUP_REF_TYPE_METADATA); } return ret; @@ -5119,7 +5124,8 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) spin_unlock(&BTRFS_I(inode)->lock); if (root->fs_info->quota_enabled) { - ret = btrfs_qgroup_reserve(root, nr_extents * root->nodesize); + ret = btrfs_qgroup_reserve(root, nr_extents * root->nodesize, + BTRFS_QGROUP_REF_TYPE_METADATA); if (ret) goto out_fail; } @@ -5127,7 +5133,8 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); if (unlikely(ret)) { if (root->fs_info->quota_enabled) - btrfs_qgroup_free(root, nr_extents * root->nodesize); + btrfs_qgroup_free(root, nr_extents * root->nodesize, + BTRFS_QGROUP_REF_TYPE_METADATA); goto out_fail; } @@ -5785,7 +5792,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, u64 root_objectid, u64 owner_objectid, u64 owner_offset, int refs_to_drop, struct btrfs_delayed_extent_op *extent_op, - int no_quota) + int no_quota, unsigned int quota_type) { struct btrfs_key key; struct btrfs_path *path; @@ -6055,7 +6062,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, ret = btrfs_qgroup_record_ref(trans, info, root_objectid, bytenr, num_bytes, type, - mod_seq); + quota_type, mod_seq); } out: btrfs_free_path(path); @@ -6996,7 +7003,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, /* Always set parent to 0 here since its exclusive anyway. */ ret = btrfs_qgroup_record_ref(trans, fs_info, root_objectid, ins->objectid, ins->offset, - BTRFS_QGROUP_OPER_ADD_EXCL, 0); + BTRFS_QGROUP_OPER_ADD_EXCL, + BTRFS_QGROUP_REF_TYPE_DATA, 0); if (ret) return ret; @@ -7084,7 +7092,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, if (!no_quota) { ret = btrfs_qgroup_record_ref(trans, fs_info, root_objectid, ins->objectid, num_bytes, - BTRFS_QGROUP_OPER_ADD_EXCL, 0); + BTRFS_QGROUP_OPER_ADD_EXCL, + BTRFS_QGROUP_REF_TYPE_METADATA, 0); if (ret) return ret; } @@ -7462,7 +7471,8 @@ static int account_leaf_items(struct btrfs_trans_handle *trans, ret = btrfs_qgroup_record_ref(trans, root->fs_info, root->objectid, bytenr, num_bytes, - BTRFS_QGROUP_OPER_SUB_SUBTREE, 0); + BTRFS_QGROUP_OPER_SUB_SUBTREE, + BTRFS_QGROUP_REF_TYPE_METADATA, 0); if (ret) return ret; } @@ -7612,7 +7622,7 @@ walk_down: child_bytenr, root->nodesize, BTRFS_QGROUP_OPER_SUB_SUBTREE, - 0); + BTRFS_QGROUP_REF_TYPE_METADATA, 0); if (ret) goto out; diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 34eb4f5..9dd2627 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1451,7 +1451,8 @@ static int insert_qgroup_oper(struct btrfs_fs_info *fs_info, int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 ref_root, u64 bytenr, u64 num_bytes, - enum btrfs_qgroup_operation_type type, int mod_seq) + enum btrfs_qgroup_operation_type type, + unsigned int quota_type, int mod_seq) { struct btrfs_qgroup_operation *oper; int ret; @@ -1467,6 +1468,7 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, oper->bytenr = bytenr; oper->num_bytes = num_bytes; oper->type = type; + oper->quota_type = quota_type; oper->seq = atomic_inc_return(&fs_info->qgroup_op_seq); INIT_LIST_HEAD(&oper->elem.list); oper->elem.seq = 0; @@ -1542,11 +1544,14 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info, ASSERT(0); } - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - info = &qgroup->data_info; + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qgroup->data_info; + } else { + if (oper->quota_type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qgroup->data_info; + else + info = &qgroup->metadata_info; + } info->rfer += sign * oper->num_bytes; info->rfer_cmpr += sign * oper->num_bytes; @@ -1571,11 +1576,14 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info, ULIST_ITER_INIT(&uiter); while ((unode = ulist_next(tmp, &uiter))) { qgroup = u64_to_ptr(unode->aux); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - info = &qgroup->data_info; + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qgroup->data_info; + } else { + if (oper->quota_type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qgroup->data_info; + else + info = &qgroup->metadata_info; + } info->rfer += sign * oper->num_bytes; info->rfer_cmpr += sign * oper->num_bytes; WARN_ON(sign < 0 && info->excl < oper->num_bytes); @@ -1842,13 +1850,14 @@ static int qgroup_calc_new_refcnt(struct btrfs_fs_info *fs_info, */ static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, u64 root_to_skip, u64 num_bytes, - struct ulist *qgroups, u64 seq, - int old_roots, int new_roots, int rescan) + u8 quota_type, struct ulist *qgroups, + u64 seq, int old_roots, int new_roots, + int rescan) { struct ulist_node *unode; struct ulist_iterator uiter; struct btrfs_qgroup *qg; - struct btrfs_qgroup_info *data_info; + struct btrfs_qgroup_info *info; u64 cur_new_count, cur_old_count; ULIST_ITER_INIT(&uiter); @@ -1857,14 +1866,21 @@ static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, qg = u64_to_ptr(unode->aux); - data_info = &qg->data_info; + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qg->data_info; + } else { + if (quota_type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qg->data_info; + else + info = &qg->metadata_info; + } /* * Wasn't referenced before but is now, add to the reference * counters. */ if (qg->old_refcnt <= seq && qg->new_refcnt > seq) { - data_info->rfer += num_bytes; - data_info->rfer_cmpr += num_bytes; + info->rfer += num_bytes; + info->rfer_cmpr += num_bytes; dirty = true; } @@ -1873,8 +1889,8 @@ static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, * reference counters. */ if (qg->old_refcnt > seq && qg->new_refcnt <= seq) { - data_info->rfer -= num_bytes; - data_info->rfer_cmpr -= num_bytes; + info->rfer -= num_bytes; + info->rfer_cmpr -= num_bytes; dirty = true; } @@ -1895,13 +1911,8 @@ static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, if (old_roots && cur_old_count == old_roots && (cur_new_count != new_roots || new_roots == 0)) { WARN_ON(cur_new_count != new_roots && new_roots == 0); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qg->data_info; - data_info->excl -= num_bytes; - data_info->excl_cmpr -= num_bytes; + info->excl -= num_bytes; + info->excl_cmpr -= num_bytes; dirty = true; } @@ -1911,13 +1922,8 @@ static int qgroup_adjust_counters(struct btrfs_fs_info *fs_info, */ if ((!old_roots || (old_roots && cur_old_count != old_roots)) && cur_new_count == new_roots) { - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qg->data_info; - data_info->excl += num_bytes; - data_info->excl_cmpr += num_bytes; + info->excl += num_bytes; + info->excl_cmpr += num_bytes; dirty = true; } @@ -2102,7 +2108,8 @@ static int qgroup_shared_accounting(struct btrfs_trans_handle *trans, * solution for this. */ qgroup_adjust_counters(fs_info, oper->ref_root, oper->num_bytes, - qgroups, seq, old_roots, new_roots, 0); + oper->quota_type, qgroups, seq, old_roots, + new_roots, 0); out: spin_unlock(&fs_info->qgroup_lock); ulist_free(qgroups); @@ -2171,11 +2178,16 @@ static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans, qg = find_qgroup_rb(fs_info, root_obj); if (!qg) goto out_unlock; - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - info = &qg->data_info; + + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qg->data_info; + } else { + if (oper->quota_type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qg->data_info; + else + info = &qg->metadata_info; + } + info->excl += oper->num_bytes; info->excl_cmpr += oper->num_bytes; qgroup_dirty(fs_info, qg); @@ -2197,11 +2209,15 @@ static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans, ULIST_ITER_INIT(&uiter); while ((unode = ulist_next(parents, &uiter))) { qg = u64_to_ptr(unode->aux); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - info = &qg->data_info; + + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qg->data_info; + } else { + if (oper->quota_type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qg->data_info; + else + info = &qg->metadata_info; + } info->excl += oper->num_bytes; info->excl_cmpr += oper->num_bytes; qgroup_dirty(fs_info, qg); @@ -2579,12 +2595,47 @@ out: return ret; } -int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) +static int exceed_limits(struct btrfs_qgroup_info *info, + struct btrfs_qgroup_limits *limits, + struct btrfs_qgroup_info *another_info, + u64 num_bytes) +{ + if (another_info) { + /* + * For the mixed limits. + */ + if ((limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && + info->reserved + (s64)info->excl + + another_info->reserved + (s64)another_info->excl + + num_bytes > limits->max_excl) + return 1; + + if ((limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && + info->reserved + (s64)info->rfer + + another_info->reserved + (s64)another_info->rfer + + num_bytes > limits->max_rfer) + return 1; + + } else { + if ((limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && + info->reserved + (s64)info->excl + num_bytes > + limits->max_excl) + return 1; + + if ((limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && + info->reserved + (s64)info->rfer + num_bytes > + limits->max_rfer) + return 1; + } + + return 0; +} + +int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes, u8 type) { struct btrfs_root *quota_root; struct btrfs_qgroup *qgroup; - struct btrfs_qgroup_info *data_info; - struct btrfs_qgroup_limits *mixed_limits; + struct btrfs_qgroup_info *info; struct btrfs_fs_info *fs_info = root->fs_info; u64 ref_root = root->root_key.objectid; int ret = 0; @@ -2617,33 +2668,32 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) goto out; ULIST_ITER_INIT(&uiter); while ((unode = ulist_next(fs_info->qgroup_ulist, &uiter))) { - struct btrfs_qgroup *qg; + struct btrfs_qgroup *qgroup; struct btrfs_qgroup_list *glist; - qg = u64_to_ptr(unode->aux); - - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qgroup->data_info; - mixed_limits = &qgroup->mixed_limits; + qgroup = u64_to_ptr(unode->aux); - if ((mixed_limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && - data_info->reserved + (s64)data_info->rfer + num_bytes > - mixed_limits->max_rfer) { - ret = -EDQUOT; - goto out; + if (type == BTRFS_QGROUP_REF_TYPE_DATA) { + info = &qgroup->data_info; + if (exceed_limits(info, &qgroup->data_limits, NULL, num_bytes)) { + ret = -EDQUOT; + goto out; + } + } else { + info = &qgroup->metadata_info; + if (exceed_limits(info, &qgroup->metadata_limits, NULL, num_bytes)) { + ret = -EDQUOT; + goto out; + } } - if ((mixed_limits->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && - data_info->reserved + (s64)data_info->excl + num_bytes > - mixed_limits->max_excl) { + if (exceed_limits(&qgroup->data_info, &qgroup->mixed_limits, + &qgroup->metadata_info, num_bytes)) { ret = -EDQUOT; goto out; } - list_for_each_entry(glist, &qg->groups, next_group) { + list_for_each_entry(glist, &qgroup->groups, next_group) { ret = ulist_add(fs_info->qgroup_ulist, glist->group->qgroupid, (uintptr_t)glist->group, GFP_ATOMIC); @@ -2661,13 +2711,16 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) qg = u64_to_ptr(unode->aux); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qg->data_info; + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qg->data_info; + } else { + if (type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qg->data_info; + else + info = &qg->metadata_info; + } - data_info->reserved += num_bytes; + info->reserved += num_bytes; } out: @@ -2675,11 +2728,11 @@ out: return ret; } -void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) +void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes, u8 type) { struct btrfs_root *quota_root; struct btrfs_qgroup *qgroup; - struct btrfs_qgroup_info *data_info; + struct btrfs_qgroup_info *info; struct btrfs_fs_info *fs_info = root->fs_info; struct ulist_node *unode; struct ulist_iterator uiter; @@ -2714,13 +2767,16 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) qg = u64_to_ptr(unode->aux); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qg->data_info; + if (!btrfs_fs_incompat(fs_info, QGROUP_TYPE)) { + info = &qg->data_info; + } else { + if (type == BTRFS_QGROUP_REF_TYPE_DATA) + info = &qg->data_info; + else + info = &qg->metadata_info; + } - data_info->reserved -= num_bytes; + info->reserved -= num_bytes; list_for_each_entry(glist, &qg->groups, next_group) { ret = ulist_add(fs_info->qgroup_ulist, @@ -2830,7 +2886,7 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path, goto out; } - ret = qgroup_adjust_counters(fs_info, 0, num_bytes, qgroups, + ret = qgroup_adjust_counters(fs_info, 0, num_bytes, 0, qgroups, seq, 0, new_roots, 1); if (ret < 0) { spin_unlock(&fs_info->qgroup_lock); @@ -2979,22 +3035,25 @@ qgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info) { struct rb_node *n; struct btrfs_qgroup *qgroup; - struct btrfs_qgroup_info *data_info; + struct btrfs_qgroup_info *info; spin_lock(&fs_info->qgroup_lock); /* clear all current qgroup tracking information */ for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) { qgroup = rb_entry(n, struct btrfs_qgroup, node); - /* - * FIXME: use the data_info to store all information currently. - * will seperate the information into data and metadata later. - **/ - data_info = &qgroup->data_info; - data_info->rfer = 0; - data_info->rfer_cmpr = 0; - data_info->excl = 0; - data_info->excl_cmpr = 0; + info = &qgroup->data_info; + +again: + info->rfer = 0; + info->rfer_cmpr = 0; + info->excl = 0; + info->excl_cmpr = 0; + + if (info != &qgroup->metadata_info) { + info = &qgroup->metadata_info; + goto again; + } } spin_unlock(&fs_info->qgroup_lock); } diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 52d8b19..11b73f3 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h @@ -20,6 +20,22 @@ #define __BTRFS_QGROUP__ /* + * Type for quota reference. Caller of qgroup_record_ref() + * should choose one type of the reference passed to qgroup. + * Then qgroup will account the reference in the chosen info. + */ +#define BTRFS_QGROUP_REF_TYPE_DATA (1 << 0) +#define BTRFS_QGROUP_REF_TYPE_METADATA (1 << 1) + +/* + * To keep the compatibility, define a default type to manage + * the all reference in the older kernel. Choose the data_info + * to account all reference in older kernel which did not record + * and account reference for data and metadata separately. + */ +#define BTRFS_QGROUP_REF_TYPE_DEFAULT BTRFS_QGROUP_REF_TYPE_DATA + +/* * A description of the operations, all of these operations only happen when we * are adding the 1st reference for that subvolume in the case of adding space * or on the last reference delete in the case of subtraction. The only @@ -53,6 +69,10 @@ struct btrfs_qgroup_operation { u64 num_bytes; u64 seq; enum btrfs_qgroup_operation_type type; + /* + * DATA or METADATA; + **/ + unsigned int quota_type; struct seq_list elem; struct rb_node n; struct list_head list; @@ -86,6 +106,7 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 ref_root, u64 bytenr, u64 num_bytes, enum btrfs_qgroup_operation_type type, + unsigned int quota_type, int mod_seq); int btrfs_delayed_qgroup_accounting(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); @@ -97,8 +118,8 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans, int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid, struct btrfs_qgroup_inherit *inherit); -int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes); -void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes); +int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes, u8 type); +void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes, u8 type); void assert_qgroups_uptodate(struct btrfs_trans_handle *trans); diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c index c32a7ba..2c978ce 100644 --- a/fs/btrfs/tests/qgroup-tests.c +++ b/fs/btrfs/tests/qgroup-tests.c @@ -239,7 +239,8 @@ static int test_no_shared_qgroup(struct btrfs_root *root) } ret = btrfs_qgroup_record_ref(&trans, fs_info, 5, 4096, 4096, - BTRFS_QGROUP_OPER_ADD_EXCL, 0); + BTRFS_QGROUP_OPER_ADD_EXCL, + BTRFS_QGROUP_REF_TYPE_DEFAULT, 0); if (ret) { test_msg("Couldn't add space to a qgroup %d\n", ret); return ret; @@ -265,7 +266,8 @@ static int test_no_shared_qgroup(struct btrfs_root *root) return -EINVAL; ret = btrfs_qgroup_record_ref(&trans, fs_info, 5, 4096, 4096, - BTRFS_QGROUP_OPER_SUB_EXCL, 0); + BTRFS_QGROUP_OPER_SUB_EXCL, + BTRFS_QGROUP_REF_TYPE_DEFAULT, 0); if (ret) { test_msg("Couldn't remove space from the qgroup %d\n", ret); return -EINVAL; @@ -312,7 +314,8 @@ static int test_multiple_refs(struct btrfs_root *root) return ret; ret = btrfs_qgroup_record_ref(&trans, fs_info, 5, 4096, 4096, - BTRFS_QGROUP_OPER_ADD_EXCL, 0); + BTRFS_QGROUP_OPER_ADD_EXCL, + BTRFS_QGROUP_REF_TYPE_DEFAULT, 0); if (ret) { test_msg("Couldn't add space to a qgroup %d\n", ret); return ret; @@ -334,7 +337,8 @@ static int test_multiple_refs(struct btrfs_root *root) return ret; ret = btrfs_qgroup_record_ref(&trans, fs_info, 256, 4096, 4096, - BTRFS_QGROUP_OPER_ADD_SHARED, 0); + BTRFS_QGROUP_OPER_ADD_SHARED, + BTRFS_QGROUP_REF_TYPE_DEFAULT, 0); if (ret) { test_msg("Qgroup record ref failed %d\n", ret); return ret; @@ -361,7 +365,8 @@ static int test_multiple_refs(struct btrfs_root *root) return ret; ret = btrfs_qgroup_record_ref(&trans, fs_info, 256, 4096, 4096, - BTRFS_QGROUP_OPER_SUB_SHARED, 0); + BTRFS_QGROUP_OPER_SUB_SHARED, + BTRFS_QGROUP_REF_TYPE_DEFAULT, 0); if (ret) { test_msg("Qgroup record ref failed %d\n", ret); return ret; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 7e80f32..8d4bffb 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -440,7 +440,8 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, if (root->fs_info->quota_enabled && is_fstree(root->root_key.objectid)) { qgroup_reserved = num_items * root->nodesize; - ret = btrfs_qgroup_reserve(root, qgroup_reserved); + ret = btrfs_qgroup_reserve(root, qgroup_reserved, + BTRFS_QGROUP_REF_TYPE_METADATA); if (ret) return ERR_PTR(ret); } @@ -555,7 +556,7 @@ alloc_fail: num_bytes); reserve_fail: if (qgroup_reserved) - btrfs_qgroup_free(root, qgroup_reserved); + btrfs_qgroup_free(root, qgroup_reserved, BTRFS_QGROUP_REF_TYPE_METADATA); return ERR_PTR(ret); } @@ -777,7 +778,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, * the same root has to be passed here between start_transaction * and end_transaction. Subvolume quota depends on this. */ - btrfs_qgroup_free(trans->root, trans->qgroup_reserved); + btrfs_qgroup_free(trans->root, trans->qgroup_reserved, BTRFS_QGROUP_REF_TYPE_METADATA); trans->qgroup_reserved = 0; } @@ -1783,7 +1784,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, btrfs_trans_release_metadata(trans, root); trans->block_rsv = NULL; if (trans->qgroup_reserved) { - btrfs_qgroup_free(root, trans->qgroup_reserved); + btrfs_qgroup_free(root, trans->qgroup_reserved, BTRFS_QGROUP_REF_TYPE_METADATA); trans->qgroup_reserved = 0; } @@ -2079,7 +2080,7 @@ cleanup_transaction: btrfs_trans_release_metadata(trans, root); trans->block_rsv = NULL; if (trans->qgroup_reserved) { - btrfs_qgroup_free(root, trans->qgroup_reserved); + btrfs_qgroup_free(root, trans->qgroup_reserved, BTRFS_QGROUP_REF_TYPE_METADATA); trans->qgroup_reserved = 0; } btrfs_warn(root->fs_info, "Skipping commit of aborted transaction."); -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html