diff options
author | Nikolay Borisov <nborisov@suse.com> | 2018-06-08 15:47:57 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-10-23 14:48:41 +0200 |
commit | 909357e86799a338f40c9e997d1e3ba4adde3f89 (patch) | |
tree | 2b6ae9ec51a1daba8154614cd7567222bc6279bf /transaction.c | |
parent | d8a5e756be6beb47d315165610f68f18ae21fe39 (diff) |
btrfs-progs: Wire up delayed refs
This commit enables the delayed refs infrastructures. This entails doing
the following:
1. Replacing existing calls of btrfs_extent_post_op (which is the
equivalent of delayed refs) with the proper btrfs_run_delayed_refs.
As well as eliminating open-coded calls to finish_current_insert and
del_pending_extents which execute the delayed ops.
2. Wiring up the addition of delayed refs when freeing extents
(btrfs_free_extent) and when adding new extents (alloc_tree_block).
3. Adding calls to btrfs_run_delayed refs in the transaction commit
path alongside comments why every call is needed, since it's not
always obvious (those call sites were derived empirically by running
and debugging existing tests)
4. Correctly flagging the transaction in which we are reinitialising
the extent tree.
5. Moving btrfs_write_dirty_block_groups to
btrfs_write_dirty_block_groups since blockgroups should be written to
disk after the last delayed refs have been run.
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'transaction.c')
-rw-r--r-- | transaction.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/transaction.c b/transaction.c index 20a78c73..db9f3398 100644 --- a/transaction.c +++ b/transaction.c @@ -61,7 +61,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, u64 old_root_bytenr; struct btrfs_root *tree_root = root->fs_info->tree_root; - btrfs_write_dirty_block_groups(trans); while(1) { old_root_bytenr = btrfs_root_bytenr(&root->root_item); if (old_root_bytenr == root->node->start) @@ -99,6 +98,17 @@ int commit_tree_roots(struct btrfs_trans_handle *trans, if (ret) return ret; + /* + * If the above CoW is the first one to dirty the current tree_root, + * delayed refs for it won't be run until after this function has + * finished executing, meaning we won't process the extent tree root, + * which will have been added to ->dirty_cowonly_roots. So run + * delayed refs here as well. + */ + ret = btrfs_run_delayed_refs(trans, -1); + if (ret) + return ret; + while(!list_empty(&fs_info->dirty_cowonly_roots)) { next = fs_info->dirty_cowonly_roots.next; list_del_init(next); @@ -150,6 +160,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, if (trans->fs_info->transaction_aborted) return -EROFS; + /* + * Flush all accumulated delayed refs so that root-tree updates are + * consistent + */ + ret = btrfs_run_delayed_refs(trans, -1); + BUG_ON(ret); if (root->commit_root == root->node) goto commit_tree; @@ -167,10 +183,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ret = btrfs_update_root(trans, root->fs_info->tree_root, &root->root_key, &root->root_item); BUG_ON(ret); + commit_tree: ret = commit_tree_roots(trans, fs_info); BUG_ON(ret); - ret = __commit_transaction(trans, root); + /* + * Ensure that all comitted roots are properly accounted in the + * extent tree + */ + ret = btrfs_run_delayed_refs(trans, -1); + BUG_ON(ret); + btrfs_write_dirty_block_groups(trans); + __commit_transaction(trans, root); if (ret < 0) goto out; write_ctree_super(trans); |