diff options
-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; |