diff options
author | Josef Bacik <josef@redhat.com> | 2012-03-07 16:20:05 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-03-26 16:51:07 -0400 |
commit | 4f2de97acee6532b36dd6e995b858343771ad126 (patch) | |
tree | 240ee16e76f2f2e4850e6fe2e90174e7cd794a9b /fs/btrfs/disk-io.c | |
parent | 727011e07cbdf87772fcc1999cccd15cc915eb62 (diff) | |
download | linux-3.10-4f2de97acee6532b36dd6e995b858343771ad126.tar.gz linux-3.10-4f2de97acee6532b36dd6e995b858343771ad126.tar.bz2 linux-3.10-4f2de97acee6532b36dd6e995b858343771ad126.zip |
Btrfs: set page->private to the eb
We spend a lot of time looking up extent buffers from pages when we could just
store the pointer to the eb the page is associated with in page->private. This
patch does just that, and it makes things a little simpler and reduces a bit of
CPU overhead involved with doing metadata IO. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 91 |
1 files changed, 23 insertions, 68 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 68fc93e18db..bc88649cffb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -403,39 +403,28 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page) struct extent_io_tree *tree; u64 start = (u64)page->index << PAGE_CACHE_SHIFT; u64 found_start; - unsigned long len; struct extent_buffer *eb; tree = &BTRFS_I(page->mapping->host)->io_tree; - if (page->private == EXTENT_PAGE_PRIVATE) - goto out; - if (!page->private) { - WARN_ON(1); - goto out; - } - len = page->private >> 2; - WARN_ON(len == 0); - - eb = find_extent_buffer(tree, start, len); + eb = (struct extent_buffer *)page->private; + if (page != eb->pages[0]) + return 0; found_start = btrfs_header_bytenr(eb); if (found_start != start) { WARN_ON(1); - goto err; + return 0; } if (eb->pages[0] != page) { WARN_ON(1); - goto err; + return 0; } if (!PageUptodate(page)) { WARN_ON(1); - goto err; + return 0; } csum_tree_block(root, eb, 0); -err: - free_extent_buffer(eb); -out: return 0; } @@ -566,7 +555,6 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, struct extent_io_tree *tree; u64 found_start; int found_level; - unsigned long len; struct extent_buffer *eb; struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; int ret = 0; @@ -576,13 +564,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, goto out; tree = &BTRFS_I(page->mapping->host)->io_tree; - len = page->private >> 2; + eb = (struct extent_buffer *)page->private; - eb = find_eb_for_page(tree, page, max(root->leafsize, root->nodesize)); - if (!eb) { - ret = -EIO; - goto out; - } reads_done = atomic_dec_and_test(&eb->pages_reading); if (!reads_done) goto err; @@ -631,7 +614,6 @@ err: if (ret && eb) clear_extent_buffer_uptodate(tree, eb, NULL); - free_extent_buffer(eb); out: return ret; } @@ -640,31 +622,17 @@ static int btree_io_failed_hook(struct bio *failed_bio, struct page *page, u64 start, u64 end, int mirror_num, struct extent_state *state) { - struct extent_io_tree *tree; - unsigned long len; struct extent_buffer *eb; struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; - tree = &BTRFS_I(page->mapping->host)->io_tree; - if (page->private == EXTENT_PAGE_PRIVATE) - goto out; - if (!page->private) - goto out; - - len = page->private >> 2; - WARN_ON(len == 0); - - eb = alloc_extent_buffer(tree, start, len); - if (eb == NULL) - goto out; + eb = (struct extent_buffer *)page->private; + if (page != eb->pages[0]) + return -EIO; if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); btree_readahead_hook(root, eb, eb->start, -EIO); } - free_extent_buffer(eb); - -out: return -EIO; /* we fixed nothing */ } @@ -955,10 +923,8 @@ static int btree_readpage(struct file *file, struct page *page) static int btree_releasepage(struct page *page, gfp_t gfp_flags) { - struct extent_io_tree *tree; struct extent_map_tree *map; - struct extent_buffer *eb; - struct btrfs_root *root; + struct extent_io_tree *tree; int ret; if (PageWriteback(page) || PageDirty(page)) @@ -967,13 +933,6 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags) tree = &BTRFS_I(page->mapping->host)->io_tree; map = &BTRFS_I(page->mapping->host)->extent_tree; - root = BTRFS_I(page->mapping->host)->root; - if (page->private == EXTENT_PAGE_PRIVATE) { - eb = find_eb_for_page(tree, page, max(root->leafsize, root->nodesize)); - free_extent_buffer(eb); - if (eb) - return 0; - } /* * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing * slab allocation from alloc_extent_state down the callchain where @@ -985,14 +944,7 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags) if (!ret) return 0; - ret = try_release_extent_buffer(tree, page); - if (ret == 1) { - ClearPagePrivate(page); - set_page_private(page, 0); - page_cache_release(page); - } - - return ret; + return try_release_extent_buffer(tree, page); } static void btree_invalidatepage(struct page *page, unsigned long offset) @@ -3219,17 +3171,21 @@ static int btree_lock_page_hook(struct page *page, void *data, { struct inode *inode = page->mapping->host; struct btrfs_root *root = BTRFS_I(inode)->root; - struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_buffer *eb; - unsigned long len; - u64 bytenr = page_offset(page); - if (page->private == EXTENT_PAGE_PRIVATE) + /* + * We culled this eb but the page is still hanging out on the mapping, + * carry on. + */ + if (!PagePrivate(page)) goto out; - len = page->private >> 2; - eb = find_extent_buffer(io_tree, bytenr, len); - if (!eb) + eb = (struct extent_buffer *)page->private; + if (!eb) { + WARN_ON(1); + goto out; + } + if (page != eb->pages[0]) goto out; if (!btrfs_try_tree_write_lock(eb)) { @@ -3248,7 +3204,6 @@ static int btree_lock_page_hook(struct page *page, void *data, } btrfs_tree_unlock(eb); - free_extent_buffer(eb); out: if (!trylock_page(page)) { flush_fn(data); |