Commit 810191ff authored by Chris Mason's avatar Chris Mason

Btrfs: extent_map optimizations to cut down on CPU usage

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3326d1b0
...@@ -463,6 +463,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, ...@@ -463,6 +463,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
static int check_block(struct btrfs_root *root, struct btrfs_path *path, static int check_block(struct btrfs_root *root, struct btrfs_path *path,
int level) int level)
{ {
return 0;
#if 0 #if 0
struct extent_buffer *buf = path->nodes[level]; struct extent_buffer *buf = path->nodes[level];
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#ifndef __BTRFS__ #ifndef __BTRFS__
#define __BTRFS__ #define __BTRFS__
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -499,70 +501,22 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \ ...@@ -499,70 +501,22 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
static inline u##bits btrfs_##name(struct extent_buffer *eb) \ static inline u##bits btrfs_##name(struct extent_buffer *eb) \
{ \ { \
int err; \ char *kaddr = kmap_atomic(eb->first_page, KM_USER0); \
char *map_token; \
char *kaddr; \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \ unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \ u##bits res; \
if (eb->map_token && offset >= eb->map_start && \ __le##bits *tmp = (__le##bits *)(kaddr + offset); \
offset + sizeof(((type *)0)->member) <= eb->map_start + \ res = le##bits##_to_cpu(*tmp); \
eb->map_len) { \ kunmap_atomic(kaddr, KM_USER0); \
kaddr = eb->kaddr; \ return res; \
map_start = eb->map_start; \
err = 0; \
} else { \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER1); \
} \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
u##bits res = le##bits##_to_cpu(*tmp); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
return res; \
} else { \
__le##bits res; \
read_eb_member(eb, NULL, type, member, &res); \
return le##bits##_to_cpu(res); \
} \
} \ } \
static inline void btrfs_set_##name(struct extent_buffer *eb, \ static inline void btrfs_set_##name(struct extent_buffer *eb, \
u##bits val) \ u##bits val) \
{ \ { \
int err; \ char *kaddr = kmap_atomic(eb->first_page, KM_USER0); \
char *map_token; \
char *kaddr; \
unsigned long map_start; \
unsigned long map_len; \
unsigned long offset = offsetof(type, member); \ unsigned long offset = offsetof(type, member); \
int unmap_on_exit = (eb->map_token == NULL); \ __le##bits *tmp = (__le##bits *)(kaddr + offset); \
if (eb->map_token && offset >= eb->map_start && \ *tmp = cpu_to_le##bits(val); \
offset + sizeof(((type *)0)->member) <= eb->map_start + \ kunmap_atomic(kaddr, KM_USER0); \
eb->map_len) { \
kaddr = eb->kaddr; \
map_start = eb->map_start; \
err = 0; \
} else { \
err = map_extent_buffer(eb, offset, \
sizeof(((type *)0)->member), \
&map_token, &kaddr, \
&map_start, &map_len, KM_USER1); \
} \
if (!err) { \
__le##bits *tmp = (__le##bits *)(kaddr + offset - \
map_start); \
*tmp = cpu_to_le##bits(val); \
if (unmap_on_exit) \
unmap_extent_buffer(eb, map_token, KM_USER1); \
} else { \
val = cpu_to_le##bits(val); \
write_eb_member(eb, NULL, type, member, &val); \
} \
} }
#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
...@@ -659,13 +613,13 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb, ...@@ -659,13 +613,13 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val); btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
} }
static unsigned long btrfs_node_key_ptr_offset(int nr) static inline unsigned long btrfs_node_key_ptr_offset(int nr)
{ {
return offsetof(struct btrfs_node, ptrs) + return offsetof(struct btrfs_node, ptrs) +
sizeof(struct btrfs_key_ptr) * nr; sizeof(struct btrfs_key_ptr) * nr;
} }
static void btrfs_node_key(struct extent_buffer *eb, static inline void btrfs_node_key(struct extent_buffer *eb,
struct btrfs_disk_key *disk_key, int nr) struct btrfs_disk_key *disk_key, int nr)
{ {
unsigned long ptr; unsigned long ptr;
......
...@@ -644,20 +644,20 @@ int close_ctree(struct btrfs_root *root) ...@@ -644,20 +644,20 @@ int close_ctree(struct btrfs_root *root)
int btrfs_buffer_uptodate(struct extent_buffer *buf) int btrfs_buffer_uptodate(struct extent_buffer *buf)
{ {
struct inode *btree_inode = buf->last_page->mapping->host; struct inode *btree_inode = buf->first_page->mapping->host;
return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf); return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf);
} }
int btrfs_set_buffer_uptodate(struct extent_buffer *buf) int btrfs_set_buffer_uptodate(struct extent_buffer *buf)
{ {
struct inode *btree_inode = buf->last_page->mapping->host; struct inode *btree_inode = buf->first_page->mapping->host;
return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree,
buf); buf);
} }
void btrfs_mark_buffer_dirty(struct extent_buffer *buf) void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
u64 transid = btrfs_header_generation(buf); u64 transid = btrfs_header_generation(buf);
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
...@@ -678,7 +678,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) ...@@ -678,7 +678,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
void btrfs_set_buffer_defrag(struct extent_buffer *buf) void btrfs_set_buffer_defrag(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS);
...@@ -686,7 +686,7 @@ void btrfs_set_buffer_defrag(struct extent_buffer *buf) ...@@ -686,7 +686,7 @@ void btrfs_set_buffer_defrag(struct extent_buffer *buf)
void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) void btrfs_set_buffer_defrag_done(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, buf->start + buf->len - 1, EXTENT_DEFRAG_DONE,
...@@ -695,7 +695,7 @@ void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) ...@@ -695,7 +695,7 @@ void btrfs_set_buffer_defrag_done(struct extent_buffer *buf)
int btrfs_buffer_defrag(struct extent_buffer *buf) int btrfs_buffer_defrag(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0);
...@@ -703,7 +703,7 @@ int btrfs_buffer_defrag(struct extent_buffer *buf) ...@@ -703,7 +703,7 @@ int btrfs_buffer_defrag(struct extent_buffer *buf)
int btrfs_buffer_defrag_done(struct extent_buffer *buf) int btrfs_buffer_defrag_done(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
buf->start, buf->start + buf->len - 1, buf->start, buf->start + buf->len - 1,
...@@ -712,7 +712,7 @@ int btrfs_buffer_defrag_done(struct extent_buffer *buf) ...@@ -712,7 +712,7 @@ int btrfs_buffer_defrag_done(struct extent_buffer *buf)
int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
buf->start, buf->start + buf->len - 1, buf->start, buf->start + buf->len - 1,
...@@ -721,7 +721,7 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) ...@@ -721,7 +721,7 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf)
int btrfs_clear_buffer_defrag(struct extent_buffer *buf) int btrfs_clear_buffer_defrag(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
buf->start, buf->start + buf->len - 1, buf->start, buf->start + buf->len - 1,
...@@ -730,7 +730,7 @@ int btrfs_clear_buffer_defrag(struct extent_buffer *buf) ...@@ -730,7 +730,7 @@ int btrfs_clear_buffer_defrag(struct extent_buffer *buf)
int btrfs_read_buffer(struct extent_buffer *buf) int btrfs_read_buffer(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
struct inode *btree_inode = root->fs_info->btree_inode; struct inode *btree_inode = root->fs_info->btree_inode;
return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
buf, 1); buf, 1);
......
...@@ -1963,9 +1963,9 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb, ...@@ -1963,9 +1963,9 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb,
struct page *p; struct page *p;
if (i == 0) if (i == 0)
return eb->last_page; return eb->first_page;
i += eb->start >> PAGE_CACHE_SHIFT; i += eb->start >> PAGE_CACHE_SHIFT;
p = find_get_page(eb->last_page->mapping, i); p = find_get_page(eb->first_page->mapping, i);
page_cache_release(p); page_cache_release(p);
return p; return p;
} }
...@@ -2037,7 +2037,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, ...@@ -2037,7 +2037,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
} }
set_page_extent_mapped(p); set_page_extent_mapped(p);
if (i == 0) if (i == 0)
eb->last_page = p; eb->first_page = p;
if (!PageUptodate(p)) if (!PageUptodate(p))
uptodate = 0; uptodate = 0;
unlock_page(p); unlock_page(p);
...@@ -2083,7 +2083,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, ...@@ -2083,7 +2083,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
} }
set_page_extent_mapped(p); set_page_extent_mapped(p);
if (i == 0) if (i == 0)
eb->last_page = p; eb->first_page = p;
if (!PageUptodate(p)) if (!PageUptodate(p))
uptodate = 0; uptodate = 0;
unlock_page(p); unlock_page(p);
...@@ -2169,7 +2169,15 @@ EXPORT_SYMBOL(wait_on_extent_buffer_writeback); ...@@ -2169,7 +2169,15 @@ EXPORT_SYMBOL(wait_on_extent_buffer_writeback);
int set_extent_buffer_dirty(struct extent_map_tree *tree, int set_extent_buffer_dirty(struct extent_map_tree *tree,
struct extent_buffer *eb) struct extent_buffer *eb)
{ {
return set_range_dirty(tree, eb->start, eb->start + eb->len - 1); unsigned long i;
unsigned long num_pages;
num_pages = num_extent_pages(eb->start, eb->len);
for (i = 0; i < num_pages; i++) {
__set_page_dirty_nobuffers(extent_buffer_page(eb, i));
}
return set_extent_dirty(tree, eb->start,
eb->start + eb->len - 1, GFP_NOFS);
} }
EXPORT_SYMBOL(set_extent_buffer_dirty); EXPORT_SYMBOL(set_extent_buffer_dirty);
...@@ -2317,16 +2325,11 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start, ...@@ -2317,16 +2325,11 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1);
unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
unsigned long end_i = (start_offset + start + min_len) >> unsigned long end_i = (start_offset + start + min_len) >>
PAGE_CACHE_SHIFT; PAGE_CACHE_SHIFT;
if (i != end_i) if (i != end_i)
return -EINVAL; return -EINVAL;
if (start >= eb->len) {
printk("bad start in map eb start %Lu len %lu caller start %lu min %lu\n", eb->start, eb->len, start, min_len);
WARN_ON(1);
}
if (i == 0) { if (i == 0) {
offset = start_offset; offset = start_offset;
*map_start = 0; *map_start = 0;
...@@ -2353,14 +2356,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start, ...@@ -2353,14 +2356,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
int err; int err;
int save = 0; int save = 0;
if (eb->map_token) { if (eb->map_token) {
if (start >= eb->map_start &&
start + min_len <= eb->map_start + eb->map_len) {
*token = eb->map_token;
*map = eb->kaddr;
*map_start = eb->map_start;
*map_len = eb->map_len;
return 0;
}
unmap_extent_buffer(eb, eb->map_token, km); unmap_extent_buffer(eb, eb->map_token, km);
eb->map_token = NULL; eb->map_token = NULL;
save = 1; save = 1;
......
...@@ -75,7 +75,7 @@ struct extent_buffer { ...@@ -75,7 +75,7 @@ struct extent_buffer {
char *kaddr; char *kaddr;
unsigned long map_start; unsigned long map_start;
unsigned long map_len; unsigned long map_len;
struct page *last_page; struct page *first_page;
struct list_head lru; struct list_head lru;
atomic_t refs; atomic_t refs;
int flags; int flags;
......
...@@ -289,7 +289,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, ...@@ -289,7 +289,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
*/ */
inline_size = end_pos; inline_size = end_pos;
if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) || if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
inline_size > 16384 ||
inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
u64 last_end; u64 last_end;
......
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