diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:14:27 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | 479965d66e320f1a095bb76027171daa675a9c72 (patch) | |
tree | e8b57bf49e2c0eb37e5dbd389f716e4dc21d54dc /fs | |
parent | 5f39d397dfbe140a14edecd4e73c34ce23c4f9ee (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.c | 51 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 48 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 11 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 2 |
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 { | |||
431 | static inline u##bits btrfs_##name(struct extent_buffer *eb, \ | 432 | static 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 | } \ |
438 | static inline void btrfs_set_##name(struct extent_buffer *eb, \ | 458 | static 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, | |||
2140 | EXPORT_SYMBOL(read_extent_buffer); | 2140 | EXPORT_SYMBOL(read_extent_buffer); |
2141 | 2141 | ||
2142 | int map_extent_buffer(struct extent_buffer *eb, unsigned long start, | 2142 | int 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, | |||
173 | int extent_buffer_uptodate(struct extent_map_tree *tree, | 173 | int extent_buffer_uptodate(struct extent_map_tree *tree, |
174 | struct extent_buffer *eb); | 174 | struct extent_buffer *eb); |
175 | int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, | 175 | int 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); |
179 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); | 179 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); |