Skip to content

Commit

Permalink
Btrfs: limit balancing work while flushing delayed refs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Mason committed Mar 24, 2009
1 parent 5d13a98 commit a4b6e07
Showing 1 changed file with 9 additions and 3 deletions.
12 changes: 9 additions & 3 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
return 0;

if (trans->transaction->delayed_refs.flushing &&
btrfs_header_nritems(mid) > 2)
return 0;

if (btrfs_header_nritems(mid) < 2)
err_on_enospc = 1;

Expand Down Expand Up @@ -2159,7 +2163,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
ret = insert_new_root(trans, root, path, level + 1);
if (ret)
return ret;
} else {
} else if (!trans->transaction->delayed_refs.flushing) {
ret = push_nodes_for_insert(trans, root, path, level);
c = path->nodes[level];
if (!ret && btrfs_header_nritems(c) <
Expand Down Expand Up @@ -2848,7 +2852,8 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
int num_doubles = 0;

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

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

0 comments on commit a4b6e07

Please sign in to comment.