Skip to content

Commit 3368d00

Browse files
Qu Wenruomasoncl
Qu Wenruo
authored andcommitted
btrfs: qgroup: Record possible quota-related extent for qgroup.
Add hook in add_delayed_ref_head() to record quota-related extent record into delayed_ref_root->dirty_extent_record rb-tree for later qgroup accounting. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent 823ae5b commit 3368d00

File tree

5 files changed

+95
-7
lines changed

5 files changed

+95
-7
lines changed

fs/btrfs/delayed-ref.c

+43-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ctree.h"
2323
#include "delayed-ref.h"
2424
#include "transaction.h"
25+
#include "qgroup.h"
2526

2627
struct kmem_cache *btrfs_delayed_ref_head_cachep;
2728
struct kmem_cache *btrfs_delayed_tree_ref_cachep;
@@ -420,12 +421,14 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs,
420421
static noinline struct btrfs_delayed_ref_head *
421422
add_delayed_ref_head(struct btrfs_fs_info *fs_info,
422423
struct btrfs_trans_handle *trans,
423-
struct btrfs_delayed_ref_node *ref, u64 bytenr,
424-
u64 num_bytes, int action, int is_data)
424+
struct btrfs_delayed_ref_node *ref,
425+
struct btrfs_qgroup_extent_record *qrecord,
426+
u64 bytenr, u64 num_bytes, int action, int is_data)
425427
{
426428
struct btrfs_delayed_ref_head *existing;
427429
struct btrfs_delayed_ref_head *head_ref = NULL;
428430
struct btrfs_delayed_ref_root *delayed_refs;
431+
struct btrfs_qgroup_extent_record *qexisting;
429432
int count_mod = 1;
430433
int must_insert_reserved = 0;
431434

@@ -474,6 +477,18 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
474477
head_ref->processing = 0;
475478
head_ref->total_ref_mod = count_mod;
476479

480+
/* Record qgroup extent info if provided */
481+
if (qrecord) {
482+
qrecord->bytenr = bytenr;
483+
qrecord->num_bytes = num_bytes;
484+
qrecord->old_roots = NULL;
485+
486+
qexisting = btrfs_qgroup_insert_dirty_extent(delayed_refs,
487+
qrecord);
488+
if (qexisting)
489+
kfree(qrecord);
490+
}
491+
477492
spin_lock_init(&head_ref->lock);
478493
mutex_init(&head_ref->mutex);
479494

@@ -624,6 +639,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
624639
struct btrfs_delayed_tree_ref *ref;
625640
struct btrfs_delayed_ref_head *head_ref;
626641
struct btrfs_delayed_ref_root *delayed_refs;
642+
struct btrfs_qgroup_extent_record *record = NULL;
627643

628644
if (!is_fstree(ref_root) || !fs_info->quota_enabled)
629645
no_quota = 0;
@@ -639,6 +655,15 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
639655
return -ENOMEM;
640656
}
641657

658+
if (fs_info->quota_enabled && is_fstree(ref_root)) {
659+
record = kmalloc(sizeof(*record), GFP_NOFS);
660+
if (!record) {
661+
kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref);
662+
kmem_cache_free(btrfs_delayed_ref_head_cachep, ref);
663+
return -ENOMEM;
664+
}
665+
}
666+
642667
head_ref->extent_op = extent_op;
643668

644669
delayed_refs = &trans->transaction->delayed_refs;
@@ -648,7 +673,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
648673
* insert both the head node and the new ref without dropping
649674
* the spin lock
650675
*/
651-
head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node,
676+
head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node, record,
652677
bytenr, num_bytes, action, 0);
653678

654679
add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
@@ -673,6 +698,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
673698
struct btrfs_delayed_data_ref *ref;
674699
struct btrfs_delayed_ref_head *head_ref;
675700
struct btrfs_delayed_ref_root *delayed_refs;
701+
struct btrfs_qgroup_extent_record *record = NULL;
676702

677703
if (!is_fstree(ref_root) || !fs_info->quota_enabled)
678704
no_quota = 0;
@@ -688,6 +714,16 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
688714
return -ENOMEM;
689715
}
690716

717+
if (fs_info->quota_enabled && is_fstree(ref_root)) {
718+
record = kmalloc(sizeof(*record), GFP_NOFS);
719+
if (!record) {
720+
kmem_cache_free(btrfs_delayed_data_ref_cachep, ref);
721+
kmem_cache_free(btrfs_delayed_ref_head_cachep,
722+
head_ref);
723+
return -ENOMEM;
724+
}
725+
}
726+
691727
head_ref->extent_op = extent_op;
692728

693729
delayed_refs = &trans->transaction->delayed_refs;
@@ -697,7 +733,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
697733
* insert both the head node and the new ref without dropping
698734
* the spin lock
699735
*/
700-
head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node,
736+
head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node, record,
701737
bytenr, num_bytes, action, 1);
702738

703739
add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
@@ -725,9 +761,9 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
725761
delayed_refs = &trans->transaction->delayed_refs;
726762
spin_lock(&delayed_refs->lock);
727763

728-
add_delayed_ref_head(fs_info, trans, &head_ref->node, bytenr,
729-
num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
730-
extent_op->is_data);
764+
add_delayed_ref_head(fs_info, trans, &head_ref->node, NULL, bytenr,
765+
num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
766+
extent_op->is_data);
731767

732768
spin_unlock(&delayed_refs->lock);
733769
return 0;

fs/btrfs/delayed-ref.h

+3
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ struct btrfs_delayed_ref_root {
148148
/* head ref rbtree */
149149
struct rb_root href_root;
150150

151+
/* dirty extent records */
152+
struct rb_root dirty_extent_root;
153+
151154
/* this spin lock protects the rbtree and the entries inside */
152155
spinlock_t lock;
153156

fs/btrfs/qgroup.c

+31
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,37 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
15531553
return 0;
15541554
}
15551555

1556+
struct btrfs_qgroup_extent_record
1557+
*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
1558+
struct btrfs_qgroup_extent_record *record)
1559+
{
1560+
struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
1561+
struct rb_node *parent_node = NULL;
1562+
struct btrfs_qgroup_extent_record *entry;
1563+
u64 bytenr = record->bytenr;
1564+
1565+
while (*p) {
1566+
parent_node = *p;
1567+
entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,
1568+
node);
1569+
if (bytenr < entry->bytenr)
1570+
p = &(*p)->rb_left;
1571+
else if (bytenr > entry->bytenr)
1572+
p = &(*p)->rb_right;
1573+
else
1574+
return entry;
1575+
}
1576+
1577+
rb_link_node(&record->node, parent_node, p);
1578+
rb_insert_color(&record->node, &delayed_refs->dirty_extent_root);
1579+
return NULL;
1580+
}
1581+
1582+
/*
1583+
* The easy accounting, if we are adding/removing the only ref for an extent
1584+
* then this qgroup and all of the parent qgroups get their refrence and
1585+
* exclusive counts adjusted.
1586+
*/
15561587
static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
15571588
struct btrfs_qgroup_operation *oper)
15581589
{

fs/btrfs/qgroup.h

+17
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#ifndef __BTRFS_QGROUP__
2020
#define __BTRFS_QGROUP__
2121

22+
#include "ulist.h"
23+
#include "delayed-ref.h"
24+
2225
/*
2326
* A description of the operations, all of these operations only happen when we
2427
* are adding the 1st reference for that subvolume in the case of adding space
@@ -58,6 +61,17 @@ struct btrfs_qgroup_operation {
5861
struct list_head list;
5962
};
6063

64+
/*
65+
* Record a dirty extent, and info qgroup to update quota on it
66+
* TODO: Use kmem cache to alloc it.
67+
*/
68+
struct btrfs_qgroup_extent_record {
69+
struct rb_node node;
70+
u64 bytenr;
71+
u64 num_bytes;
72+
struct ulist *old_roots;
73+
};
74+
6175
int btrfs_quota_enable(struct btrfs_trans_handle *trans,
6276
struct btrfs_fs_info *fs_info);
6377
int btrfs_quota_disable(struct btrfs_trans_handle *trans,
@@ -84,6 +98,9 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
8498
u64 bytenr, u64 num_bytes,
8599
enum btrfs_qgroup_operation_type type,
86100
int mod_seq);
101+
struct btrfs_qgroup_extent_record
102+
*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
103+
struct btrfs_qgroup_extent_record *record);
87104
int btrfs_delayed_qgroup_accounting(struct btrfs_trans_handle *trans,
88105
struct btrfs_fs_info *fs_info);
89106
void btrfs_remove_qgroup_operation(struct btrfs_trans_handle *trans,

fs/btrfs/transaction.c

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ static noinline int join_transaction(struct btrfs_root *root, unsigned int type)
225225
cur_trans->dirty_bg_run = 0;
226226

227227
cur_trans->delayed_refs.href_root = RB_ROOT;
228+
cur_trans->delayed_refs.dirty_extent_root = RB_ROOT;
228229
atomic_set(&cur_trans->delayed_refs.num_entries, 0);
229230
cur_trans->delayed_refs.num_heads_ready = 0;
230231
cur_trans->delayed_refs.pending_csums = 0;

0 commit comments

Comments
 (0)