aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-09-26 13:58:47 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:48 -0400
commit1728366efa5ebf48bd2ed544afa8700cd07ba822 (patch)
tree1f5d2129f3db9a9e8c3aa96b0c8120a55aac925c /fs/btrfs/transaction.c
parent462d6fac8960a3ba797927adfcbd29d503eb16fd (diff)
Btrfs: stop using write_one_page
While looking for a performance regression a user was complaining about, I noticed that we had a regression with the varmail test of filebench. This was introduced by 0d10ee2e6deb5c8409ae65b970846344897d5e4e which keeps us from calling writepages in writepage. This is a correct change, however it happens to help the varmail test because we write out in larger chunks. This is largly to do with how we write out dirty pages for each transaction. If you run filebench with load varmail set $dir=/mnt/btrfs-test run 60 prior to this patch you would get ~1420 ops/second, but with the patch you get ~1200 ops/second. This is a 16% decrease. So since we know the range of dirty pages we want to write out, don't write out in one page chunks, write out in ranges. So to do this we call filemap_fdatawrite_range() on the range of bytes. Then we convert the DIRTY extents to NEED_WAIT extents. When we then call btrfs_wait_marked_extents() we only have to filemap_fdatawait_range() on that range and clear the NEED_WAIT extents. This doesn't get us back to our original speeds, but I've been seeing ~1380 ops/second, which is a <5% regression as opposed to a >15% regression. That is acceptable given that the original commit greatly reduces our latency to begin with. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c86
1 files changed, 19 insertions, 67 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 7debbf396ef..45655793a2c 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -572,50 +572,21 @@ int btrfs_end_transaction_dmeta(struct btrfs_trans_handle *trans,
572int btrfs_write_marked_extents(struct btrfs_root *root, 572int btrfs_write_marked_extents(struct btrfs_root *root,
573 struct extent_io_tree *dirty_pages, int mark) 573 struct extent_io_tree *dirty_pages, int mark)
574{ 574{
575 int ret;
576 int err = 0; 575 int err = 0;
577 int werr = 0; 576 int werr = 0;
578 struct page *page; 577 struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
579 struct inode *btree_inode = root->fs_info->btree_inode;
580 u64 start = 0; 578 u64 start = 0;
581 u64 end; 579 u64 end;
582 unsigned long index;
583 580
584 while (1) { 581 while (!find_first_extent_bit(dirty_pages, start, &start, &end,
585 ret = find_first_extent_bit(dirty_pages, start, &start, &end, 582 mark)) {
586 mark); 583 convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, mark,
587 if (ret) 584 GFP_NOFS);
588 break; 585 err = filemap_fdatawrite_range(mapping, start, end);
589 while (start <= end) { 586 if (err)
590 cond_resched(); 587 werr = err;
591 588 cond_resched();
592 index = start >> PAGE_CACHE_SHIFT; 589 start = end + 1;
593 start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
594 page = find_get_page(btree_inode->i_mapping, index);
595 if (!page)
596 continue;
597
598 btree_lock_page_hook(page);
599 if (!page->mapping) {
600 unlock_page(page);
601 page_cache_release(page);
602 continue;
603 }
604
605 if (PageWriteback(page)) {
606 if (PageDirty(page))
607 wait_on_page_writeback(page);
608 else {
609 unlock_page(page);
610 page_cache_release(page);
611 continue;
612 }
613 }
614 err = write_one_page(page, 0);
615 if (err)
616 werr = err;
617 page_cache_release(page);
618 }
619 } 590 }
620 if (err) 591 if (err)
621 werr = err; 592 werr = err;
@@ -631,39 +602,20 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
631int btrfs_wait_marked_extents(struct btrfs_root *root, 602int btrfs_wait_marked_extents(struct btrfs_root *root,
632 struct extent_io_tree *dirty_pages, int mark) 603 struct extent_io_tree *dirty_pages, int mark)
633{ 604{
634 int ret;
635 int err = 0; 605 int err = 0;
636 int werr = 0; 606 int werr = 0;
637 struct page *page; 607 struct address_space *mapping = root->fs_info->btree_inode->i_mapping;
638 struct inode *btree_inode = root->fs_info->btree_inode;
639 u64 start = 0; 608 u64 start = 0;
640 u64 end; 609 u64 end;
641 unsigned long index;
642 610
643 while (1) { 611 while (!find_first_extent_bit(dirty_pages, start, &start, &end,
644 ret = find_first_extent_bit(dirty_pages, start, &start, &end, 612 EXTENT_NEED_WAIT)) {
645 mark); 613 clear_extent_bits(dirty_pages, start, end, EXTENT_NEED_WAIT, GFP_NOFS);
646 if (ret) 614 err = filemap_fdatawait_range(mapping, start, end);
647 break; 615 if (err)
648 616 werr = err;
649 clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS); 617 cond_resched();
650 while (start <= end) { 618 start = end + 1;
651 index = start >> PAGE_CACHE_SHIFT;
652 start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
653 page = find_get_page(btree_inode->i_mapping, index);
654 if (!page)
655 continue;
656 if (PageDirty(page)) {
657 btree_lock_page_hook(page);
658 wait_on_page_writeback(page);
659 err = write_one_page(page, 0);
660 if (err)
661 werr = err;
662 }
663 wait_on_page_writeback(page);
664 page_cache_release(page);
665 cond_resched();
666 }
667 } 619 }
668 if (err) 620 if (err)
669 werr = err; 621 werr = err;