diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-08-15 15:34:15 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | 777e6bd706ee40897545463871de5b456fbc46dc (patch) | |
tree | cb927528e02234eb7fa6b5d1f14b9367efd755b6 | |
parent | 0986fe9eac24fd186927c3b87af51d62f8ab92cd (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.c | 11 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 36 |
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 | ||
432 | static int congested_async(struct btrfs_fs_info *info, int iodone) | 432 | int 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, | |||
72 | int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, | 72 | int 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); |
75 | int 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; |