aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-08-15 15:34:15 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:06 -0400
commit777e6bd706ee40897545463871de5b456fbc46dc (patch)
treecb927528e02234eb7fa6b5d1f14b9367efd755b6
parent0986fe9eac24fd186927c3b87af51d62f8ab92cd (diff)
Btrfs: Transaction commit: don't use filemap_fdatawait
After writing out all the remaining btree blocks in the transaction, the commit code would use filemap_fdatawait to make sure it was all on disk. This means it would wait for blocks written by other procs as well. The new code walks the list of blocks for this transaction again and waits only for those required by this transaction. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/disk-io.c11
-rw-r--r--fs/btrfs/disk-io.h1
-rw-r--r--fs/btrfs/transaction.c36
3 files changed, 36 insertions, 12 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 9902d29abd06..9601b13c7d7a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -429,7 +429,7 @@ int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
429 return 0; 429 return 0;
430} 430}
431 431
432static int congested_async(struct btrfs_fs_info *info, int iodone) 432int btrfs_congested_async(struct btrfs_fs_info *info, int iodone)
433{ 433{
434 int limit = 256 * info->fs_devices->open_devices; 434 int limit = 256 * info->fs_devices->open_devices;
435 435
@@ -438,9 +438,6 @@ static int congested_async(struct btrfs_fs_info *info, int iodone)
438 if (atomic_read(&info->nr_async_submits) > limit) 438 if (atomic_read(&info->nr_async_submits) > limit)
439 return 1; 439 return 1;
440 440
441 limit = 8192 * info->fs_devices->open_devices;
442 if (iodone)
443 limit = (limit * 3) / 2;
444 return atomic_read(&info->nr_async_bios) > limit; 441 return atomic_read(&info->nr_async_bios) > limit;
445} 442}
446 443
@@ -454,7 +451,7 @@ static void run_one_async_submit(struct btrfs_work *work)
454 atomic_dec(&fs_info->nr_async_submits); 451 atomic_dec(&fs_info->nr_async_submits);
455 452
456 if ((async->bio->bi_rw & (1 << BIO_RW)) && 453 if ((async->bio->bi_rw & (1 << BIO_RW)) &&
457 !congested_async(fs_info, 1)) { 454 !btrfs_congested_async(fs_info, 1)) {
458 clear_bdi_congested(&fs_info->bdi, WRITE); 455 clear_bdi_congested(&fs_info->bdi, WRITE);
459 } 456 }
460 async->submit_bio_hook(async->inode, async->rw, async->bio, 457 async->submit_bio_hook(async->inode, async->rw, async->bio,
@@ -963,7 +960,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
963 struct backing_dev_info *bdi; 960 struct backing_dev_info *bdi;
964 961
965 if ((bdi_bits & (1 << BDI_write_congested)) && 962 if ((bdi_bits & (1 << BDI_write_congested)) &&
966 congested_async(info, 0)) 963 btrfs_congested_async(info, 0))
967 return 1; 964 return 1;
968 965
969 list_for_each(cur, &info->fs_devices->devices) { 966 list_for_each(cur, &info->fs_devices->devices) {
@@ -1844,7 +1841,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
1844 struct extent_io_tree *tree; 1841 struct extent_io_tree *tree;
1845 u64 num_dirty; 1842 u64 num_dirty;
1846 u64 start = 0; 1843 u64 start = 0;
1847 unsigned long thresh = 16 * 1024 * 1024; 1844 unsigned long thresh = 2 * 1024 * 1024;
1848 tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; 1845 tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
1849 1846
1850 if (current_is_pdflush()) 1847 if (current_is_pdflush())
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 353c3c50c957..e904a69347a4 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -72,4 +72,5 @@ int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
72int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, 72int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
73 int rw, struct bio *bio, int mirror_num, 73 int rw, struct bio *bio, int mirror_num,
74 extent_submit_bio_hook_t *submit_bio_hook); 74 extent_submit_bio_hook_t *submit_bio_hook);
75int btrfs_congested_async(struct btrfs_fs_info *info, int iodone);
75#endif 76#endif
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 9d3d08e9f8d1..6bcb0876f9bb 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -303,12 +303,12 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
303 struct btrfs_root *root) 303 struct btrfs_root *root)
304{ 304{
305 int ret; 305 int ret;
306 int err; 306 int err = 0;
307 int werr = 0; 307 int werr = 0;
308 struct extent_io_tree *dirty_pages; 308 struct extent_io_tree *dirty_pages;
309 struct page *page; 309 struct page *page;
310 struct inode *btree_inode = root->fs_info->btree_inode; 310 struct inode *btree_inode = root->fs_info->btree_inode;
311 u64 start; 311 u64 start = 0;
312 u64 end; 312 u64 end;
313 unsigned long index; 313 unsigned long index;
314 314
@@ -317,12 +317,15 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
317 } 317 }
318 dirty_pages = &trans->transaction->dirty_pages; 318 dirty_pages = &trans->transaction->dirty_pages;
319 while(1) { 319 while(1) {
320 ret = find_first_extent_bit(dirty_pages, 0, &start, &end, 320 ret = find_first_extent_bit(dirty_pages, start, &start, &end,
321 EXTENT_DIRTY); 321 EXTENT_DIRTY);
322 if (ret) 322 if (ret)
323 break; 323 break;
324 clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
325 while(start <= end) { 324 while(start <= end) {
325 if (btrfs_congested_async(root->fs_info, 0))
326 congestion_wait(WRITE, HZ/10);
327 cond_resched();
328
326 index = start >> PAGE_CACHE_SHIFT; 329 index = start >> PAGE_CACHE_SHIFT;
327 start = (u64)(index + 1) << PAGE_CACHE_SHIFT; 330 start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
328 page = find_lock_page(btree_inode->i_mapping, index); 331 page = find_lock_page(btree_inode->i_mapping, index);
@@ -343,7 +346,30 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
343 page_cache_release(page); 346 page_cache_release(page);
344 } 347 }
345 } 348 }
346 err = filemap_fdatawait(btree_inode->i_mapping); 349 while(1) {
350 ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
351 EXTENT_DIRTY);
352 if (ret)
353 break;
354
355 clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
356 while(start <= end) {
357 index = start >> PAGE_CACHE_SHIFT;
358 start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
359 page = find_get_page(btree_inode->i_mapping, index);
360 if (!page)
361 continue;
362 if (PageDirty(page)) {
363 lock_page(page);
364 err = write_one_page(page, 0);
365 if (err)
366 werr = err;
367 }
368 wait_on_page_writeback(page);
369 page_cache_release(page);
370 cond_resched();
371 }
372 }
347 if (err) 373 if (err)
348 werr = err; 374 werr = err;
349 return werr; 375 return werr;