aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-10-13 13:29:19 -0400
committerChris Mason <chris.mason@oracle.com>2009-10-13 13:35:12 -0400
commit690587d109ffe19d6743e4cc80c18b0906b7f9ff (patch)
tree788acd32c4ed1463d0166d0c45b233d96bb102e0 /fs/btrfs
parent257c62e1bce03e5b9f3f069fd52ad73a56de71fd (diff)
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: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/transaction.c45
-rw-r--r--fs/btrfs/transaction.h4
-rw-r--r--fs/btrfs/tree-log.c8
3 files changed, 53 insertions, 4 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 0b8f36d4400a..bca82a4ca8e6 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -344,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
344/* 344/*
345 * when btree blocks are allocated, they have some corresponding bits set for 345 * when btree blocks are allocated, they have some corresponding bits set for
346 * them in one of two extent_io trees. This is used to make sure all of 346 * them in one of two extent_io trees. This is used to make sure all of
347 * those extents are on disk for transaction or log commit 347 * those extents are sent to disk but does not wait on them
348 */ 348 */
349int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, 349int btrfs_write_marked_extents(struct btrfs_root *root,
350 struct extent_io_tree *dirty_pages) 350 struct extent_io_tree *dirty_pages)
351{ 351{
352 int ret; 352 int ret;
353 int err = 0; 353 int err = 0;
@@ -394,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
394 page_cache_release(page); 394 page_cache_release(page);
395 } 395 }
396 } 396 }
397 if (err)
398 werr = err;
399 return werr;
400}
401
402/*
403 * when btree blocks are allocated, they have some corresponding bits set for
404 * them in one of two extent_io trees. This is used to make sure all of
405 * those extents are on disk for transaction or log commit. We wait
406 * on all the pages and clear them from the dirty pages state tree
407 */
408int btrfs_wait_marked_extents(struct btrfs_root *root,
409 struct extent_io_tree *dirty_pages)
410{
411 int ret;
412 int err = 0;
413 int werr = 0;
414 struct page *page;
415 struct inode *btree_inode = root->fs_info->btree_inode;
416 u64 start = 0;
417 u64 end;
418 unsigned long index;
419
397 while (1) { 420 while (1) {
398 ret = find_first_extent_bit(dirty_pages, 0, &start, &end, 421 ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
399 EXTENT_DIRTY); 422 EXTENT_DIRTY);
@@ -424,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
424 return werr; 447 return werr;
425} 448}
426 449
450/*
451 * when btree blocks are allocated, they have some corresponding bits set for
452 * them in one of two extent_io trees. This is used to make sure all of
453 * those extents are on disk for transaction or log commit
454 */
455int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
456 struct extent_io_tree *dirty_pages)
457{
458 int ret;
459 int ret2;
460
461 ret = btrfs_write_marked_extents(root, dirty_pages);
462 ret2 = btrfs_wait_marked_extents(root, dirty_pages);
463 return ret || ret2;
464}
465
427int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, 466int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
428 struct btrfs_root *root) 467 struct btrfs_root *root)
429{ 468{
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index f68cbbe61e56..d4e3e7a6938c 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -108,5 +108,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
108 struct btrfs_root *root); 108 struct btrfs_root *root);
109int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, 109int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
110 struct extent_io_tree *dirty_pages); 110 struct extent_io_tree *dirty_pages);
111int btrfs_write_marked_extents(struct btrfs_root *root,
112 struct extent_io_tree *dirty_pages);
113int btrfs_wait_marked_extents(struct btrfs_root *root,
114 struct extent_io_tree *dirty_pages);
111int btrfs_transaction_in_commit(struct btrfs_fs_info *info); 115int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
112#endif 116#endif
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 0a1bde268963..4aff766d171a 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2013,7 +2013,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2013 goto out; 2013 goto out;
2014 } 2014 }
2015 2015
2016 ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); 2016 /* we start IO on all the marked extents here, but we don't actually
2017 * wait for them until later.
2018 */
2019 ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
2017 BUG_ON(ret); 2020 BUG_ON(ret);
2018 2021
2019 btrfs_set_root_node(&log->root_item, log->node); 2022 btrfs_set_root_node(&log->root_item, log->node);
@@ -2048,6 +2051,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2048 2051
2049 index2 = log_root_tree->log_transid % 2; 2052 index2 = log_root_tree->log_transid % 2;
2050 if (atomic_read(&log_root_tree->log_commit[index2])) { 2053 if (atomic_read(&log_root_tree->log_commit[index2])) {
2054 btrfs_wait_marked_extents(log, &log->dirty_log_pages);
2051 wait_log_commit(trans, log_root_tree, 2055 wait_log_commit(trans, log_root_tree,
2052 log_root_tree->log_transid); 2056 log_root_tree->log_transid);
2053 mutex_unlock(&log_root_tree->log_mutex); 2057 mutex_unlock(&log_root_tree->log_mutex);
@@ -2067,6 +2071,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2067 * check the full commit flag again 2071 * check the full commit flag again
2068 */ 2072 */
2069 if (root->fs_info->last_trans_log_full_commit == trans->transid) { 2073 if (root->fs_info->last_trans_log_full_commit == trans->transid) {
2074 btrfs_wait_marked_extents(log, &log->dirty_log_pages);
2070 mutex_unlock(&log_root_tree->log_mutex); 2075 mutex_unlock(&log_root_tree->log_mutex);
2071 ret = -EAGAIN; 2076 ret = -EAGAIN;
2072 goto out_wake_log_root; 2077 goto out_wake_log_root;
@@ -2075,6 +2080,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2075 ret = btrfs_write_and_wait_marked_extents(log_root_tree, 2080 ret = btrfs_write_and_wait_marked_extents(log_root_tree,
2076 &log_root_tree->dirty_log_pages); 2081 &log_root_tree->dirty_log_pages);
2077 BUG_ON(ret); 2082 BUG_ON(ret);
2083 btrfs_wait_marked_extents(log, &log->dirty_log_pages);
2078 2084
2079 btrfs_set_super_log_root(&root->fs_info->super_for_commit, 2085 btrfs_set_super_log_root(&root->fs_info->super_for_commit,
2080 log_root_tree->node->start); 2086 log_root_tree->node->start);