aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-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;