diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-11-06 22:02:51 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-11-06 22:02:51 -0500 |
commit | 771ed689d2cd53439e28e095bc38fbe40a71429e (patch) | |
tree | 518801f7141928e398d40c2b5955720d4346ce1a /fs/btrfs/disk-io.c | |
parent | 4a69a41009c4ac691f7d9c289f5f37fabeddce46 (diff) |
Btrfs: Optimize compressed writeback and reads
When reading compressed extents, try to put pages into the page cache
for any pages covered by the compressed extent that readpages didn't already
preload.
Add an async work queue to handle transformations at delayed allocation processing
time. Right now this is just compression. The workflow is:
1) Find offsets in the file marked for delayed allocation
2) Lock the pages
3) Lock the state bits
4) Call the async delalloc code
The async delalloc code clears the state lock bits and delalloc bits. It is
important this happens before the range goes into the work queue because
otherwise it might deadlock with other work queue items that try to lock
those extent bits.
The file pages are compressed, and if the compression doesn't work the
pages are written back directly.
An ordered work queue is used to make sure the inodes are written in the same
order that pdflush or writepages sent them down.
This changes extent_write_cache_pages to let the writepage function
update the wbc nr_written count.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e0a28f705a64..8efc123d222b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -539,6 +539,13 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, | |||
539 | (atomic_read(&fs_info->nr_async_bios) < limit), | 539 | (atomic_read(&fs_info->nr_async_bios) < limit), |
540 | HZ/10); | 540 | HZ/10); |
541 | } | 541 | } |
542 | |||
543 | while(atomic_read(&fs_info->async_submit_draining) && | ||
544 | atomic_read(&fs_info->nr_async_submits)) { | ||
545 | wait_event(fs_info->async_submit_wait, | ||
546 | (atomic_read(&fs_info->nr_async_submits) == 0)); | ||
547 | } | ||
548 | |||
542 | return 0; | 549 | return 0; |
543 | } | 550 | } |
544 | 551 | ||
@@ -1437,6 +1444,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1437 | INIT_LIST_HEAD(&fs_info->space_info); | 1444 | INIT_LIST_HEAD(&fs_info->space_info); |
1438 | btrfs_mapping_init(&fs_info->mapping_tree); | 1445 | btrfs_mapping_init(&fs_info->mapping_tree); |
1439 | atomic_set(&fs_info->nr_async_submits, 0); | 1446 | atomic_set(&fs_info->nr_async_submits, 0); |
1447 | atomic_set(&fs_info->async_delalloc_pages, 0); | ||
1440 | atomic_set(&fs_info->async_submit_draining, 0); | 1448 | atomic_set(&fs_info->async_submit_draining, 0); |
1441 | atomic_set(&fs_info->nr_async_bios, 0); | 1449 | atomic_set(&fs_info->nr_async_bios, 0); |
1442 | atomic_set(&fs_info->throttles, 0); | 1450 | atomic_set(&fs_info->throttles, 0); |
@@ -1550,6 +1558,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1550 | btrfs_init_workers(&fs_info->workers, "worker", | 1558 | btrfs_init_workers(&fs_info->workers, "worker", |
1551 | fs_info->thread_pool_size); | 1559 | fs_info->thread_pool_size); |
1552 | 1560 | ||
1561 | btrfs_init_workers(&fs_info->delalloc_workers, "delalloc", | ||
1562 | fs_info->thread_pool_size); | ||
1563 | |||
1553 | btrfs_init_workers(&fs_info->submit_workers, "submit", | 1564 | btrfs_init_workers(&fs_info->submit_workers, "submit", |
1554 | min_t(u64, fs_devices->num_devices, | 1565 | min_t(u64, fs_devices->num_devices, |
1555 | fs_info->thread_pool_size)); | 1566 | fs_info->thread_pool_size)); |
@@ -1560,15 +1571,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1560 | */ | 1571 | */ |
1561 | fs_info->submit_workers.idle_thresh = 64; | 1572 | fs_info->submit_workers.idle_thresh = 64; |
1562 | 1573 | ||
1563 | /* fs_info->workers is responsible for checksumming file data | 1574 | fs_info->workers.idle_thresh = 16; |
1564 | * blocks and metadata. Using a larger idle thresh allows each | ||
1565 | * worker thread to operate on things in roughly the order they | ||
1566 | * were sent by the writeback daemons, improving overall locality | ||
1567 | * of the IO going down the pipe. | ||
1568 | */ | ||
1569 | fs_info->workers.idle_thresh = 8; | ||
1570 | fs_info->workers.ordered = 1; | 1575 | fs_info->workers.ordered = 1; |
1571 | 1576 | ||
1577 | fs_info->delalloc_workers.idle_thresh = 2; | ||
1578 | fs_info->delalloc_workers.ordered = 1; | ||
1579 | |||
1572 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1); | 1580 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1); |
1573 | btrfs_init_workers(&fs_info->endio_workers, "endio", | 1581 | btrfs_init_workers(&fs_info->endio_workers, "endio", |
1574 | fs_info->thread_pool_size); | 1582 | fs_info->thread_pool_size); |
@@ -1584,6 +1592,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1584 | 1592 | ||
1585 | btrfs_start_workers(&fs_info->workers, 1); | 1593 | btrfs_start_workers(&fs_info->workers, 1); |
1586 | btrfs_start_workers(&fs_info->submit_workers, 1); | 1594 | btrfs_start_workers(&fs_info->submit_workers, 1); |
1595 | btrfs_start_workers(&fs_info->delalloc_workers, 1); | ||
1587 | btrfs_start_workers(&fs_info->fixup_workers, 1); | 1596 | btrfs_start_workers(&fs_info->fixup_workers, 1); |
1588 | btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size); | 1597 | btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size); |
1589 | btrfs_start_workers(&fs_info->endio_write_workers, | 1598 | btrfs_start_workers(&fs_info->endio_write_workers, |
@@ -1732,6 +1741,7 @@ fail_tree_root: | |||
1732 | fail_sys_array: | 1741 | fail_sys_array: |
1733 | fail_sb_buffer: | 1742 | fail_sb_buffer: |
1734 | btrfs_stop_workers(&fs_info->fixup_workers); | 1743 | btrfs_stop_workers(&fs_info->fixup_workers); |
1744 | btrfs_stop_workers(&fs_info->delalloc_workers); | ||
1735 | btrfs_stop_workers(&fs_info->workers); | 1745 | btrfs_stop_workers(&fs_info->workers); |
1736 | btrfs_stop_workers(&fs_info->endio_workers); | 1746 | btrfs_stop_workers(&fs_info->endio_workers); |
1737 | btrfs_stop_workers(&fs_info->endio_write_workers); | 1747 | btrfs_stop_workers(&fs_info->endio_write_workers); |
@@ -1988,6 +1998,7 @@ int close_ctree(struct btrfs_root *root) | |||
1988 | truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); | 1998 | truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); |
1989 | 1999 | ||
1990 | btrfs_stop_workers(&fs_info->fixup_workers); | 2000 | btrfs_stop_workers(&fs_info->fixup_workers); |
2001 | btrfs_stop_workers(&fs_info->delalloc_workers); | ||
1991 | btrfs_stop_workers(&fs_info->workers); | 2002 | btrfs_stop_workers(&fs_info->workers); |
1992 | btrfs_stop_workers(&fs_info->endio_workers); | 2003 | btrfs_stop_workers(&fs_info->endio_workers); |
1993 | btrfs_stop_workers(&fs_info->endio_write_workers); | 2004 | btrfs_stop_workers(&fs_info->endio_write_workers); |
@@ -2062,7 +2073,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) | |||
2062 | struct extent_io_tree *tree; | 2073 | struct extent_io_tree *tree; |
2063 | u64 num_dirty; | 2074 | u64 num_dirty; |
2064 | u64 start = 0; | 2075 | u64 start = 0; |
2065 | unsigned long thresh = 96 * 1024 * 1024; | 2076 | unsigned long thresh = 32 * 1024 * 1024; |
2066 | tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; | 2077 | tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; |
2067 | 2078 | ||
2068 | if (current_is_pdflush() || current->flags & PF_MEMALLOC) | 2079 | if (current_is_pdflush() || current->flags & PF_MEMALLOC) |