Skip to content

Commit cecbb53

Browse files
boryaskdave
authored andcommitted
btrfs: record simple quota deltas in delayed refs
At the moment that we run delayed refs, we make the final ref-count based decision on creating/removing extent (and metadata) items. Therefore, it is exactly the spot to hook up simple quotas. There are a few important subtleties to the fields we must collect to accurately track simple quotas, particularly when removing an extent. When removing a data extent, the ref could be in any tree (due to reflink, for example) and so we need to recover the owning root id from the owner ref item. When removing a metadata extent, we know the owning root from the owner field in the header when we create the delayed ref, so we can recover it from there. We must also be careful to handle reservations properly to not leaked reserved space. The happy path is freeing the reservation when the simple quota delta runs on a data extent. If that doesn't happen, due to refs canceling out or some error, the ref head already has the must_insert_reserved machinery to handle this, so we piggy back on that and use it to clean up the reserved data. Signed-off-by: Boris Burkov <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 8d29909 commit cecbb53

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

fs/btrfs/delayed-ref.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref,
801801
head_ref->bytenr = bytenr;
802802
head_ref->num_bytes = num_bytes;
803803
head_ref->ref_mod = count_mod;
804+
head_ref->reserved_bytes = reserved;
804805
head_ref->must_insert_reserved = must_insert_reserved;
805806
head_ref->owning_root = owning_root;
806807
head_ref->is_data = is_data;

fs/btrfs/delayed-ref.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ struct btrfs_delayed_ref_head {
116116
*/
117117
u64 owning_root;
118118

119+
/*
120+
* Track reserved bytes when setting must_insert_reserved. On success
121+
* or cleanup, we will need to free the reservation.
122+
*/
123+
u64 reserved_bytes;
124+
119125
/*
120126
* when a new extent is allocated, it is just reserved in memory
121127
* The actual extent isn't inserted into the extent allocation tree

fs/btrfs/extent-tree.c

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949

5050
static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
51+
struct btrfs_delayed_ref_head *href,
5152
struct btrfs_delayed_ref_node *node, u64 parent,
5253
u64 root_objectid, u64 owner_objectid,
5354
u64 owner_offset,
@@ -1541,6 +1542,7 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
15411542
}
15421543

15431544
static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
1545+
struct btrfs_delayed_ref_head *href,
15441546
struct btrfs_delayed_ref_node *node,
15451547
struct btrfs_delayed_extent_op *extent_op,
15461548
bool insert_reserved)
@@ -1558,6 +1560,13 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
15581560

15591561
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
15601562
struct btrfs_key key;
1563+
struct btrfs_squota_delta delta = {
1564+
.root = href->owning_root,
1565+
.num_bytes = node->num_bytes,
1566+
.rsv_bytes = href->reserved_bytes,
1567+
.is_data = true,
1568+
.is_inc = true,
1569+
};
15611570

15621571
if (extent_op)
15631572
flags |= extent_op->flags_to_set;
@@ -1570,12 +1579,17 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
15701579
flags, ref->objectid,
15711580
ref->offset, &key,
15721581
node->ref_mod);
1582+
if (!ret)
1583+
ret = btrfs_record_squota_delta(trans->fs_info, &delta);
1584+
else
1585+
btrfs_qgroup_free_refroot(trans->fs_info, delta.root,
1586+
delta.rsv_bytes, BTRFS_QGROUP_RSV_DATA);
15731587
} else if (node->action == BTRFS_ADD_DELAYED_REF) {
15741588
ret = __btrfs_inc_extent_ref(trans, node, parent, ref->root,
15751589
ref->objectid, ref->offset,
15761590
extent_op);
15771591
} else if (node->action == BTRFS_DROP_DELAYED_REF) {
1578-
ret = __btrfs_free_extent(trans, node, parent,
1592+
ret = __btrfs_free_extent(trans, href, node, parent,
15791593
ref->root, ref->objectid,
15801594
ref->offset, extent_op);
15811595
} else {
@@ -1692,11 +1706,13 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
16921706
}
16931707

16941708
static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
1709+
struct btrfs_delayed_ref_head *href,
16951710
struct btrfs_delayed_ref_node *node,
16961711
struct btrfs_delayed_extent_op *extent_op,
16971712
bool insert_reserved)
16981713
{
16991714
int ret = 0;
1715+
struct btrfs_fs_info *fs_info = trans->fs_info;
17001716
struct btrfs_delayed_tree_ref *ref;
17011717
u64 parent = 0;
17021718
u64 ref_root = 0;
@@ -1716,13 +1732,23 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
17161732
return -EUCLEAN;
17171733
}
17181734
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
1735+
struct btrfs_squota_delta delta = {
1736+
.root = href->owning_root,
1737+
.num_bytes = fs_info->nodesize,
1738+
.rsv_bytes = 0,
1739+
.is_data = false,
1740+
.is_inc = true,
1741+
};
1742+
17191743
BUG_ON(!extent_op || !extent_op->update_flags);
17201744
ret = alloc_reserved_tree_block(trans, node, extent_op);
1745+
if (!ret)
1746+
btrfs_record_squota_delta(fs_info, &delta);
17211747
} else if (node->action == BTRFS_ADD_DELAYED_REF) {
17221748
ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root,
17231749
ref->level, 0, extent_op);
17241750
} else if (node->action == BTRFS_DROP_DELAYED_REF) {
1725-
ret = __btrfs_free_extent(trans, node, parent, ref_root,
1751+
ret = __btrfs_free_extent(trans, href, node, parent, ref_root,
17261752
ref->level, 0, extent_op);
17271753
} else {
17281754
BUG();
@@ -1732,6 +1758,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
17321758

17331759
/* helper function to actually process a single delayed ref entry */
17341760
static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
1761+
struct btrfs_delayed_ref_head *href,
17351762
struct btrfs_delayed_ref_node *node,
17361763
struct btrfs_delayed_extent_op *extent_op,
17371764
bool insert_reserved)
@@ -1746,11 +1773,11 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
17461773

17471774
if (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
17481775
node->type == BTRFS_SHARED_BLOCK_REF_KEY)
1749-
ret = run_delayed_tree_ref(trans, node, extent_op,
1776+
ret = run_delayed_tree_ref(trans, href, node, extent_op,
17501777
insert_reserved);
17511778
else if (node->type == BTRFS_EXTENT_DATA_REF_KEY ||
17521779
node->type == BTRFS_SHARED_DATA_REF_KEY)
1753-
ret = run_delayed_data_ref(trans, node, extent_op,
1780+
ret = run_delayed_data_ref(trans, href, node, extent_op,
17541781
insert_reserved);
17551782
else if (node->type == BTRFS_EXTENT_OWNER_REF_KEY)
17561783
ret = 0;
@@ -1852,6 +1879,10 @@ u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
18521879

18531880
return btrfs_calc_delayed_ref_csum_bytes(fs_info, nr_csums);
18541881
}
1882+
if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE &&
1883+
head->must_insert_reserved && head->is_data)
1884+
btrfs_qgroup_free_refroot(fs_info, head->owning_root,
1885+
head->reserved_bytes, BTRFS_QGROUP_RSV_DATA);
18551886

18561887
return 0;
18571888
}
@@ -2000,10 +2031,11 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
20002031
locked_ref->extent_op = NULL;
20012032
spin_unlock(&locked_ref->lock);
20022033

2003-
ret = run_one_delayed_ref(trans, ref, extent_op,
2034+
ret = run_one_delayed_ref(trans, locked_ref, ref, extent_op,
20042035
must_insert_reserved);
20052036
btrfs_delayed_refs_rsv_release(fs_info, 1, 0);
20062037
*bytes_released += btrfs_calc_delayed_ref_bytes(fs_info, 1);
2038+
20072039
btrfs_free_delayed_extent_op(extent_op);
20082040
if (ret) {
20092041
unselect_delayed_ref_head(delayed_refs, locked_ref);
@@ -2916,11 +2948,12 @@ u64 btrfs_get_extent_owner_root(struct btrfs_fs_info *fs_info,
29162948
}
29172949

29182950
static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
2919-
u64 bytenr, u64 num_bytes, bool is_data)
2951+
u64 bytenr, struct btrfs_squota_delta *delta)
29202952
{
29212953
int ret;
2954+
u64 num_bytes = delta->num_bytes;
29222955

2923-
if (is_data) {
2956+
if (delta->is_data) {
29242957
struct btrfs_root *csum_root;
29252958

29262959
csum_root = btrfs_csum_root(trans->fs_info, bytenr);
@@ -2937,6 +2970,12 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
29372970
}
29382971
}
29392972

2973+
ret = btrfs_record_squota_delta(trans->fs_info, delta);
2974+
if (ret) {
2975+
btrfs_abort_transaction(trans, ret);
2976+
return ret;
2977+
}
2978+
29402979
ret = add_to_free_space_tree(trans, bytenr, num_bytes);
29412980
if (ret) {
29422981
btrfs_abort_transaction(trans, ret);
@@ -3017,6 +3056,7 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
30173056
* And that (13631488 EXTENT_DATA_REF <HASH>) gets removed.
30183057
*/
30193058
static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
3059+
struct btrfs_delayed_ref_head *href,
30203060
struct btrfs_delayed_ref_node *node, u64 parent,
30213061
u64 root_objectid, u64 owner_objectid,
30223062
u64 owner_offset,
@@ -3040,6 +3080,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
30403080
u64 bytenr = node->bytenr;
30413081
u64 num_bytes = node->num_bytes;
30423082
bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
3083+
u64 delayed_ref_root = href->owning_root;
30433084

30443085
extent_root = btrfs_extent_root(info, bytenr);
30453086
ASSERT(extent_root);
@@ -3240,6 +3281,14 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
32403281
}
32413282
}
32423283
} else {
3284+
struct btrfs_squota_delta delta = {
3285+
.root = delayed_ref_root,
3286+
.num_bytes = num_bytes,
3287+
.rsv_bytes = 0,
3288+
.is_data = is_data,
3289+
.is_inc = false,
3290+
};
3291+
32433292
/* In this branch refs == 1 */
32443293
if (found_extent) {
32453294
if (is_data && refs_to_drop !=
@@ -3278,6 +3327,16 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
32783327
num_to_del = 2;
32793328
}
32803329
}
3330+
/*
3331+
* We can't infer the data owner from the delayed ref, so we need
3332+
* to try to get it from the owning ref item.
3333+
*
3334+
* If it is not present, then that extent was not written under
3335+
* simple quotas mode, so we don't need to account for its deletion.
3336+
*/
3337+
if (is_data)
3338+
delta.root = btrfs_get_extent_owner_root(trans->fs_info,
3339+
leaf, extent_slot);
32813340

32823341
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
32833342
num_to_del);
@@ -3287,7 +3346,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
32873346
}
32883347
btrfs_release_path(path);
32893348

3290-
ret = do_free_extent_accounting(trans, bytenr, num_bytes, is_data);
3349+
ret = do_free_extent_accounting(trans, bytenr, &delta);
32913350
}
32923351
btrfs_release_path(path);
32933352

@@ -4862,6 +4921,13 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
48624921
int ret;
48634922
struct btrfs_block_group *block_group;
48644923
struct btrfs_space_info *space_info;
4924+
struct btrfs_squota_delta delta = {
4925+
.root = root_objectid,
4926+
.num_bytes = ins->offset,
4927+
.rsv_bytes = 0,
4928+
.is_data = true,
4929+
.is_inc = true,
4930+
};
48654931

48664932
/*
48674933
* Mixed block groups will exclude before processing the log so we only
@@ -4890,6 +4956,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
48904956
offset, ins, 1);
48914957
if (ret)
48924958
btrfs_pin_extent(trans, ins->objectid, ins->offset, 1);
4959+
ret = btrfs_record_squota_delta(fs_info, &delta);
48934960
btrfs_put_block_group(block_group);
48944961
return ret;
48954962
}

0 commit comments

Comments
 (0)