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