Skip to content

Commit 550d7a2

Browse files
Qu Wenruomasoncl
authored andcommitted
btrfs: qgroup: Add new qgroup calculation function
btrfs_qgroup_account_extents(). The new btrfs_qgroup_account_extents() function should be called in btrfs_commit_transaction() and it will update all the qgroup according to delayed_ref_root->dirty_extent_root. The new function can handle both normal operation during commit_transaction() or in rescan in a unified method with clearer logic. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
1 parent 21633fc commit 550d7a2

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

fs/btrfs/extent-tree.h

Whitespace-only changes.

fs/btrfs/qgroup.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,6 +2455,122 @@ static int btrfs_qgroup_account(struct btrfs_trans_handle *trans,
24552455
return ret;
24562456
}
24572457

2458+
static int
2459+
btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
2460+
struct btrfs_fs_info *fs_info,
2461+
u64 bytenr, u64 num_bytes,
2462+
struct ulist *old_roots, struct ulist *new_roots)
2463+
{
2464+
struct ulist *qgroups = NULL;
2465+
struct ulist *tmp = NULL;
2466+
u64 seq;
2467+
u64 nr_new_roots = 0;
2468+
u64 nr_old_roots = 0;
2469+
int ret = 0;
2470+
2471+
if (new_roots)
2472+
nr_new_roots = new_roots->nnodes;
2473+
if (old_roots)
2474+
nr_old_roots = old_roots->nnodes;
2475+
2476+
if (!fs_info->quota_enabled)
2477+
goto out_free;
2478+
BUG_ON(!fs_info->quota_root);
2479+
2480+
qgroups = ulist_alloc(GFP_NOFS);
2481+
if (!qgroups) {
2482+
ret = -ENOMEM;
2483+
goto out_free;
2484+
}
2485+
tmp = ulist_alloc(GFP_NOFS);
2486+
if (!tmp) {
2487+
ret = -ENOMEM;
2488+
goto out_free;
2489+
}
2490+
2491+
mutex_lock(&fs_info->qgroup_rescan_lock);
2492+
if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
2493+
if (fs_info->qgroup_rescan_progress.objectid <= bytenr) {
2494+
mutex_unlock(&fs_info->qgroup_rescan_lock);
2495+
ret = 0;
2496+
goto out_free;
2497+
}
2498+
}
2499+
mutex_unlock(&fs_info->qgroup_rescan_lock);
2500+
2501+
spin_lock(&fs_info->qgroup_lock);
2502+
seq = fs_info->qgroup_seq;
2503+
2504+
/* Update old refcnts using old_roots */
2505+
ret = qgroup_update_refcnt(fs_info, old_roots, tmp, qgroups, seq,
2506+
UPDATE_OLD);
2507+
if (ret < 0)
2508+
goto out;
2509+
2510+
/* Update new refcnts using new_roots */
2511+
ret = qgroup_update_refcnt(fs_info, new_roots, tmp, qgroups, seq,
2512+
UPDATE_NEW);
2513+
if (ret < 0)
2514+
goto out;
2515+
2516+
qgroup_update_counters(fs_info, qgroups, nr_old_roots, nr_new_roots,
2517+
num_bytes, seq);
2518+
2519+
/*
2520+
* Bump qgroup_seq to avoid seq overlap
2521+
*/
2522+
fs_info->qgroup_seq += max(nr_old_roots, nr_new_roots) + 1;
2523+
out:
2524+
spin_unlock(&fs_info->qgroup_lock);
2525+
out_free:
2526+
ulist_free(tmp);
2527+
ulist_free(qgroups);
2528+
ulist_free(old_roots);
2529+
ulist_free(new_roots);
2530+
return ret;
2531+
}
2532+
2533+
int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,
2534+
struct btrfs_fs_info *fs_info)
2535+
{
2536+
struct btrfs_qgroup_extent_record *record;
2537+
struct btrfs_delayed_ref_root *delayed_refs;
2538+
struct ulist *new_roots = NULL;
2539+
struct rb_node *node;
2540+
int ret = 0;
2541+
2542+
delayed_refs = &trans->transaction->delayed_refs;
2543+
while ((node = rb_first(&delayed_refs->dirty_extent_root))) {
2544+
record = rb_entry(node, struct btrfs_qgroup_extent_record,
2545+
node);
2546+
2547+
if (!ret) {
2548+
/*
2549+
* Use (u64)-1 as time_seq to do special search, which
2550+
* doesn't lock tree or delayed_refs and search current
2551+
* root. It's safe inside commit_transaction().
2552+
*/
2553+
ret = btrfs_find_all_roots(trans, fs_info,
2554+
record->bytenr, (u64)-1, &new_roots);
2555+
if (ret < 0)
2556+
goto cleanup;
2557+
ret = btrfs_qgroup_account_extent(trans, fs_info,
2558+
record->bytenr, record->num_bytes,
2559+
record->old_roots, new_roots);
2560+
record->old_roots = NULL;
2561+
new_roots = NULL;
2562+
}
2563+
cleanup:
2564+
ulist_free(record->old_roots);
2565+
ulist_free(new_roots);
2566+
new_roots = NULL;
2567+
rb_erase(node, &delayed_refs->dirty_extent_root);
2568+
kfree(record);
2569+
2570+
}
2571+
return ret;
2572+
}
2573+
24582574
/*
24592575
* Needs to be called everytime we run delayed refs, even if there is an error
24602576
* in order to cleanup outstanding operations.

fs/btrfs/qgroup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
103103
struct btrfs_qgroup_extent_record
104104
*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
105105
struct btrfs_qgroup_extent_record *record);
106+
int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,
107+
struct btrfs_fs_info *fs_info);
106108
int btrfs_delayed_qgroup_accounting(struct btrfs_trans_handle *trans,
107109
struct btrfs_fs_info *fs_info);
108110
void btrfs_remove_qgroup_operation(struct btrfs_trans_handle *trans,

0 commit comments

Comments
 (0)