Btrfs: Optimizations for the extent_buffer code
authorChris Mason <chris.mason@oracle.com>
Mon, 15 Oct 2007 20:14:27 +0000 (16:14 -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/extent_map.c
fs/btrfs/extent_map.h

index f60920e8a0e061f7d4cd4eaebe51a483cceb4645..9427b79c5d796ff7a8cafe2b75577a5ddc609d27 100644 (file)
@@ -464,22 +464,12 @@ static int check_block(struct btrfs_root *root, struct btrfs_path *path,
                        int level)
 {
        struct extent_buffer *buf = path->nodes[level];
-       char fsid[BTRFS_FSID_SIZE];
 
-       read_extent_buffer(buf, fsid, (unsigned long)btrfs_header_fsid(buf),
-                          BTRFS_FSID_SIZE);
-
-       if (memcmp(fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) {
-               int i = 0;
+       if (memcmp_extent_buffer(buf, root->fs_info->fsid,
+                                (unsigned long)btrfs_header_fsid(buf),
+                                BTRFS_FSID_SIZE)) {
                printk("warning bad block %Lu\n", buf->start);
-               if (!btrfs_buffer_uptodate(buf)) {
-                       WARN_ON(1);
-               }
-               for (i = 0; i < BTRFS_FSID_SIZE; i++) {
-                       printk("%x:%x ", root->fs_info->fsid[i], fsid[i]);
-               }
-               printk("\n");
-               // BUG();
+               BUG();
        }
        if (level == 0)
                return check_leaf(root, path, level);
@@ -504,13 +494,14 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
        int high = max;
        int mid;
        int ret;
-       struct btrfs_disk_key *tmp;
+       struct btrfs_disk_key *tmp = NULL;
        struct btrfs_disk_key unaligned;
        unsigned long offset;
        char *map_token = NULL;
        char *kaddr = NULL;
        unsigned long map_start = 0;
        unsigned long map_len = 0;
+       int err;
 
        while(low < high) {
                mid = (low + high) / 2;
@@ -519,19 +510,24 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
                if (!map_token || offset < map_start ||
                    (offset + sizeof(struct btrfs_disk_key)) >
                    map_start + map_len) {
-                       if (map_token)
+                       if (map_token) {
                                unmap_extent_buffer(eb, map_token, KM_USER0);
-                       map_extent_buffer(eb, offset, &map_token, &kaddr,
-                                         &map_start, &map_len, KM_USER0);
+                               map_token = NULL;
+                       }
+                       err = map_extent_buffer(eb, offset,
+                                               sizeof(struct btrfs_disk_key),
+                                               &map_token, &kaddr,
+                                               &map_start, &map_len, KM_USER0);
+
+                       if (!err) {
+                               tmp = (struct btrfs_disk_key *)(kaddr + offset -
+                                                       map_start);
+                       } else {
+                               read_extent_buffer(eb, &unaligned,
+                                                  offset, sizeof(unaligned));
+                               tmp = &unaligned;
+                       }
 
-               }
-               if (offset + sizeof(struct btrfs_disk_key) >
-                   map_start + map_len) {
-                       unmap_extent_buffer(eb, map_token, KM_USER0);
-                       read_extent_buffer(eb, &unaligned,
-                                          offset, sizeof(unaligned));
-                       map_token = NULL;
-                       tmp = &unaligned;
                } else {
                        tmp = (struct btrfs_disk_key *)(kaddr + offset -
                                                        map_start);
@@ -544,7 +540,8 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
                        high = mid;
                else {
                        *slot = mid;
-                       unmap_extent_buffer(eb, map_token, KM_USER0);
+                       if (map_token)
+                               unmap_extent_buffer(eb, map_token, KM_USER0);
                        return 0;
                }
        }
index c4b8298068556458f4b9775635d28187049eb484..30fbbd7221a96086eea849efcb63c6b2efab7a09 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/workqueue.h>
 #include <linux/completion.h>
+#include <asm/kmap_types.h>
 #include "bit-radix.h"
 #include "extent_map.h"
 
@@ -431,15 +432,52 @@ struct btrfs_root {
 static inline u##bits btrfs_##name(struct extent_buffer *eb,           \
                                   type *s)                             \
 {                                                                      \
-       __le##bits res;                                                 \
-       read_eb_member(eb, s, type, member, &res);                      \
-       return le##bits##_to_cpu(res);                                  \
+       int err;                                                        \
+       char *map_token;                                                \
+       char *kaddr;                                                    \
+       unsigned long map_start;                                        \
+       unsigned long map_len;                                          \
+       unsigned long offset = (unsigned long)s +                       \
+                               offsetof(type, member);                 \
+       err = map_extent_buffer(eb, offset,                             \
+                               sizeof(((type *)0)->member),            \
+                               &map_token, &kaddr,                     \
+                               &map_start, &map_len, KM_USER0);        \
+       if (!err) {                                                     \
+               __le##bits *tmp = (__le##bits *)(kaddr + offset -       \
+                                              map_start);              \
+               u##bits res = le##bits##_to_cpu(*tmp);                  \
+               unmap_extent_buffer(eb, map_token, KM_USER0);           \
+               return res;                                             \
+       } else {                                                        \
+               __le##bits res;                                         \
+               read_eb_member(eb, s, type, member, &res);              \
+               return le##bits##_to_cpu(res);                          \
+       }                                                               \
 }                                                                      \
 static inline void btrfs_set_##name(struct extent_buffer *eb,          \
                                    type *s, u##bits val)               \
 {                                                                      \
-       val = cpu_to_le##bits(val);                                     \
-       write_eb_member(eb, s, type, member, &val);                     \
+       int err;                                                        \
+       char *map_token;                                                \
+       char *kaddr;                                                    \
+       unsigned long map_start;                                        \
+       unsigned long map_len;                                          \
+       unsigned long offset = (unsigned long)s +                       \
+                               offsetof(type, member);                 \
+       err = map_extent_buffer(eb, offset,                             \
+                               sizeof(((type *)0)->member),            \
+                               &map_token, &kaddr,                     \
+                               &map_start, &map_len, KM_USER0);        \
+       if (!err) {                                                     \
+               __le##bits *tmp = (__le##bits *)(kaddr + offset -       \
+                                              map_start);              \
+               *tmp = cpu_to_le##bits(val);                            \
+               unmap_extent_buffer(eb, map_token, KM_USER0);           \
+       } else {                                                        \
+               val = cpu_to_le##bits(val);                             \
+               write_eb_member(eb, s, type, member, &val);             \
+       }                                                               \
 }
 
 #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)            \
index 55fefdfab84ce7f52157ba889e9487435232e344..8bef309e1b3737dce85939e420b2e6bf1852226b 100644 (file)
@@ -2140,14 +2140,20 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
 EXPORT_SYMBOL(read_extent_buffer);
 
 int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
+                     unsigned long min_len,
                      char **token, char **map,
                      unsigned long *map_start,
                      unsigned long *map_len, int km)
 {
-       size_t offset;
+       size_t offset = start & (PAGE_CACHE_SIZE - 1);
        char *kaddr;
        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;
+
+       if (i != end_i)
+               return -EINVAL;
 
        WARN_ON(start > eb->len);
 
@@ -2155,8 +2161,7 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
                offset = start_offset;
                *map_start = 0;
        } else {
-               offset = 0;
-               *map_start = (i << PAGE_CACHE_SHIFT) - offset;
+               *map_start = (i << PAGE_CACHE_SHIFT) - start_offset;
        }
 
        // kaddr = kmap_atomic(eb->pages[i], km);
index 430b997a70f6876e1891e8454dc641af593d4ff0..895789039ddd9faf9c36b15285292bb5e8805343 100644 (file)
@@ -173,7 +173,7 @@ int set_extent_buffer_uptodate(struct extent_map_tree *tree,
 int extent_buffer_uptodate(struct extent_map_tree *tree,
                           struct extent_buffer *eb);
 int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
-                     char **token, char **map,
+                     unsigned long min_len, char **token, char **map,
                      unsigned long *map_start,
                      unsigned long *map_len, int km);
 void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);