diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6ec80c0fc869..92d73929d381 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -668,14 +668,31 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
668 | static int btree_writepage(struct page *page, struct writeback_control *wbc) | 668 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
669 | { | 669 | { |
670 | struct extent_io_tree *tree; | 670 | struct extent_io_tree *tree; |
671 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; | ||
672 | struct extent_buffer *eb; | ||
673 | int was_dirty; | ||
674 | |||
671 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 675 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
676 | if (!(current->flags & PF_MEMALLOC)) { | ||
677 | return extent_write_full_page(tree, page, | ||
678 | btree_get_extent, wbc); | ||
679 | } | ||
672 | 680 | ||
673 | if (current->flags & PF_MEMALLOC) { | 681 | redirty_page_for_writepage(wbc, page); |
674 | redirty_page_for_writepage(wbc, page); | 682 | eb = btrfs_find_tree_block(root, page_offset(page), |
675 | unlock_page(page); | 683 | PAGE_CACHE_SIZE); |
676 | return 0; | 684 | WARN_ON(!eb); |
685 | |||
686 | was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); | ||
687 | if (!was_dirty) { | ||
688 | spin_lock(&root->fs_info->delalloc_lock); | ||
689 | root->fs_info->dirty_metadata_bytes += PAGE_CACHE_SIZE; | ||
690 | spin_unlock(&root->fs_info->delalloc_lock); | ||
677 | } | 691 | } |
678 | return extent_write_full_page(tree, page, btree_get_extent, wbc); | 692 | free_extent_buffer(eb); |
693 | |||
694 | unlock_page(page); | ||
695 | return 0; | ||
679 | } | 696 | } |
680 | 697 | ||
681 | static int btree_writepages(struct address_space *mapping, | 698 | static int btree_writepages(struct address_space *mapping, |
@@ -684,15 +701,15 @@ static int btree_writepages(struct address_space *mapping, | |||
684 | struct extent_io_tree *tree; | 701 | struct extent_io_tree *tree; |
685 | tree = &BTRFS_I(mapping->host)->io_tree; | 702 | tree = &BTRFS_I(mapping->host)->io_tree; |
686 | if (wbc->sync_mode == WB_SYNC_NONE) { | 703 | if (wbc->sync_mode == WB_SYNC_NONE) { |
704 | struct btrfs_root *root = BTRFS_I(mapping->host)->root; | ||
687 | u64 num_dirty; | 705 | u64 num_dirty; |
688 | u64 start = 0; | ||
689 | unsigned long thresh = 32 * 1024 * 1024; | 706 | unsigned long thresh = 32 * 1024 * 1024; |
690 | 707 | ||
691 | if (wbc->for_kupdate) | 708 | if (wbc->for_kupdate) |
692 | return 0; | 709 | return 0; |
693 | 710 | ||
694 | num_dirty = count_range_bits(tree, &start, (u64)-1, | 711 | /* this is a bit racy, but that's ok */ |
695 | thresh, EXTENT_DIRTY); | 712 | num_dirty = root->fs_info->dirty_metadata_bytes; |
696 | if (num_dirty < thresh) | 713 | if (num_dirty < thresh) |
697 | return 0; | 714 | return 0; |
698 | } | 715 | } |
@@ -859,9 +876,17 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
859 | root->fs_info->running_transaction->transid) { | 876 | root->fs_info->running_transaction->transid) { |
860 | btrfs_assert_tree_locked(buf); | 877 | btrfs_assert_tree_locked(buf); |
861 | 878 | ||
862 | /* ugh, clear_extent_buffer_dirty can be expensive */ | 879 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)) { |
863 | btrfs_set_lock_blocking(buf); | 880 | spin_lock(&root->fs_info->delalloc_lock); |
881 | if (root->fs_info->dirty_metadata_bytes >= buf->len) | ||
882 | root->fs_info->dirty_metadata_bytes -= buf->len; | ||
883 | else | ||
884 | WARN_ON(1); | ||
885 | spin_unlock(&root->fs_info->delalloc_lock); | ||
886 | } | ||
864 | 887 | ||
888 | /* ugh, clear_extent_buffer_dirty needs to lock the page */ | ||
889 | btrfs_set_lock_blocking(buf); | ||
865 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, | 890 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, |
866 | buf); | 891 | buf); |
867 | } | 892 | } |
@@ -1471,12 +1496,6 @@ static int transaction_kthread(void *arg) | |||
1471 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); | 1496 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); |
1472 | mutex_lock(&root->fs_info->transaction_kthread_mutex); | 1497 | mutex_lock(&root->fs_info->transaction_kthread_mutex); |
1473 | 1498 | ||
1474 | if (root->fs_info->total_ref_cache_size > 20 * 1024 * 1024) { | ||
1475 | printk(KERN_INFO "btrfs: total reference cache " | ||
1476 | "size %llu\n", | ||
1477 | root->fs_info->total_ref_cache_size); | ||
1478 | } | ||
1479 | |||
1480 | mutex_lock(&root->fs_info->trans_mutex); | 1499 | mutex_lock(&root->fs_info->trans_mutex); |
1481 | cur = root->fs_info->running_transaction; | 1500 | cur = root->fs_info->running_transaction; |
1482 | if (!cur) { | 1501 | if (!cur) { |
@@ -1493,6 +1512,7 @@ static int transaction_kthread(void *arg) | |||
1493 | mutex_unlock(&root->fs_info->trans_mutex); | 1512 | mutex_unlock(&root->fs_info->trans_mutex); |
1494 | trans = btrfs_start_transaction(root, 1); | 1513 | trans = btrfs_start_transaction(root, 1); |
1495 | ret = btrfs_commit_transaction(trans, root); | 1514 | ret = btrfs_commit_transaction(trans, root); |
1515 | |||
1496 | sleep: | 1516 | sleep: |
1497 | wake_up_process(root->fs_info->cleaner_kthread); | 1517 | wake_up_process(root->fs_info->cleaner_kthread); |
1498 | mutex_unlock(&root->fs_info->transaction_kthread_mutex); | 1518 | mutex_unlock(&root->fs_info->transaction_kthread_mutex); |
@@ -1552,6 +1572,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1552 | INIT_LIST_HEAD(&fs_info->dead_roots); | 1572 | INIT_LIST_HEAD(&fs_info->dead_roots); |
1553 | INIT_LIST_HEAD(&fs_info->hashers); | 1573 | INIT_LIST_HEAD(&fs_info->hashers); |
1554 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); | 1574 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); |
1575 | INIT_LIST_HEAD(&fs_info->ordered_operations); | ||
1555 | spin_lock_init(&fs_info->delalloc_lock); | 1576 | spin_lock_init(&fs_info->delalloc_lock); |
1556 | spin_lock_init(&fs_info->new_trans_lock); | 1577 | spin_lock_init(&fs_info->new_trans_lock); |
1557 | spin_lock_init(&fs_info->ref_cache_lock); | 1578 | spin_lock_init(&fs_info->ref_cache_lock); |
@@ -1611,10 +1632,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1611 | 1632 | ||
1612 | extent_io_tree_init(&fs_info->pinned_extents, | 1633 | extent_io_tree_init(&fs_info->pinned_extents, |
1613 | fs_info->btree_inode->i_mapping, GFP_NOFS); | 1634 | fs_info->btree_inode->i_mapping, GFP_NOFS); |
1614 | extent_io_tree_init(&fs_info->pending_del, | ||
1615 | fs_info->btree_inode->i_mapping, GFP_NOFS); | ||
1616 | extent_io_tree_init(&fs_info->extent_ins, | ||
1617 | fs_info->btree_inode->i_mapping, GFP_NOFS); | ||
1618 | fs_info->do_barriers = 1; | 1635 | fs_info->do_barriers = 1; |
1619 | 1636 | ||
1620 | INIT_LIST_HEAD(&fs_info->dead_reloc_roots); | 1637 | INIT_LIST_HEAD(&fs_info->dead_reloc_roots); |
@@ -1627,9 +1644,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1627 | insert_inode_hash(fs_info->btree_inode); | 1644 | insert_inode_hash(fs_info->btree_inode); |
1628 | 1645 | ||
1629 | mutex_init(&fs_info->trans_mutex); | 1646 | mutex_init(&fs_info->trans_mutex); |
1647 | mutex_init(&fs_info->ordered_operations_mutex); | ||
1630 | mutex_init(&fs_info->tree_log_mutex); | 1648 | mutex_init(&fs_info->tree_log_mutex); |
1631 | mutex_init(&fs_info->drop_mutex); | 1649 | mutex_init(&fs_info->drop_mutex); |
1632 | mutex_init(&fs_info->extent_ins_mutex); | ||
1633 | mutex_init(&fs_info->pinned_mutex); | 1650 | mutex_init(&fs_info->pinned_mutex); |
1634 | mutex_init(&fs_info->chunk_mutex); | 1651 | mutex_init(&fs_info->chunk_mutex); |
1635 | mutex_init(&fs_info->transaction_kthread_mutex); | 1652 | mutex_init(&fs_info->transaction_kthread_mutex); |
@@ -2358,8 +2375,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
2358 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; | 2375 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; |
2359 | u64 transid = btrfs_header_generation(buf); | 2376 | u64 transid = btrfs_header_generation(buf); |
2360 | struct inode *btree_inode = root->fs_info->btree_inode; | 2377 | struct inode *btree_inode = root->fs_info->btree_inode; |
2361 | 2378 | int was_dirty; | |
2362 | btrfs_set_lock_blocking(buf); | ||
2363 | 2379 | ||
2364 | btrfs_assert_tree_locked(buf); | 2380 | btrfs_assert_tree_locked(buf); |
2365 | if (transid != root->fs_info->generation) { | 2381 | if (transid != root->fs_info->generation) { |
@@ -2370,7 +2386,13 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
2370 | (unsigned long long)root->fs_info->generation); | 2386 | (unsigned long long)root->fs_info->generation); |
2371 | WARN_ON(1); | 2387 | WARN_ON(1); |
2372 | } | 2388 | } |
2373 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); | 2389 | was_dirty = set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, |
2390 | buf); | ||
2391 | if (!was_dirty) { | ||
2392 | spin_lock(&root->fs_info->delalloc_lock); | ||
2393 | root->fs_info->dirty_metadata_bytes += buf->len; | ||
2394 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2395 | } | ||
2374 | } | 2396 | } |
2375 | 2397 | ||
2376 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) | 2398 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) |
@@ -2410,6 +2432,7 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) | |||
2410 | int btree_lock_page_hook(struct page *page) | 2432 | int btree_lock_page_hook(struct page *page) |
2411 | { | 2433 | { |
2412 | struct inode *inode = page->mapping->host; | 2434 | struct inode *inode = page->mapping->host; |
2435 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2413 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 2436 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
2414 | struct extent_buffer *eb; | 2437 | struct extent_buffer *eb; |
2415 | unsigned long len; | 2438 | unsigned long len; |
@@ -2425,6 +2448,16 @@ int btree_lock_page_hook(struct page *page) | |||
2425 | 2448 | ||
2426 | btrfs_tree_lock(eb); | 2449 | btrfs_tree_lock(eb); |
2427 | btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); | 2450 | btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); |
2451 | |||
2452 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { | ||
2453 | spin_lock(&root->fs_info->delalloc_lock); | ||
2454 | if (root->fs_info->dirty_metadata_bytes >= eb->len) | ||
2455 | root->fs_info->dirty_metadata_bytes -= eb->len; | ||
2456 | else | ||
2457 | WARN_ON(1); | ||
2458 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2459 | } | ||
2460 | |||
2428 | btrfs_tree_unlock(eb); | 2461 | btrfs_tree_unlock(eb); |
2429 | free_extent_buffer(eb); | 2462 | free_extent_buffer(eb); |
2430 | out: | 2463 | out: |