aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:18:55 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit810191ff3087e8143b41a944fcf4fd8c693f00e3 (patch)
tree9d23dd51458623eaac41bc8c89dd2998a2eda7ae /fs/btrfs
parent3326d1b07c0cb6a2ff5b835b7a2cffa54124d074 (diff)
Btrfs: extent_map optimizations to cut down on CPU usage
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c1
-rw-r--r--fs/btrfs/ctree.h74
-rw-r--r--fs/btrfs/disk-io.c20
-rw-r--r--fs/btrfs/extent_map.c33
-rw-r--r--fs/btrfs/extent_map.h2
-rw-r--r--fs/btrfs/file.c1
6 files changed, 40 insertions, 91 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index f691542dfa15..54a5d006c562 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -463,6 +463,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
463static int check_block(struct btrfs_root *root, struct btrfs_path *path, 463static int check_block(struct btrfs_root *root, struct btrfs_path *path,
464 int level) 464 int level)
465{ 465{
466 return 0;
466#if 0 467#if 0
467 struct extent_buffer *buf = path->nodes[level]; 468 struct extent_buffer *buf = path->nodes[level];
468 469
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 18994c53106c..a942a2427228 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -19,6 +19,8 @@
19#ifndef __BTRFS__ 19#ifndef __BTRFS__
20#define __BTRFS__ 20#define __BTRFS__
21 21
22#include <linux/mm.h>
23#include <linux/highmem.h>
22#include <linux/fs.h> 24#include <linux/fs.h>
23#include <linux/workqueue.h> 25#include <linux/workqueue.h>
24#include <linux/completion.h> 26#include <linux/completion.h>
@@ -499,70 +501,22 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
499#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ 501#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
500static inline u##bits btrfs_##name(struct extent_buffer *eb) \ 502static inline u##bits btrfs_##name(struct extent_buffer *eb) \
501{ \ 503{ \
502 int err; \ 504 char *kaddr = kmap_atomic(eb->first_page, KM_USER0); \
503 char *map_token; \
504 char *kaddr; \
505 unsigned long map_start; \
506 unsigned long map_len; \
507 unsigned long offset = offsetof(type, member); \ 505 unsigned long offset = offsetof(type, member); \
508 int unmap_on_exit = (eb->map_token == NULL); \ 506 u##bits res; \
509 if (eb->map_token && offset >= eb->map_start && \ 507 __le##bits *tmp = (__le##bits *)(kaddr + offset); \
510 offset + sizeof(((type *)0)->member) <= eb->map_start + \ 508 res = le##bits##_to_cpu(*tmp); \
511 eb->map_len) { \ 509 kunmap_atomic(kaddr, KM_USER0); \
512 kaddr = eb->kaddr; \ 510 return res; \
513 map_start = eb->map_start; \
514 err = 0; \
515 } else { \
516 err = map_extent_buffer(eb, offset, \
517 sizeof(((type *)0)->member), \
518 &map_token, &kaddr, \
519 &map_start, &map_len, KM_USER1); \
520 } \
521 if (!err) { \
522 __le##bits *tmp = (__le##bits *)(kaddr + offset - \
523 map_start); \
524 u##bits res = le##bits##_to_cpu(*tmp); \
525 if (unmap_on_exit) \
526 unmap_extent_buffer(eb, map_token, KM_USER1); \
527 return res; \
528 } else { \
529 __le##bits res; \
530 read_eb_member(eb, NULL, type, member, &res); \
531 return le##bits##_to_cpu(res); \
532 } \
533} \ 511} \
534static inline void btrfs_set_##name(struct extent_buffer *eb, \ 512static inline void btrfs_set_##name(struct extent_buffer *eb, \
535 u##bits val) \ 513 u##bits val) \
536{ \ 514{ \
537 int err; \ 515 char *kaddr = kmap_atomic(eb->first_page, KM_USER0); \
538 char *map_token; \
539 char *kaddr; \
540 unsigned long map_start; \
541 unsigned long map_len; \
542 unsigned long offset = offsetof(type, member); \ 516 unsigned long offset = offsetof(type, member); \
543 int unmap_on_exit = (eb->map_token == NULL); \ 517 __le##bits *tmp = (__le##bits *)(kaddr + offset); \
544 if (eb->map_token && offset >= eb->map_start && \ 518 *tmp = cpu_to_le##bits(val); \
545 offset + sizeof(((type *)0)->member) <= eb->map_start + \ 519 kunmap_atomic(kaddr, KM_USER0); \
546 eb->map_len) { \
547 kaddr = eb->kaddr; \
548 map_start = eb->map_start; \
549 err = 0; \
550 } else { \
551 err = map_extent_buffer(eb, offset, \
552 sizeof(((type *)0)->member), \
553 &map_token, &kaddr, \
554 &map_start, &map_len, KM_USER1); \
555 } \
556 if (!err) { \
557 __le##bits *tmp = (__le##bits *)(kaddr + offset - \
558 map_start); \
559 *tmp = cpu_to_le##bits(val); \
560 if (unmap_on_exit) \
561 unmap_extent_buffer(eb, map_token, KM_USER1); \
562 } else { \
563 val = cpu_to_le##bits(val); \
564 write_eb_member(eb, NULL, type, member, &val); \
565 } \
566} 520}
567 521
568#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ 522#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
@@ -659,13 +613,13 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
659 btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val); 613 btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
660} 614}
661 615
662static unsigned long btrfs_node_key_ptr_offset(int nr) 616static inline unsigned long btrfs_node_key_ptr_offset(int nr)
663{ 617{
664 return offsetof(struct btrfs_node, ptrs) + 618 return offsetof(struct btrfs_node, ptrs) +
665 sizeof(struct btrfs_key_ptr) * nr; 619 sizeof(struct btrfs_key_ptr) * nr;
666} 620}
667 621
668static void btrfs_node_key(struct extent_buffer *eb, 622static inline void btrfs_node_key(struct extent_buffer *eb,
669 struct btrfs_disk_key *disk_key, int nr) 623 struct btrfs_disk_key *disk_key, int nr)
670{ 624{
671 unsigned long ptr; 625 unsigned long ptr;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index fd7e6c182b9d..16f0260fca66 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -644,20 +644,20 @@ int close_ctree(struct btrfs_root *root)
644 644
645int btrfs_buffer_uptodate(struct extent_buffer *buf) 645int btrfs_buffer_uptodate(struct extent_buffer *buf)
646{ 646{
647 struct inode *btree_inode = buf->last_page->mapping->host; 647 struct inode *btree_inode = buf->first_page->mapping->host;
648 return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf); 648 return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf);
649} 649}
650 650
651int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 651int btrfs_set_buffer_uptodate(struct extent_buffer *buf)
652{ 652{
653 struct inode *btree_inode = buf->last_page->mapping->host; 653 struct inode *btree_inode = buf->first_page->mapping->host;
654 return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, 654 return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree,
655 buf); 655 buf);
656} 656}
657 657
658void btrfs_mark_buffer_dirty(struct extent_buffer *buf) 658void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
659{ 659{
660 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 660 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
661 u64 transid = btrfs_header_generation(buf); 661 u64 transid = btrfs_header_generation(buf);
662 struct inode *btree_inode = root->fs_info->btree_inode; 662 struct inode *btree_inode = root->fs_info->btree_inode;
663 663
@@ -678,7 +678,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
678 678
679void btrfs_set_buffer_defrag(struct extent_buffer *buf) 679void btrfs_set_buffer_defrag(struct extent_buffer *buf)
680{ 680{
681 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 681 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
682 struct inode *btree_inode = root->fs_info->btree_inode; 682 struct inode *btree_inode = root->fs_info->btree_inode;
683 set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 683 set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
684 buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS); 684 buf->start + buf->len - 1, EXTENT_DEFRAG, GFP_NOFS);
@@ -686,7 +686,7 @@ void btrfs_set_buffer_defrag(struct extent_buffer *buf)
686 686
687void btrfs_set_buffer_defrag_done(struct extent_buffer *buf) 687void btrfs_set_buffer_defrag_done(struct extent_buffer *buf)
688{ 688{
689 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 689 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
690 struct inode *btree_inode = root->fs_info->btree_inode; 690 struct inode *btree_inode = root->fs_info->btree_inode;
691 set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start, 691 set_extent_bits(&BTRFS_I(btree_inode)->extent_tree, buf->start,
692 buf->start + buf->len - 1, EXTENT_DEFRAG_DONE, 692 buf->start + buf->len - 1, EXTENT_DEFRAG_DONE,
@@ -695,7 +695,7 @@ void btrfs_set_buffer_defrag_done(struct extent_buffer *buf)
695 695
696int btrfs_buffer_defrag(struct extent_buffer *buf) 696int btrfs_buffer_defrag(struct extent_buffer *buf)
697{ 697{
698 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 698 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
699 struct inode *btree_inode = root->fs_info->btree_inode; 699 struct inode *btree_inode = root->fs_info->btree_inode;
700 return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 700 return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
701 buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0); 701 buf->start, buf->start + buf->len - 1, EXTENT_DEFRAG, 0);
@@ -703,7 +703,7 @@ int btrfs_buffer_defrag(struct extent_buffer *buf)
703 703
704int btrfs_buffer_defrag_done(struct extent_buffer *buf) 704int btrfs_buffer_defrag_done(struct extent_buffer *buf)
705{ 705{
706 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 706 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
707 struct inode *btree_inode = root->fs_info->btree_inode; 707 struct inode *btree_inode = root->fs_info->btree_inode;
708 return test_range_bit(&BTRFS_I(btree_inode)->extent_tree, 708 return test_range_bit(&BTRFS_I(btree_inode)->extent_tree,
709 buf->start, buf->start + buf->len - 1, 709 buf->start, buf->start + buf->len - 1,
@@ -712,7 +712,7 @@ int btrfs_buffer_defrag_done(struct extent_buffer *buf)
712 712
713int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf) 713int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf)
714{ 714{
715 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 715 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
716 struct inode *btree_inode = root->fs_info->btree_inode; 716 struct inode *btree_inode = root->fs_info->btree_inode;
717 return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 717 return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
718 buf->start, buf->start + buf->len - 1, 718 buf->start, buf->start + buf->len - 1,
@@ -721,7 +721,7 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf)
721 721
722int btrfs_clear_buffer_defrag(struct extent_buffer *buf) 722int btrfs_clear_buffer_defrag(struct extent_buffer *buf)
723{ 723{
724 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 724 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
725 struct inode *btree_inode = root->fs_info->btree_inode; 725 struct inode *btree_inode = root->fs_info->btree_inode;
726 return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree, 726 return clear_extent_bits(&BTRFS_I(btree_inode)->extent_tree,
727 buf->start, buf->start + buf->len - 1, 727 buf->start, buf->start + buf->len - 1,
@@ -730,7 +730,7 @@ int btrfs_clear_buffer_defrag(struct extent_buffer *buf)
730 730
731int btrfs_read_buffer(struct extent_buffer *buf) 731int btrfs_read_buffer(struct extent_buffer *buf)
732{ 732{
733 struct btrfs_root *root = BTRFS_I(buf->last_page->mapping->host)->root; 733 struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
734 struct inode *btree_inode = root->fs_info->btree_inode; 734 struct inode *btree_inode = root->fs_info->btree_inode;
735 return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree, 735 return read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
736 buf, 1); 736 buf, 1);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 85b28a6a4e05..f8aaba8a30a2 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -1963,9 +1963,9 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb,
1963 struct page *p; 1963 struct page *p;
1964 1964
1965 if (i == 0) 1965 if (i == 0)
1966 return eb->last_page; 1966 return eb->first_page;
1967 i += eb->start >> PAGE_CACHE_SHIFT; 1967 i += eb->start >> PAGE_CACHE_SHIFT;
1968 p = find_get_page(eb->last_page->mapping, i); 1968 p = find_get_page(eb->first_page->mapping, i);
1969 page_cache_release(p); 1969 page_cache_release(p);
1970 return p; 1970 return p;
1971} 1971}
@@ -2037,7 +2037,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
2037 } 2037 }
2038 set_page_extent_mapped(p); 2038 set_page_extent_mapped(p);
2039 if (i == 0) 2039 if (i == 0)
2040 eb->last_page = p; 2040 eb->first_page = p;
2041 if (!PageUptodate(p)) 2041 if (!PageUptodate(p))
2042 uptodate = 0; 2042 uptodate = 0;
2043 unlock_page(p); 2043 unlock_page(p);
@@ -2083,7 +2083,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
2083 } 2083 }
2084 set_page_extent_mapped(p); 2084 set_page_extent_mapped(p);
2085 if (i == 0) 2085 if (i == 0)
2086 eb->last_page = p; 2086 eb->first_page = p;
2087 if (!PageUptodate(p)) 2087 if (!PageUptodate(p))
2088 uptodate = 0; 2088 uptodate = 0;
2089 unlock_page(p); 2089 unlock_page(p);
@@ -2169,7 +2169,15 @@ EXPORT_SYMBOL(wait_on_extent_buffer_writeback);
2169int set_extent_buffer_dirty(struct extent_map_tree *tree, 2169int set_extent_buffer_dirty(struct extent_map_tree *tree,
2170 struct extent_buffer *eb) 2170 struct extent_buffer *eb)
2171{ 2171{
2172 return set_range_dirty(tree, eb->start, eb->start + eb->len - 1); 2172 unsigned long i;
2173 unsigned long num_pages;
2174
2175 num_pages = num_extent_pages(eb->start, eb->len);
2176 for (i = 0; i < num_pages; i++) {
2177 __set_page_dirty_nobuffers(extent_buffer_page(eb, i));
2178 }
2179 return set_extent_dirty(tree, eb->start,
2180 eb->start + eb->len - 1, GFP_NOFS);
2173} 2181}
2174EXPORT_SYMBOL(set_extent_buffer_dirty); 2182EXPORT_SYMBOL(set_extent_buffer_dirty);
2175 2183
@@ -2317,16 +2325,11 @@ static int __map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2317 size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1); 2325 size_t start_offset = eb->start & ((u64)PAGE_CACHE_SIZE - 1);
2318 unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT; 2326 unsigned long i = (start_offset + start) >> PAGE_CACHE_SHIFT;
2319 unsigned long end_i = (start_offset + start + min_len) >> 2327 unsigned long end_i = (start_offset + start + min_len) >>
2320 PAGE_CACHE_SHIFT; 2328 PAGE_CACHE_SHIFT;
2321 2329
2322 if (i != end_i) 2330 if (i != end_i)
2323 return -EINVAL; 2331 return -EINVAL;
2324 2332
2325 if (start >= eb->len) {
2326 printk("bad start in map eb start %Lu len %lu caller start %lu min %lu\n", eb->start, eb->len, start, min_len);
2327 WARN_ON(1);
2328 }
2329
2330 if (i == 0) { 2333 if (i == 0) {
2331 offset = start_offset; 2334 offset = start_offset;
2332 *map_start = 0; 2335 *map_start = 0;
@@ -2353,14 +2356,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
2353 int err; 2356 int err;
2354 int save = 0; 2357 int save = 0;
2355 if (eb->map_token) { 2358 if (eb->map_token) {
2356 if (start >= eb->map_start &&
2357 start + min_len <= eb->map_start + eb->map_len) {
2358 *token = eb->map_token;
2359 *map = eb->kaddr;
2360 *map_start = eb->map_start;
2361 *map_len = eb->map_len;
2362 return 0;
2363 }
2364 unmap_extent_buffer(eb, eb->map_token, km); 2359 unmap_extent_buffer(eb, eb->map_token, km);
2365 eb->map_token = NULL; 2360 eb->map_token = NULL;
2366 save = 1; 2361 save = 1;
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index 52a8b9394fc6..f1dc28d260eb 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -75,7 +75,7 @@ struct extent_buffer {
75 char *kaddr; 75 char *kaddr;
76 unsigned long map_start; 76 unsigned long map_start;
77 unsigned long map_len; 77 unsigned long map_len;
78 struct page *last_page; 78 struct page *first_page;
79 struct list_head lru; 79 struct list_head lru;
80 atomic_t refs; 80 atomic_t refs;
81 int flags; 81 int flags;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 1af2b6534dad..fe28404ae7f4 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -289,7 +289,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
289 */ 289 */
290 inline_size = end_pos; 290 inline_size = end_pos;
291 if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) || 291 if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
292 inline_size > 16384 ||
293 inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { 292 inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
294 u64 last_end; 293 u64 last_end;
295 294