Commit 6af118ce authored by Chris Mason's avatar Chris Mason

Btrfs: Index extent buffers in an rbtree

Before, extent buffers were a temporary object, meant to map a number of pages
at once and collect operations on them.

But, a few extra fields have crept in, and they are also the best place to
store a per-tree block lock field as well.  This commit puts the extent
buffers into an rbtree, and ensures a single extent buffer for each
tree block.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 4a096752
......@@ -381,7 +381,6 @@ int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
end = eb->start + end - 1;
release_extent_buffer_tail_pages(eb);
err:
free_extent_buffer(eb);
out:
......@@ -563,21 +562,21 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags)
struct extent_map_tree *map;
int ret;
if (page_count(page) > 3) {
/* once for page->private, once for the caller, once
* once for the page cache
*/
return 0;
}
tree = &BTRFS_I(page->mapping->host)->io_tree;
map = &BTRFS_I(page->mapping->host)->extent_tree;
ret = try_release_extent_state(map, tree, page, gfp_flags);
if (!ret) {
return 0;
}
ret = try_release_extent_buffer(tree, page);
if (ret == 1) {
invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
ClearPagePrivate(page);
set_page_private(page, 0);
page_cache_release(page);
}
return ret;
}
......@@ -588,7 +587,8 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
extent_invalidatepage(tree, page, offset);
btree_releasepage(page, GFP_NOFS);
if (PagePrivate(page)) {
invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
printk("warning page private not zero on page %Lu\n",
page_offset(page));
ClearPagePrivate(page);
set_page_private(page, 0);
page_cache_release(page);
......@@ -1456,7 +1456,6 @@ fail_tree_root:
free_extent_buffer(tree_root->node);
fail_sys_array:
fail_sb_buffer:
extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
btrfs_stop_workers(&fs_info->fixup_workers);
btrfs_stop_workers(&fs_info->workers);
btrfs_stop_workers(&fs_info->endio_workers);
......@@ -1705,13 +1704,6 @@ int close_ctree(struct btrfs_root *root)
filemap_write_and_wait(fs_info->btree_inode->i_mapping);
extent_io_tree_empty_lru(&fs_info->free_space_cache);
extent_io_tree_empty_lru(&fs_info->block_group_cache);
extent_io_tree_empty_lru(&fs_info->pinned_extents);
extent_io_tree_empty_lru(&fs_info->pending_del);
extent_io_tree_empty_lru(&fs_info->extent_ins);
extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
btrfs_stop_workers(&fs_info->fixup_workers);
......
This diff is collapsed.
......@@ -54,13 +54,12 @@ struct extent_io_ops {
struct extent_io_tree {
struct rb_root state;
struct rb_root buffer;
struct address_space *mapping;
u64 dirty_bytes;
spinlock_t lock;
spinlock_t buffer_lock;
struct extent_io_ops *ops;
spinlock_t lru_lock;
struct list_head buffer_lru;
int lru_size;
struct extent_state *last;
};
......@@ -87,10 +86,10 @@ struct extent_buffer {
unsigned long map_start;
unsigned long map_len;
struct page *first_page;
struct list_head lru;
atomic_t refs;
int flags;
struct list_head leak_list;
struct rb_node rb_node;
};
struct extent_map_tree;
......@@ -112,10 +111,10 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode,
void extent_io_tree_init(struct extent_io_tree *tree,
struct address_space *mapping, gfp_t mask);
void extent_io_tree_empty_lru(struct extent_io_tree *tree);
int try_release_extent_mapping(struct extent_map_tree *map,
struct extent_io_tree *tree, struct page *page,
gfp_t mask);
int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page);
int try_release_extent_state(struct extent_map_tree *map,
struct extent_io_tree *tree, struct page *page,
gfp_t mask);
......@@ -241,8 +240,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
unsigned long *map_start,
unsigned long *map_len, int km);
void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);
int invalidate_extent_lru(struct extent_io_tree *tree, u64 start,
unsigned long len);
int release_extent_buffer_tail_pages(struct extent_buffer *eb);
int extent_range_uptodate(struct extent_io_tree *tree,
u64 start, u64 end);
......
......@@ -2670,7 +2670,6 @@ static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags)
map = &BTRFS_I(page->mapping->host)->extent_tree;
ret = try_release_extent_mapping(map, tree, page, gfp_flags);
if (ret == 1) {
invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
ClearPagePrivate(page);
set_page_private(page, 0);
page_cache_release(page);
......@@ -2721,8 +2720,6 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
ClearPageChecked(page);
if (PagePrivate(page)) {
invalidate_extent_lru(tree, page_offset(page),
PAGE_CACHE_SIZE);
ClearPagePrivate(page);
set_page_private(page, 0);
page_cache_release(page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment