Commit 690587d1 authored by Chris Mason's avatar Chris Mason

Btrfs: streamline tree-log btree block writeout

Syncing the tree log is a 3 phase operation.

1) write and wait for all the tree log blocks for a given root.

2) write and wait for all the tree log blocks for the
tree of tree log roots.

3) write and wait for the super blocks (barriers here)

This isn't as efficient as it could be because there is
no requirement to wait for the blocks from step one to hit the disk
before we start writing the blocks from step two.  This commit
changes the sequence so that we don't start waiting until
all the tree blocks from both steps one and two have been sent
to disk.

We do this by breaking up btrfs_write_wait_marked_extents into
two functions, which is trivial because it was already broken
up into two parts.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 257c62e1
...@@ -344,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, ...@@ -344,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
/* /*
* when btree blocks are allocated, they have some corresponding bits set for * when btree blocks are allocated, they have some corresponding bits set for
* them in one of two extent_io trees. This is used to make sure all of * them in one of two extent_io trees. This is used to make sure all of
* those extents are on disk for transaction or log commit * those extents are sent to disk but does not wait on them
*/ */
int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, int btrfs_write_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages) struct extent_io_tree *dirty_pages)
{ {
int ret; int ret;
int err = 0; int err = 0;
...@@ -394,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, ...@@ -394,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
page_cache_release(page); page_cache_release(page);
} }
} }
if (err)
werr = err;
return werr;
}
/*
* when btree blocks are allocated, they have some corresponding bits set for
* them in one of two extent_io trees. This is used to make sure all of
* those extents are on disk for transaction or log commit. We wait
* on all the pages and clear them from the dirty pages state tree
*/
int btrfs_wait_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages)
{
int ret;
int err = 0;
int werr = 0;
struct page *page;
struct inode *btree_inode = root->fs_info->btree_inode;
u64 start = 0;
u64 end;
unsigned long index;
while (1) { while (1) {
ret = find_first_extent_bit(dirty_pages, 0, &start, &end, ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
EXTENT_DIRTY); EXTENT_DIRTY);
...@@ -424,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, ...@@ -424,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
return werr; return werr;
} }
/*
* when btree blocks are allocated, they have some corresponding bits set for
* them in one of two extent_io trees. This is used to make sure all of
* those extents are on disk for transaction or log commit
*/
int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages)
{
int ret;
int ret2;
ret = btrfs_write_marked_extents(root, dirty_pages);
ret2 = btrfs_wait_marked_extents(root, dirty_pages);
return ret || ret2;
}
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root) struct btrfs_root *root)
{ {
......
...@@ -108,5 +108,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, ...@@ -108,5 +108,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages); struct extent_io_tree *dirty_pages);
int btrfs_write_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages);
int btrfs_wait_marked_extents(struct btrfs_root *root,
struct extent_io_tree *dirty_pages);
int btrfs_transaction_in_commit(struct btrfs_fs_info *info); int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
#endif #endif
...@@ -2013,7 +2013,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, ...@@ -2013,7 +2013,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
goto out; goto out;
} }
ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); /* we start IO on all the marked extents here, but we don't actually
* wait for them until later.
*/
ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
BUG_ON(ret); BUG_ON(ret);
btrfs_set_root_node(&log->root_item, log->node); btrfs_set_root_node(&log->root_item, log->node);
...@@ -2048,6 +2051,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, ...@@ -2048,6 +2051,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
index2 = log_root_tree->log_transid % 2; index2 = log_root_tree->log_transid % 2;
if (atomic_read(&log_root_tree->log_commit[index2])) { if (atomic_read(&log_root_tree->log_commit[index2])) {
btrfs_wait_marked_extents(log, &log->dirty_log_pages);
wait_log_commit(trans, log_root_tree, wait_log_commit(trans, log_root_tree,
log_root_tree->log_transid); log_root_tree->log_transid);
mutex_unlock(&log_root_tree->log_mutex); mutex_unlock(&log_root_tree->log_mutex);
...@@ -2067,6 +2071,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, ...@@ -2067,6 +2071,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
* check the full commit flag again * check the full commit flag again
*/ */
if (root->fs_info->last_trans_log_full_commit == trans->transid) { if (root->fs_info->last_trans_log_full_commit == trans->transid) {
btrfs_wait_marked_extents(log, &log->dirty_log_pages);
mutex_unlock(&log_root_tree->log_mutex); mutex_unlock(&log_root_tree->log_mutex);
ret = -EAGAIN; ret = -EAGAIN;
goto out_wake_log_root; goto out_wake_log_root;
...@@ -2075,6 +2080,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, ...@@ -2075,6 +2080,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
ret = btrfs_write_and_wait_marked_extents(log_root_tree, ret = btrfs_write_and_wait_marked_extents(log_root_tree,
&log_root_tree->dirty_log_pages); &log_root_tree->dirty_log_pages);
BUG_ON(ret); BUG_ON(ret);
btrfs_wait_marked_extents(log, &log->dirty_log_pages);
btrfs_set_super_log_root(&root->fs_info->super_for_commit, btrfs_set_super_log_root(&root->fs_info->super_for_commit,
log_root_tree->node->start); log_root_tree->node->start);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment