btrfs: qgroup: Add function qgroup_update_counters().
Add function qgroup_update_counters(), which will update related qgroups' rfer/excl according to old/new_roots. This is one of the two core functions for the new qgroup implement. This is based on btrfs_adjust_coutners() but with clearer logic and comment. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
d810ef2be5
commit
823ae5b8e3
1 changed files with 120 additions and 0 deletions
|
@ -1864,6 +1864,126 @@ static int qgroup_update_refcnt(struct btrfs_fs_info *fs_info,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update qgroup rfer/excl counters.
|
||||||
|
* Rfer update is easy, codes can explain themselves.
|
||||||
|
* Excl update is tricky, the update is split into 2 part.
|
||||||
|
* Part 1: Possible exclusive <-> sharing detect:
|
||||||
|
* | A | !A |
|
||||||
|
* -------------------------------------
|
||||||
|
* B | * | - |
|
||||||
|
* -------------------------------------
|
||||||
|
* !B | + | ** |
|
||||||
|
* -------------------------------------
|
||||||
|
*
|
||||||
|
* Conditions:
|
||||||
|
* A: cur_old_roots < nr_old_roots (not exclusive before)
|
||||||
|
* !A: cur_old_roots == nr_old_roots (possible exclusive before)
|
||||||
|
* B: cur_new_roots < nr_new_roots (not exclusive now)
|
||||||
|
* !B: cur_new_roots == nr_new_roots (possible exclsuive now)
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* +: Possible sharing -> exclusive -: Possible exclusive -> sharing
|
||||||
|
* *: Definitely not changed. **: Possible unchanged.
|
||||||
|
*
|
||||||
|
* For !A and !B condition, the exception is cur_old/new_roots == 0 case.
|
||||||
|
*
|
||||||
|
* To make the logic clear, we first use condition A and B to split
|
||||||
|
* combination into 4 results.
|
||||||
|
*
|
||||||
|
* Then, for result "+" and "-", check old/new_roots == 0 case, as in them
|
||||||
|
* only on variant maybe 0.
|
||||||
|
*
|
||||||
|
* Lastly, check result **, since there are 2 variants maybe 0, split them
|
||||||
|
* again(2x2).
|
||||||
|
* But this time we don't need to consider other things, the codes and logic
|
||||||
|
* is easy to understand now.
|
||||||
|
*/
|
||||||
|
static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
|
||||||
|
struct ulist *qgroups,
|
||||||
|
u64 nr_old_roots,
|
||||||
|
u64 nr_new_roots,
|
||||||
|
u64 num_bytes, u64 seq)
|
||||||
|
{
|
||||||
|
struct ulist_node *unode;
|
||||||
|
struct ulist_iterator uiter;
|
||||||
|
struct btrfs_qgroup *qg;
|
||||||
|
u64 cur_new_count, cur_old_count;
|
||||||
|
|
||||||
|
ULIST_ITER_INIT(&uiter);
|
||||||
|
while ((unode = ulist_next(qgroups, &uiter))) {
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
qg = u64_to_ptr(unode->aux);
|
||||||
|
cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
|
||||||
|
cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
|
||||||
|
|
||||||
|
/* Rfer update part */
|
||||||
|
if (cur_old_count == 0 && cur_new_count > 0) {
|
||||||
|
qg->rfer += num_bytes;
|
||||||
|
qg->rfer_cmpr += num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
if (cur_old_count > 0 && cur_new_count == 0) {
|
||||||
|
qg->rfer -= num_bytes;
|
||||||
|
qg->rfer_cmpr -= num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Excl update part */
|
||||||
|
/* Exclusive/none -> shared case */
|
||||||
|
if (cur_old_count == nr_old_roots &&
|
||||||
|
cur_new_count < nr_new_roots) {
|
||||||
|
/* Exclusive -> shared */
|
||||||
|
if (cur_old_count != 0) {
|
||||||
|
qg->excl -= num_bytes;
|
||||||
|
qg->excl_cmpr -= num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shared -> exclusive/none case */
|
||||||
|
if (cur_old_count < nr_old_roots &&
|
||||||
|
cur_new_count == nr_new_roots) {
|
||||||
|
/* Shared->exclusive */
|
||||||
|
if (cur_new_count != 0) {
|
||||||
|
qg->excl += num_bytes;
|
||||||
|
qg->excl_cmpr += num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exclusive/none -> exclusive/none case */
|
||||||
|
if (cur_old_count == nr_old_roots &&
|
||||||
|
cur_new_count == nr_new_roots) {
|
||||||
|
if (cur_old_count == 0) {
|
||||||
|
/* None -> exclusive/none */
|
||||||
|
|
||||||
|
if (cur_new_count != 0) {
|
||||||
|
/* None -> exclusive */
|
||||||
|
qg->excl += num_bytes;
|
||||||
|
qg->excl_cmpr += num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
/* None -> none, nothing changed */
|
||||||
|
} else {
|
||||||
|
/* Exclusive -> exclusive/none */
|
||||||
|
|
||||||
|
if (cur_new_count == 0) {
|
||||||
|
/* Exclusive -> none */
|
||||||
|
qg->excl -= num_bytes;
|
||||||
|
qg->excl_cmpr -= num_bytes;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
/* Exclusive -> exclusive, nothing changed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirty)
|
||||||
|
qgroup_dirty(fs_info, qg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This adjusts the counters for all referenced qgroups if need be.
|
* This adjusts the counters for all referenced qgroups if need be.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue