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, ...@@ -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 = min_t(u64, eb->len, PAGE_CACHE_SIZE);
end = eb->start + end - 1; end = eb->start + end - 1;
release_extent_buffer_tail_pages(eb);
err: err:
free_extent_buffer(eb); free_extent_buffer(eb);
out: out:
...@@ -563,21 +562,21 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags) ...@@ -563,21 +562,21 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags)
struct extent_map_tree *map; struct extent_map_tree *map;
int ret; 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; tree = &BTRFS_I(page->mapping->host)->io_tree;
map = &BTRFS_I(page->mapping->host)->extent_tree; map = &BTRFS_I(page->mapping->host)->extent_tree;
ret = try_release_extent_state(map, tree, page, gfp_flags); ret = try_release_extent_state(map, tree, page, gfp_flags);
if (!ret) {
return 0;
}
ret = try_release_extent_buffer(tree, page);
if (ret == 1) { if (ret == 1) {
invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
ClearPagePrivate(page); ClearPagePrivate(page);
set_page_private(page, 0); set_page_private(page, 0);
page_cache_release(page); page_cache_release(page);
} }
return ret; return ret;
} }
...@@ -588,7 +587,8 @@ static void btree_invalidatepage(struct page *page, unsigned long offset) ...@@ -588,7 +587,8 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
extent_invalidatepage(tree, page, offset); extent_invalidatepage(tree, page, offset);
btree_releasepage(page, GFP_NOFS); btree_releasepage(page, GFP_NOFS);
if (PagePrivate(page)) { 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); ClearPagePrivate(page);
set_page_private(page, 0); set_page_private(page, 0);
page_cache_release(page); page_cache_release(page);
...@@ -1456,7 +1456,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1456,7 +1456,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
free_extent_buffer(tree_root->node); free_extent_buffer(tree_root->node);
fail_sys_array: fail_sys_array:
fail_sb_buffer: 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->fixup_workers);
btrfs_stop_workers(&fs_info->workers); btrfs_stop_workers(&fs_info->workers);
btrfs_stop_workers(&fs_info->endio_workers); btrfs_stop_workers(&fs_info->endio_workers);
...@@ -1705,13 +1704,6 @@ int close_ctree(struct btrfs_root *root) ...@@ -1705,13 +1704,6 @@ int close_ctree(struct btrfs_root *root)
filemap_write_and_wait(fs_info->btree_inode->i_mapping); 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); truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
btrfs_stop_workers(&fs_info->fixup_workers); btrfs_stop_workers(&fs_info->fixup_workers);
......
This diff is collapsed.
...@@ -54,13 +54,12 @@ struct extent_io_ops { ...@@ -54,13 +54,12 @@ struct extent_io_ops {
struct extent_io_tree { struct extent_io_tree {
struct rb_root state; struct rb_root state;
struct rb_root buffer;
struct address_space *mapping; struct address_space *mapping;
u64 dirty_bytes; u64 dirty_bytes;
spinlock_t lock; spinlock_t lock;
spinlock_t buffer_lock;
struct extent_io_ops *ops; struct extent_io_ops *ops;
spinlock_t lru_lock;
struct list_head buffer_lru;
int lru_size;
struct extent_state *last; struct extent_state *last;
}; };
...@@ -87,10 +86,10 @@ struct extent_buffer { ...@@ -87,10 +86,10 @@ struct extent_buffer {
unsigned long map_start; unsigned long map_start;
unsigned long map_len; unsigned long map_len;
struct page *first_page; struct page *first_page;
struct list_head lru;
atomic_t refs; atomic_t refs;
int flags; int flags;
struct list_head leak_list; struct list_head leak_list;
struct rb_node rb_node;
}; };
struct extent_map_tree; struct extent_map_tree;
...@@ -112,10 +111,10 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode, ...@@ -112,10 +111,10 @@ typedef struct extent_map *(get_extent_t)(struct inode *inode,
void extent_io_tree_init(struct extent_io_tree *tree, void extent_io_tree_init(struct extent_io_tree *tree,
struct address_space *mapping, gfp_t mask); 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, int try_release_extent_mapping(struct extent_map_tree *map,
struct extent_io_tree *tree, struct page *page, struct extent_io_tree *tree, struct page *page,
gfp_t mask); 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, int try_release_extent_state(struct extent_map_tree *map,
struct extent_io_tree *tree, struct page *page, struct extent_io_tree *tree, struct page *page,
gfp_t mask); gfp_t mask);
...@@ -241,8 +240,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, ...@@ -241,8 +240,6 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
unsigned long *map_start, unsigned long *map_start,
unsigned long *map_len, int km); unsigned long *map_len, int km);
void unmap_extent_buffer(struct extent_buffer *eb, char *token, 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 release_extent_buffer_tail_pages(struct extent_buffer *eb);
int extent_range_uptodate(struct extent_io_tree *tree, int extent_range_uptodate(struct extent_io_tree *tree,
u64 start, u64 end); u64 start, u64 end);
......
...@@ -2670,7 +2670,6 @@ static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags) ...@@ -2670,7 +2670,6 @@ static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags)
map = &BTRFS_I(page->mapping->host)->extent_tree; map = &BTRFS_I(page->mapping->host)->extent_tree;
ret = try_release_extent_mapping(map, tree, page, gfp_flags); ret = try_release_extent_mapping(map, tree, page, gfp_flags);
if (ret == 1) { if (ret == 1) {
invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
ClearPagePrivate(page); ClearPagePrivate(page);
set_page_private(page, 0); set_page_private(page, 0);
page_cache_release(page); page_cache_release(page);
...@@ -2721,8 +2720,6 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) ...@@ -2721,8 +2720,6 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
ClearPageChecked(page); ClearPageChecked(page);
if (PagePrivate(page)) { if (PagePrivate(page)) {
invalidate_extent_lru(tree, page_offset(page),
PAGE_CACHE_SIZE);
ClearPagePrivate(page); ClearPagePrivate(page);
set_page_private(page, 0); set_page_private(page, 0);
page_cache_release(page); 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