Skip to content

Commit a4b6e07

Browse files
committed
Btrfs: limit balancing work while flushing delayed refs
The delayed reference mechanism is responsible for all updates to the extent allocation trees, including those updates created while processing the delayed references. This commit tries to limit the amount of work that gets created during the final run of delayed refs before a commit. It avoids cowing new blocks unless it is required to finish the commit, and so it avoids new allocations that were not really required. The goal is to avoid infinite loops where we are always making more work on the final run of delayed refs. Over the long term we'll make a special log for the last delayed ref updates as well. Signed-off-by: Chris Mason <chris.mason@oracle.com>
1 parent 5d13a98 commit a4b6e07

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

fs/btrfs/ctree.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
949949
BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
950950
return 0;
951951

952+
if (trans->transaction->delayed_refs.flushing &&
953+
btrfs_header_nritems(mid) > 2)
954+
return 0;
955+
952956
if (btrfs_header_nritems(mid) < 2)
953957
err_on_enospc = 1;
954958

@@ -2159,7 +2163,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
21592163
ret = insert_new_root(trans, root, path, level + 1);
21602164
if (ret)
21612165
return ret;
2162-
} else {
2166+
} else if (!trans->transaction->delayed_refs.flushing) {
21632167
ret = push_nodes_for_insert(trans, root, path, level);
21642168
c = path->nodes[level];
21652169
if (!ret && btrfs_header_nritems(c) <
@@ -2848,7 +2852,8 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
28482852
int num_doubles = 0;
28492853

28502854
/* first try to make some room by pushing left and right */
2851-
if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) {
2855+
if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY &&
2856+
!trans->transaction->delayed_refs.flushing) {
28522857
wret = push_leaf_right(trans, root, path, data_size, 0);
28532858
if (wret < 0)
28542859
return wret;
@@ -3786,7 +3791,8 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
37863791
}
37873792

37883793
/* delete the leaf if it is mostly empty */
3789-
if (used < BTRFS_LEAF_DATA_SIZE(root) / 4) {
3794+
if (used < BTRFS_LEAF_DATA_SIZE(root) / 4 &&
3795+
!trans->transaction->delayed_refs.flushing) {
37903796
/* push_leaf_left fixes the path.
37913797
* make sure the path still points to our leaf
37923798
* for possible call to del_ptr below

0 commit comments

Comments
 (0)