aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2012-03-13 09:38:00 -0400
committerChris Mason <chris.mason@oracle.com>2012-03-26 17:04:23 -0400
commit0b32f4bbb423f02acee6d43cd442f5f0775db7e0 (patch)
tree1963e5420071e70274bf77c05373dabd43bac675 /fs/btrfs/disk-io.c
parent5df4235ea15bd39f441ef334d8329b3d46b2cc57 (diff)
Btrfs: ensure an entire eb is written at once
This patch simplifies how we track our extent buffers. Previously we could exit writepages with only having written half of an extent buffer, which meant we had to track the state of the pages and the state of the extent buffers differently. Now we only read in entire extent buffers and write out entire extent buffers, this allows us to simply set bits in our bflags to indicate the state of the eb and we no longer have to do things like track uptodate with our iotree. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c76
1 files changed, 35 insertions, 41 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 0ba055e03eb8..c54aec87e89d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -333,7 +333,7 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
333 333
334 lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, 334 lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
335 0, &cached_state, GFP_NOFS); 335 0, &cached_state, GFP_NOFS);
336 if (extent_buffer_uptodate(io_tree, eb, cached_state) && 336 if (extent_buffer_uptodate(eb) &&
337 btrfs_header_generation(eb) == parent_transid) { 337 btrfs_header_generation(eb) == parent_transid) {
338 ret = 0; 338 ret = 0;
339 goto out; 339 goto out;
@@ -344,7 +344,7 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
344 (unsigned long long)parent_transid, 344 (unsigned long long)parent_transid,
345 (unsigned long long)btrfs_header_generation(eb)); 345 (unsigned long long)btrfs_header_generation(eb));
346 ret = 1; 346 ret = 1;
347 clear_extent_buffer_uptodate(io_tree, eb, &cached_state); 347 clear_extent_buffer_uptodate(eb);
348out: 348out:
349 unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, 349 unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
350 &cached_state, GFP_NOFS); 350 &cached_state, GFP_NOFS);
@@ -566,7 +566,12 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
566 tree = &BTRFS_I(page->mapping->host)->io_tree; 566 tree = &BTRFS_I(page->mapping->host)->io_tree;
567 eb = (struct extent_buffer *)page->private; 567 eb = (struct extent_buffer *)page->private;
568 568
569 reads_done = atomic_dec_and_test(&eb->pages_reading); 569 /* the pending IO might have been the only thing that kept this buffer
570 * in memory. Make sure we have a ref for all this other checks
571 */
572 extent_buffer_get(eb);
573
574 reads_done = atomic_dec_and_test(&eb->io_pages);
570 if (!reads_done) 575 if (!reads_done)
571 goto err; 576 goto err;
572 577
@@ -606,14 +611,17 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
606 ret = -EIO; 611 ret = -EIO;
607 } 612 }
608 613
614 if (!ret)
615 set_extent_buffer_uptodate(eb);
609err: 616err:
610 if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { 617 if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
611 clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); 618 clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
612 btree_readahead_hook(root, eb, eb->start, ret); 619 btree_readahead_hook(root, eb, eb->start, ret);
613 } 620 }
614 621
615 if (ret && eb) 622 if (ret)
616 clear_extent_buffer_uptodate(tree, eb, NULL); 623 clear_extent_buffer_uptodate(eb);
624 free_extent_buffer(eb);
617out: 625out:
618 return ret; 626 return ret;
619} 627}
@@ -878,20 +886,6 @@ static int btree_migratepage(struct address_space *mapping,
878} 886}
879#endif 887#endif
880 888
881static int btree_writepage(struct page *page, struct writeback_control *wbc)
882{
883 struct extent_io_tree *tree;
884 tree = &BTRFS_I(page->mapping->host)->io_tree;
885
886 if (!(current->flags & PF_MEMALLOC)) {
887 return extent_write_full_page(tree, page,
888 btree_get_extent, wbc);
889 }
890
891 redirty_page_for_writepage(wbc, page);
892 unlock_page(page);
893 return 0;
894}
895 889
896static int btree_writepages(struct address_space *mapping, 890static int btree_writepages(struct address_space *mapping,
897 struct writeback_control *wbc) 891 struct writeback_control *wbc)
@@ -911,7 +905,7 @@ static int btree_writepages(struct address_space *mapping,
911 if (num_dirty < thresh) 905 if (num_dirty < thresh)
912 return 0; 906 return 0;
913 } 907 }
914 return extent_writepages(tree, mapping, btree_get_extent, wbc); 908 return btree_write_cache_pages(mapping, wbc);
915} 909}
916 910
917static int btree_readpage(struct file *file, struct page *page) 911static int btree_readpage(struct file *file, struct page *page)
@@ -950,15 +944,28 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
950 } 944 }
951} 945}
952 946
947static int btree_set_page_dirty(struct page *page)
948{
949 struct extent_buffer *eb;
950
951 BUG_ON(!PagePrivate(page));
952 eb = (struct extent_buffer *)page->private;
953 BUG_ON(!eb);
954 BUG_ON(!test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
955 BUG_ON(!atomic_read(&eb->refs));
956 btrfs_assert_tree_locked(eb);
957 return __set_page_dirty_nobuffers(page);
958}
959
953static const struct address_space_operations btree_aops = { 960static const struct address_space_operations btree_aops = {
954 .readpage = btree_readpage, 961 .readpage = btree_readpage,
955 .writepage = btree_writepage,
956 .writepages = btree_writepages, 962 .writepages = btree_writepages,
957 .releasepage = btree_releasepage, 963 .releasepage = btree_releasepage,
958 .invalidatepage = btree_invalidatepage, 964 .invalidatepage = btree_invalidatepage,
959#ifdef CONFIG_MIGRATION 965#ifdef CONFIG_MIGRATION
960 .migratepage = btree_migratepage, 966 .migratepage = btree_migratepage,
961#endif 967#endif
968 .set_page_dirty = btree_set_page_dirty,
962}; 969};
963 970
964int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, 971int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
@@ -1001,7 +1008,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, u32 blocksize,
1001 if (test_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags)) { 1008 if (test_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags)) {
1002 free_extent_buffer(buf); 1009 free_extent_buffer(buf);
1003 return -EIO; 1010 return -EIO;
1004 } else if (extent_buffer_uptodate(io_tree, buf, NULL)) { 1011 } else if (extent_buffer_uptodate(buf)) {
1005 *eb = buf; 1012 *eb = buf;
1006 } else { 1013 } else {
1007 free_extent_buffer(buf); 1014 free_extent_buffer(buf);
@@ -1054,9 +1061,6 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
1054 return NULL; 1061 return NULL;
1055 1062
1056 ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); 1063 ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
1057
1058 if (ret == 0)
1059 set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
1060 return buf; 1064 return buf;
1061 1065
1062} 1066}
@@ -1064,7 +1068,6 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
1064int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 1068int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1065 struct extent_buffer *buf) 1069 struct extent_buffer *buf)
1066{ 1070{
1067 struct inode *btree_inode = root->fs_info->btree_inode;
1068 if (btrfs_header_generation(buf) == 1071 if (btrfs_header_generation(buf) ==
1069 root->fs_info->running_transaction->transid) { 1072 root->fs_info->running_transaction->transid) {
1070 btrfs_assert_tree_locked(buf); 1073 btrfs_assert_tree_locked(buf);
@@ -1080,8 +1083,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1080 1083
1081 /* ugh, clear_extent_buffer_dirty needs to lock the page */ 1084 /* ugh, clear_extent_buffer_dirty needs to lock the page */
1082 btrfs_set_lock_blocking(buf); 1085 btrfs_set_lock_blocking(buf);
1083 clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, 1086 clear_extent_buffer_dirty(buf);
1084 buf);
1085 } 1087 }
1086 return 0; 1088 return 0;
1087} 1089}
@@ -1948,6 +1950,7 @@ int open_ctree(struct super_block *sb,
1948 RB_CLEAR_NODE(&BTRFS_I(fs_info->btree_inode)->rb_node); 1950 RB_CLEAR_NODE(&BTRFS_I(fs_info->btree_inode)->rb_node);
1949 extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree, 1951 extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree,
1950 fs_info->btree_inode->i_mapping); 1952 fs_info->btree_inode->i_mapping);
1953 BTRFS_I(fs_info->btree_inode)->io_tree.track_uptodate = 0;
1951 extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree); 1954 extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree);
1952 1955
1953 BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; 1956 BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops;
@@ -3058,8 +3061,7 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
3058 int ret; 3061 int ret;
3059 struct inode *btree_inode = buf->pages[0]->mapping->host; 3062 struct inode *btree_inode = buf->pages[0]->mapping->host;
3060 3063
3061 ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf, 3064 ret = extent_buffer_uptodate(buf);
3062 NULL);
3063 if (!ret) 3065 if (!ret)
3064 return ret; 3066 return ret;
3065 3067
@@ -3070,16 +3072,13 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
3070 3072
3071int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 3073int btrfs_set_buffer_uptodate(struct extent_buffer *buf)
3072{ 3074{
3073 struct inode *btree_inode = buf->pages[0]->mapping->host; 3075 return set_extent_buffer_uptodate(buf);
3074 return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree,
3075 buf);
3076} 3076}
3077 3077
3078void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 3078void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
3079{ 3079{
3080 struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root; 3080 struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root;
3081 u64 transid = btrfs_header_generation(buf); 3081 u64 transid = btrfs_header_generation(buf);
3082 struct inode *btree_inode = root->fs_info->btree_inode;
3083 int was_dirty; 3082 int was_dirty;
3084 3083
3085 btrfs_assert_tree_locked(buf); 3084 btrfs_assert_tree_locked(buf);
@@ -3091,8 +3090,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
3091 (unsigned long long)root->fs_info->generation); 3090 (unsigned long long)root->fs_info->generation);
3092 WARN_ON(1); 3091 WARN_ON(1);
3093 } 3092 }
3094 was_dirty = set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, 3093 was_dirty = set_extent_buffer_dirty(buf);
3095 buf);
3096 if (!was_dirty) { 3094 if (!was_dirty) {
3097 spin_lock(&root->fs_info->delalloc_lock); 3095 spin_lock(&root->fs_info->delalloc_lock);
3098 root->fs_info->dirty_metadata_bytes += buf->len; 3096 root->fs_info->dirty_metadata_bytes += buf->len;
@@ -3147,11 +3145,7 @@ void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
3147int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) 3145int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
3148{ 3146{
3149 struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root; 3147 struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root;
3150 int ret; 3148 return btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
3151 ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
3152 if (ret == 0)
3153 set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
3154 return ret;
3155} 3149}
3156 3150
3157static int btree_lock_page_hook(struct page *page, void *data, 3151static int btree_lock_page_hook(struct page *page, void *data,