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

Btrfs: extent_map optimizations to cut down on CPU usage

parent 3326d1b0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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,
			int level)
{
	return 0;
#if 0
	struct extent_buffer *buf = path->nodes[level];

+14 −60
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#ifndef __BTRFS__
#define __BTRFS__

#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/fs.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
@@ -499,70 +501,22 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)		\
static inline u##bits btrfs_##name(struct extent_buffer *eb)		\
{									\
	int err;							\
	char *map_token;						\
	char *kaddr;							\
	unsigned long map_start;					\
	unsigned long map_len;						\
	char *kaddr = kmap_atomic(eb->first_page, KM_USER0);		\
	unsigned long offset = offsetof(type, member);			\
	int unmap_on_exit = (eb->map_token == NULL);			\
	if (eb->map_token && offset >= eb->map_start &&			\
	    offset + sizeof(((type *)0)->member) <= eb->map_start +	\
	    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);		\
		u##bits res = le##bits##_to_cpu(*tmp);			\
		if (unmap_on_exit)					\
			unmap_extent_buffer(eb, map_token, KM_USER1);	\
	u##bits res;							\
	__le##bits *tmp = (__le##bits *)(kaddr + offset);		\
	res = le##bits##_to_cpu(*tmp);					\
	kunmap_atomic(kaddr, KM_USER0);					\
	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,		\
				    u##bits val)			\
{									\
	int err;							\
	char *map_token;						\
	char *kaddr;							\
	unsigned long map_start;					\
	unsigned long map_len;						\
	char *kaddr = kmap_atomic(eb->first_page, KM_USER0);		\
	unsigned long offset = offsetof(type, member);			\
	int unmap_on_exit = (eb->map_token == NULL);			\
	if (eb->map_token && offset >= eb->map_start &&			\
	    offset + sizeof(((type *)0)->member) <= eb->map_start +	\
	    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);		\
	__le##bits *tmp = (__le##bits *)(kaddr + offset);		\
	*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);		\
	}								\
	kunmap_atomic(kaddr, KM_USER0);					\
}

#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)		\
@@ -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);
}

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) +
		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)
{
	unsigned long ptr;
+10 −10
Original line number Diff line number Diff line
@@ -644,20 +644,20 @@ int close_ctree(struct btrfs_root *root)

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);
}

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,
					  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);
	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)

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;
	set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
			buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS);
@@ -686,7 +686,7 @@ void btrfs_set_buffer_defrag(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;
	set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
			buf->start + buf->len - 1, EXTENT_DEFRAG_DONE,
@@ -695,7 +695,7 @@ void btrfs_set_buffer_defrag_done(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;
	return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
		     buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0);
@@ -703,7 +703,7 @@ int btrfs_buffer_defrag(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;
	return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
		     buf->start, buf->start + buf->len - 1,
@@ -712,7 +712,7 @@ int btrfs_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;
	return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
		     buf->start, buf->start + buf->len - 1,
@@ -721,7 +721,7 @@ int btrfs_clear_buffer_defrag_done(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;
	return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
		     buf->start, buf->start + buf->len - 1,
@@ -730,7 +730,7 @@ int btrfs_clear_buffer_defrag(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;
	return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
					buf, 1);
+14 −19
Original line number Diff line number Diff line
@@ -1963,9 +1963,9 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb,
	struct page *p;

	if (i == 0)
		return eb->last_page;
		return eb->first_page;
	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);
	return p;
}
@@ -2037,7 +2037,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
		}
		set_page_extent_mapped(p);
		if (i == 0)
			eb->last_page = p;
			eb->first_page = p;
		if (!PageUptodate(p))
			uptodate = 0;
		unlock_page(p);
@@ -2083,7 +2083,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
		}
		set_page_extent_mapped(p);
		if (i == 0)
			eb->last_page = p;
			eb->first_page = p;
		if (!PageUptodate(p))
			uptodate = 0;
		unlock_page(p);
@@ -2169,7 +2169,15 @@ EXPORT_SYMBOL(wait_on_extent_buffer_writeback);
int set_extent_buffer_dirty(struct extent_map_tree *tree,
			     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);

@@ -2322,11 +2330,6 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
	if (i != end_i)
		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) {
		offset = start_offset;
		*map_start = 0;
@@ -2353,14 +2356,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
	int err;
	int save = 0;
	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);
		eb->map_token = NULL;
		save = 1;
+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ struct extent_buffer {
	char *kaddr;
	unsigned long map_start;
	unsigned long map_len;
	struct page *last_page;
	struct page *first_page;
	struct list_head lru;
	atomic_t refs;
	int flags;
Loading