Btrfs: extent_map optimizations to cut down on CPU usage
authorChris Mason <chris.mason@oracle.com>
Mon, 15 Oct 2007 20:18:55 +0000 (16:18 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:03:56 +0000 (11:03 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent_map.c
fs/btrfs/extent_map.h
fs/btrfs/file.c

index f691542dfa1537e8d1e5a1bb3220c2fe9b997e29..54a5d006c5623a2175e5ef7f60e88de101a77b07 100644 (file)
@@ -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];
 
index 18994c53106cf1125c7a74e7d12ee713a008a61a..a942a242722841f931390d7a1bfe3d3c6db89169 100644 (file)
@@ -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);   \
-               return res;                                             \
-       } else {                                                        \
-               __le##bits res;                                         \
-               read_eb_member(eb, NULL, type, member, &res);           \
-               return le##bits##_to_cpu(res);                          \
-       }                                                               \
+       u##bits res;                                                    \
+       __le##bits *tmp = (__le##bits *)(kaddr + offset);               \
+       res = le##bits##_to_cpu(*tmp);                                  \
+       kunmap_atomic(kaddr, KM_USER0);                                 \
+       return 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);              \
-               *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);          \
-       }                                                               \
+       __le##bits *tmp = (__le##bits *)(kaddr + offset);               \
+       *tmp = cpu_to_le##bits(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;
index fd7e6c182b9d3985a25f252aaddd71510cca8b59..16f0260fca66998b897d29ac9aa2da391831bdf7 100644 (file)
@@ -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);
index 85b28a6a4e05d601cfafb3a257c01be897175c32..f8aaba8a30a204751af92f2f47fca3dc633750bc 100644 (file)
@@ -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);
 
@@ -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);
        unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
        unsigned long end_i = (start_offset + start + min_len) >>
-                               PAGE_CACHE_SHIFT;
+               PAGE_CACHE_SHIFT;
 
        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;
index 52a8b9394fc6e6f458a3483cc36eca385fcc1c7a..f1dc28d260eb0b3d4404957f7404f1188b93d9d8 100644 (file)
@@ -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;
index 1af2b6534dadd190db5585ad67e9afacadf93401..fe28404ae7f4c4ca68ec516a19bb3008b7e346e3 100644 (file)
@@ -289,7 +289,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
         */
        inline_size = end_pos;
        if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
-           inline_size > 16384 ||
            inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
                u64 last_end;