aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:14:27 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit479965d66e320f1a095bb76027171daa675a9c72 (patch)
treee8b57bf49e2c0eb37e5dbd389f716e4dc21d54dc /fs
parent5f39d397dfbe140a14edecd4e73c34ce23c4f9ee (diff)
Btrfs: Optimizations for the extent_buffer code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c51
-rw-r--r--fs/btrfs/ctree.h48
-rw-r--r--fs/btrfs/extent_map.c11
-rw-r--r--fs/btrfs/extent_map.h2
4 files changed, 76 insertions, 36 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index f60920e8a0e0..9427b79c5d79 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -464,22 +464,12 @@ static int check_block(struct btrfs_root *root, struct btrfs_path *path,
464 int level) 464 int level)
465{ 465{
466 struct extent_buffer *buf = path->nodes[level]; 466 struct extent_buffer *buf = path->nodes[level];
467 char fsid[BTRFS_FSID_SIZE];
468 467
469 read_extent_buffer(buf, fsid, (unsigned long)btrfs_header_fsid(buf), 468 if (memcmp_extent_buffer(buf, root->fs_info->fsid,
470 BTRFS_FSID_SIZE); 469 (unsigned long)btrfs_header_fsid(buf),
471 470 BTRFS_FSID_SIZE)) {
472 if (memcmp(fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) {
473 int i = 0;
474 printk("warning bad block %Lu\n", buf->start); 471 printk("warning bad block %Lu\n", buf->start);
475 if (!btrfs_buffer_uptodate(buf)) { 472 BUG();
476 WARN_ON(1);
477 }
478 for (i = 0; i < BTRFS_FSID_SIZE; i++) {
479 printk("%x:%x ", root->fs_info->fsid[i], fsid[i]);
480 }
481 printk("\n");
482 // BUG();
483 } 473 }
484 if (level == 0) 474 if (level == 0)
485 return check_leaf(root, path, level); 475 return check_leaf(root, path, level);
@@ -504,13 +494,14 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
504 int high = max; 494 int high = max;
505 int mid; 495 int mid;
506 int ret; 496 int ret;
507 struct btrfs_disk_key *tmp; 497 struct btrfs_disk_key *tmp = NULL;
508 struct btrfs_disk_key unaligned; 498 struct btrfs_disk_key unaligned;
509 unsigned long offset; 499 unsigned long offset;
510 char *map_token = NULL; 500 char *map_token = NULL;
511 char *kaddr = NULL; 501 char *kaddr = NULL;
512 unsigned long map_start = 0; 502 unsigned long map_start = 0;
513 unsigned long map_len = 0; 503 unsigned long map_len = 0;
504 int err;
514 505
515 while(low < high) { 506 while(low < high) {
516 mid = (low + high) / 2; 507 mid = (low + high) / 2;
@@ -519,19 +510,24 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
519 if (!map_token || offset < map_start || 510 if (!map_token || offset < map_start ||
520 (offset + sizeof(struct btrfs_disk_key)) > 511 (offset + sizeof(struct btrfs_disk_key)) >
521 map_start + map_len) { 512 map_start + map_len) {
522 if (map_token) 513 if (map_token) {
523 unmap_extent_buffer(eb, map_token, KM_USER0); 514 unmap_extent_buffer(eb, map_token, KM_USER0);
524 map_extent_buffer(eb, offset, &map_token, &kaddr, 515 map_token = NULL;
525 &map_start, &map_len, KM_USER0); 516 }
517 err = map_extent_buffer(eb, offset,
518 sizeof(struct btrfs_disk_key),
519 &map_token, &kaddr,
520 &map_start, &map_len, KM_USER0);
521
522 if (!err) {
523 tmp = (struct btrfs_disk_key *)(kaddr + offset -
524 map_start);
525 } else {
526 read_extent_buffer(eb, &unaligned,
527 offset, sizeof(unaligned));
528 tmp = &unaligned;
529 }
526 530
527 }
528 if (offset + sizeof(struct btrfs_disk_key) >
529 map_start + map_len) {
530 unmap_extent_buffer(eb, map_token, KM_USER0);
531 read_extent_buffer(eb, &unaligned,
532 offset, sizeof(unaligned));
533 map_token = NULL;
534 tmp = &unaligned;
535 } else { 531 } else {
536 tmp = (struct btrfs_disk_key *)(kaddr + offset - 532 tmp = (struct btrfs_disk_key *)(kaddr + offset -
537 map_start); 533 map_start);
@@ -544,7 +540,8 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
544 high = mid; 540 high = mid;
545 else { 541 else {
546 *slot = mid; 542 *slot = mid;
547 unmap_extent_buffer(eb, map_token, KM_USER0); 543 if (map_token)
544 unmap_extent_buffer(eb, map_token, KM_USER0);
548 return 0; 545 return 0;
549 } 546 }
550 } 547 }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index c4b829806855..30fbbd7221a9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -22,6 +22,7 @@
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/workqueue.h> 23#include <linux/workqueue.h>
24#include <linux/completion.h> 24#include <linux/completion.h>
25#include <asm/kmap_types.h>
25#include "bit-radix.h" 26#include "bit-radix.h"
26#include "extent_map.h" 27#include "extent_map.h"
27 28
@@ -431,15 +432,52 @@ struct btrfs_root {
431static inline u##bits btrfs_##name(struct extent_buffer *eb, \ 432static inline u##bits btrfs_##name(struct extent_buffer *eb, \
432 type *s) \ 433 type *s) \
433{ \ 434{ \
434 __le##bits res; \ 435 int err; \
435 read_eb_member(eb, s, type, member, &res); \ 436 char *map_token; \
436 return le##bits##_to_cpu(res); \ 437 char *kaddr; \
438 unsigned long map_start; \
439 unsigned long map_len; \
440 unsigned long offset = (unsigned long)s + \
441 offsetof(type, member); \
442 err = map_extent_buffer(eb, offset, \
443 sizeof(((type *)0)->member), \
444 &map_token, &kaddr, \
445 &map_start, &map_len, KM_USER0); \
446 if (!err) { \
447 __le##bits *tmp = (__le##bits *)(kaddr + offset - \
448 map_start); \
449 u##bits res = le##bits##_to_cpu(*tmp); \
450 unmap_extent_buffer(eb, map_token, KM_USER0); \
451 return res; \
452 } else { \
453 __le##bits res; \
454 read_eb_member(eb, s, type, member, &res); \
455 return le##bits##_to_cpu(res); \
456 } \
437} \ 457} \
438static inline void btrfs_set_##name(struct extent_buffer *eb, \ 458static inline void btrfs_set_##name(struct extent_buffer *eb, \
439 type *s, u##bits val) \ 459 type *s, u##bits val) \
440{ \ 460{ \
441 val = cpu_to_le##bits(val); \ 461 int err; \
442 write_eb_member(eb, s, type, member, &val); \ 462 char *map_token; \
463 char *kaddr; \
464 unsigned long map_start; \
465 unsigned long map_len; \
466 unsigned long offset = (unsigned long)s + \
467 offsetof(type, member); \
468 err = map_extent_buffer(eb, offset, \
469 sizeof(((type *)0)->member), \
470 &map_token, &kaddr, \
471 &map_start, &map_len, KM_USER0); \
472 if (!err) { \
473 __le##bits *tmp = (__le##bits *)(kaddr + offset - \
474 map_start); \
475 *tmp = cpu_to_le##bits(val); \
476 unmap_extent_buffer(eb, map_token, KM_USER0); \
477 } else { \
478 val = cpu_to_le##bits(val); \
479 write_eb_member(eb, s, type, member, &val); \
480 } \
443} 481}
444 482
445#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ 483#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 55fefdfab84c..8bef309e1b37 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -2140,14 +2140,20 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
2140EXPORT_SYMBOL(read_extent_buffer); 2140EXPORT_SYMBOL(read_extent_buffer);
2141 2141
2142int map_extent_buffer(struct extent_buffer *eb, unsigned long start, 2142int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2143 unsigned long min_len,
2143 char **token, char **map, 2144 char **token, char **map,
2144 unsigned long *map_start, 2145 unsigned long *map_start,
2145 unsigned long *map_len, int km) 2146 unsigned long *map_len, int km)
2146{ 2147{
2147 size_t offset; 2148 size_t offset = start & (PAGE_CACHE_SIZE - 1);
2148 char *kaddr; 2149 char *kaddr;
2149 size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); 2150 size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1);
2150 unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; 2151 unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
2152 unsigned long end_i = (start_offset + start + min_len) >>
2153 PAGE_CACHE_SHIFT;
2154
2155 if (i != end_i)
2156 return -EINVAL;
2151 2157
2152 WARN_ON(start > eb->len); 2158 WARN_ON(start > eb->len);
2153 2159
@@ -2155,8 +2161,7 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2155 offset = start_offset; 2161 offset = start_offset;
2156 *map_start = 0; 2162 *map_start = 0;
2157 } else { 2163 } else {
2158 offset = 0; 2164 *map_start = (i << PAGE_CACHE_SHIFT) - start_offset;
2159 *map_start = (i << PAGE_CACHE_SHIFT) - offset;
2160 } 2165 }
2161 2166
2162 // kaddr = kmap_atomic(eb->pages[i], km); 2167 // kaddr = kmap_atomic(eb->pages[i], km);
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index 430b997a70f6..895789039ddd 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -173,7 +173,7 @@ int set_extent_buffer_uptodate(struct extent_map_tree *tree,
173int extent_buffer_uptodate(struct extent_map_tree *tree, 173int extent_buffer_uptodate(struct extent_map_tree *tree,
174 struct extent_buffer *eb); 174 struct extent_buffer *eb);
175int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, 175int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
176 char **token, char **map, 176 unsigned long min_len, char **token, char **map,
177 unsigned long *map_start, 177 unsigned long *map_start,
178 unsigned long *map_len, int km); 178 unsigned long *map_len, int km);
179void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); 179void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);