aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-19 12:44:22 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-19 12:44:22 -0500
commitd2c3f4f695edac4d75c1b3eb01a1d16072de63bb (patch)
tree14a8dd519d067adbe16e8adb7342343529eb5c75 /fs/btrfs/disk-io.c
parent105d931d482b7d1b1b2dd4b0ea30365db8630b9f (diff)
Btrfs: Avoid writeback stalls
While building large bios in writepages, btrfs may end up waiting for other page writeback to finish if WB_SYNC_ALL is used. While it is waiting, the bio it is building has a number of pages with the writeback bit set and they aren't getting to the disk any time soon. This lowers the latencies of writeback in general by sending down the bio being built before waiting for other pages. The bio submission code tries to limit the total number of async bios in flight by waiting when we're over a certain number of async bios. But, the waits are happening while writepages is building bios, and this can easily lead to stalls and other problems for people calling wait_on_page_writeback. The current fix is to let the congestion tests take care of waiting. sync() and others make sure to drain the current async requests to make sure that everything that was pending when the sync was started really get to disk. The code would drain pending requests both before and after submitting a new request. But, if one of the requests is waiting for page writeback to finish, the draining waits might block that page writeback. This changes the draining code to only wait after submitting the bio being processed. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 0e8d31274c92..8d03e4a3c4e9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -538,15 +538,9 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
538 async->work.flags = 0; 538 async->work.flags = 0;
539 async->bio_flags = bio_flags; 539 async->bio_flags = bio_flags;
540 540
541 while(atomic_read(&fs_info->async_submit_draining) &&
542 atomic_read(&fs_info->nr_async_submits)) {
543 wait_event(fs_info->async_submit_wait,
544 (atomic_read(&fs_info->nr_async_submits) == 0));
545 }
546
547 atomic_inc(&fs_info->nr_async_submits); 541 atomic_inc(&fs_info->nr_async_submits);
548 btrfs_queue_worker(&fs_info->workers, &async->work); 542 btrfs_queue_worker(&fs_info->workers, &async->work);
549 543#if 0
550 if (atomic_read(&fs_info->nr_async_submits) > limit) { 544 if (atomic_read(&fs_info->nr_async_submits) > limit) {
551 wait_event_timeout(fs_info->async_submit_wait, 545 wait_event_timeout(fs_info->async_submit_wait,
552 (atomic_read(&fs_info->nr_async_submits) < limit), 546 (atomic_read(&fs_info->nr_async_submits) < limit),
@@ -556,7 +550,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
556 (atomic_read(&fs_info->nr_async_bios) < limit), 550 (atomic_read(&fs_info->nr_async_bios) < limit),
557 HZ/10); 551 HZ/10);
558 } 552 }
559 553#endif
560 while(atomic_read(&fs_info->async_submit_draining) && 554 while(atomic_read(&fs_info->async_submit_draining) &&
561 atomic_read(&fs_info->nr_async_submits)) { 555 atomic_read(&fs_info->nr_async_submits)) {
562 wait_event(fs_info->async_submit_wait, 556 wait_event(fs_info->async_submit_wait,
@@ -1765,11 +1759,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1765 ret = btrfs_cleanup_reloc_trees(tree_root); 1759 ret = btrfs_cleanup_reloc_trees(tree_root);
1766 BUG_ON(ret); 1760 BUG_ON(ret);
1767 1761
1762read_fs_root:
1768 location.objectid = BTRFS_FS_TREE_OBJECTID; 1763 location.objectid = BTRFS_FS_TREE_OBJECTID;
1769 location.type = BTRFS_ROOT_ITEM_KEY; 1764 location.type = BTRFS_ROOT_ITEM_KEY;
1770 location.offset = (u64)-1; 1765 location.offset = (u64)-1;
1771 1766
1772read_fs_root:
1773 fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); 1767 fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
1774 if (!fs_info->fs_root) 1768 if (!fs_info->fs_root)
1775 goto fail_cleaner; 1769 goto fail_cleaner;