aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-07 15:52:22 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-07 15:52:22 -0400
commit3c69faecb8d83cb2ef085a98b196a3fecea67725 (patch)
treed764502dd93bcd767c2130518d0c1fe00a7e96ff /fs/btrfs
parent9f3a742736cecda5a8778be70faa2f779458839f (diff)
Btrfs: Fold some btree readahead routines into something more generic.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c77
-rw-r--r--fs/btrfs/ctree.h1
-rw-r--r--fs/btrfs/extent-tree.c30
-rw-r--r--fs/btrfs/inode.c69
4 files changed, 81 insertions, 96 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index aa824e2c521f..7a08491e208e 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -640,6 +640,73 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
640} 640}
641 641
642/* 642/*
643 * readahead one full node of leaves
644 */
645static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
646 int slot)
647{
648 struct btrfs_node *node;
649 int i;
650 u32 nritems;
651 u64 item_objectid;
652 u64 blocknr;
653 u64 search;
654 u64 cluster_start;
655 int ret;
656 int nread = 0;
657 int direction = path->reada;
658 struct radix_tree_root found;
659 unsigned long gang[8];
660 struct buffer_head *bh;
661
662 if (!path->nodes[1])
663 return;
664
665 node = btrfs_buffer_node(path->nodes[1]);
666 search = btrfs_node_blockptr(node, slot);
667 bh = btrfs_find_tree_block(root, search);
668 if (bh) {
669 brelse(bh);
670 return;
671 }
672
673 init_bit_radix(&found);
674 nritems = btrfs_header_nritems(&node->header);
675 for (i = slot; i < nritems; i++) {
676 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
677 blocknr = btrfs_node_blockptr(node, i);
678 set_radix_bit(&found, blocknr);
679 }
680 if (direction > 0) {
681 cluster_start = search - 4;
682 if (cluster_start > search)
683 cluster_start = 0;
684 } else
685 cluster_start = search + 4;
686 while(1) {
687 ret = find_first_radix_bit(&found, gang, 0, ARRAY_SIZE(gang));
688 if (!ret)
689 break;
690 for (i = 0; i < ret; i++) {
691 blocknr = gang[i];
692 clear_radix_bit(&found, blocknr);
693 if (nread > 64)
694 continue;
695 if (direction > 0 && cluster_start <= blocknr &&
696 cluster_start + 8 > blocknr) {
697 cluster_start = blocknr;
698 readahead_tree_block(root, blocknr);
699 nread++;
700 } else if (direction < 0 && cluster_start >= blocknr &&
701 blocknr + 8 > cluster_start) {
702 cluster_start = blocknr;
703 readahead_tree_block(root, blocknr);
704 nread++;
705 }
706 }
707 }
708}
709/*
643 * look for key in the tree. path is filled in with nodes along the way 710 * look for key in the tree. path is filled in with nodes along the way
644 * if key is found, we return zero and you can find the item in the leaf 711 * if key is found, we return zero and you can find the item in the leaf
645 * level of the path (level 0) 712 * level of the path (level 0)
@@ -660,9 +727,11 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
660 struct buffer_head *cow_buf; 727 struct buffer_head *cow_buf;
661 struct btrfs_node *c; 728 struct btrfs_node *c;
662 struct btrfs_root_item *root_item = &root->root_item; 729 struct btrfs_root_item *root_item = &root->root_item;
730 u64 blocknr;
663 int slot; 731 int slot;
664 int ret; 732 int ret;
665 int level; 733 int level;
734 int should_reada = p->reada;
666 u8 lowest_level = 0; 735 u8 lowest_level = 0;
667 736
668 if (btrfs_root_refs(root_item) == 0 && root->ref_cows) { 737 if (btrfs_root_refs(root_item) == 0 && root->ref_cows) {
@@ -728,7 +797,11 @@ again:
728 /* this is only true while dropping a snapshot */ 797 /* this is only true while dropping a snapshot */
729 if (level == lowest_level) 798 if (level == lowest_level)
730 break; 799 break;
800 blocknr = btrfs_node_blockptr(c, slot);
801 if (level == 1 && should_reada)
802 reada_for_search(root, p, slot);
731 b = read_tree_block(root, btrfs_node_blockptr(c, slot)); 803 b = read_tree_block(root, btrfs_node_blockptr(c, slot));
804
732 } else { 805 } else {
733 struct btrfs_leaf *l = (struct btrfs_leaf *)c; 806 struct btrfs_leaf *l = (struct btrfs_leaf *)c;
734 p->slots[level] = slot; 807 p->slots[level] = slot;
@@ -1915,6 +1988,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1915 blocknr = btrfs_node_blockptr(c_node, slot); 1988 blocknr = btrfs_node_blockptr(c_node, slot);
1916 if (next) 1989 if (next)
1917 btrfs_block_release(root, next); 1990 btrfs_block_release(root, next);
1991 if (level == 1 && path->reada)
1992 reada_for_search(root, path, slot);
1918 next = read_tree_block(root, blocknr); 1993 next = read_tree_block(root, blocknr);
1919 break; 1994 break;
1920 } 1995 }
@@ -1927,6 +2002,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1927 path->slots[level] = 0; 2002 path->slots[level] = 0;
1928 if (!level) 2003 if (!level)
1929 break; 2004 break;
2005 if (level == 1 && path->reada)
2006 reada_for_search(root, path, slot);
1930 next = read_tree_block(root, 2007 next = read_tree_block(root,
1931 btrfs_node_blockptr(btrfs_buffer_node(next), 0)); 2008 btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1932 } 2009 }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 73c2e75a136d..c5a18d5d7f7c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -177,6 +177,7 @@ struct btrfs_node {
177struct btrfs_path { 177struct btrfs_path {
178 struct buffer_head *nodes[BTRFS_MAX_LEVEL]; 178 struct buffer_head *nodes[BTRFS_MAX_LEVEL];
179 int slots[BTRFS_MAX_LEVEL]; 179 int slots[BTRFS_MAX_LEVEL];
180 int reada;
180}; 181};
181 182
182/* 183/*
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 9455974dabea..5d4d5d8db8ef 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -32,33 +32,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
32static int del_pending_extents(struct btrfs_trans_handle *trans, struct 32static int del_pending_extents(struct btrfs_trans_handle *trans, struct
33 btrfs_root *extent_root); 33 btrfs_root *extent_root);
34 34
35static void reada_extent_leaves(struct btrfs_root *root,
36 struct btrfs_path *path, u64 limit)
37{
38 struct btrfs_node *node;
39 int i;
40 int nritems;
41 u64 item_objectid;
42 u64 blocknr;
43 int slot;
44 int ret;
45
46 if (!path->nodes[1])
47 return;
48 node = btrfs_buffer_node(path->nodes[1]);
49 slot = path->slots[1] + 1;
50 nritems = btrfs_header_nritems(&node->header);
51 for (i = slot; i < nritems && i < slot + 8; i++) {
52 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
53 if (item_objectid > limit)
54 break;
55 blocknr = btrfs_node_blockptr(node, i);
56 ret = readahead_tree_block(root, blocknr);
57 if (ret)
58 break;
59 }
60}
61
62static int cache_block_group(struct btrfs_root *root, 35static int cache_block_group(struct btrfs_root *root,
63 struct btrfs_block_group_cache *block_group) 36 struct btrfs_block_group_cache *block_group)
64{ 37{
@@ -84,6 +57,7 @@ static int cache_block_group(struct btrfs_root *root,
84 path = btrfs_alloc_path(); 57 path = btrfs_alloc_path();
85 if (!path) 58 if (!path)
86 return -ENOMEM; 59 return -ENOMEM;
60 path->reada = 1;
87 key.objectid = block_group->key.objectid; 61 key.objectid = block_group->key.objectid;
88 key.flags = 0; 62 key.flags = 0;
89 key.offset = 0; 63 key.offset = 0;
@@ -94,12 +68,10 @@ static int cache_block_group(struct btrfs_root *root,
94 if (ret && path->slots[0] > 0) 68 if (ret && path->slots[0] > 0)
95 path->slots[0]--; 69 path->slots[0]--;
96 limit = block_group->key.objectid + block_group->key.offset; 70 limit = block_group->key.objectid + block_group->key.offset;
97 reada_extent_leaves(root, path, limit);
98 while(1) { 71 while(1) {
99 leaf = btrfs_buffer_leaf(path->nodes[0]); 72 leaf = btrfs_buffer_leaf(path->nodes[0]);
100 slot = path->slots[0]; 73 slot = path->slots[0];
101 if (slot >= btrfs_header_nritems(&leaf->header)) { 74 if (slot >= btrfs_header_nritems(&leaf->header)) {
102 reada_extent_leaves(root, path, limit);
103 ret = btrfs_next_leaf(root, path); 75 ret = btrfs_next_leaf(root, path);
104 if (ret < 0) 76 if (ret < 0)
105 goto err; 77 goto err;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fa9c531c86b7..3889032fc449 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -375,40 +375,6 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans,
375} 375}
376 376
377/* 377/*
378 * truncates go from a high offset to a low offset. So, walk
379 * from hi to lo in the node and issue readas. Stop when you find
380 * keys from a different objectid
381 */
382static void reada_truncate(struct btrfs_root *root, struct btrfs_path *path,
383 u64 objectid)
384{
385 struct btrfs_node *node;
386 int i;
387 int nritems;
388 u64 item_objectid;
389 u64 blocknr;
390 int slot;
391 int ret;
392
393 if (!path->nodes[1])
394 return;
395 node = btrfs_buffer_node(path->nodes[1]);
396 slot = path->slots[1];
397 if (slot == 0)
398 return;
399 nritems = btrfs_header_nritems(&node->header);
400 for (i = slot - 1; i >= 0; i--) {
401 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
402 if (item_objectid != objectid)
403 break;
404 blocknr = btrfs_node_blockptr(node, i);
405 ret = readahead_tree_block(root, blocknr);
406 if (ret)
407 break;
408 }
409}
410
411/*
412 * this can truncate away extent items, csum items and directory items. 378 * this can truncate away extent items, csum items and directory items.
413 * It starts at a high offset and removes keys until it can't find 379 * It starts at a high offset and removes keys until it can't find
414 * any higher than i_size. 380 * any higher than i_size.
@@ -434,6 +400,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
434 int del_item; 400 int del_item;
435 401
436 path = btrfs_alloc_path(); 402 path = btrfs_alloc_path();
403 path->reada = -1;
437 BUG_ON(!path); 404 BUG_ON(!path);
438 /* FIXME, add redo link to tree so we don't leak on crash */ 405 /* FIXME, add redo link to tree so we don't leak on crash */
439 key.objectid = inode->i_ino; 406 key.objectid = inode->i_ino;
@@ -450,7 +417,6 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
450 BUG_ON(path->slots[0] == 0); 417 BUG_ON(path->slots[0] == 0);
451 path->slots[0]--; 418 path->slots[0]--;
452 } 419 }
453 reada_truncate(root, path, inode->i_ino);
454 leaf = btrfs_buffer_leaf(path->nodes[0]); 420 leaf = btrfs_buffer_leaf(path->nodes[0]);
455 found_key = &leaf->items[path->slots[0]].key; 421 found_key = &leaf->items[path->slots[0]].key;
456 found_type = btrfs_disk_key_type(found_key); 422 found_type = btrfs_disk_key_type(found_key);
@@ -827,36 +793,6 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
827 return d_splice_alias(inode, dentry); 793 return d_splice_alias(inode, dentry);
828} 794}
829 795
830/*
831 * readahead one full node of leaves as long as their keys include
832 * the objectid supplied
833 */
834static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path,
835 u64 objectid)
836{
837 struct btrfs_node *node;
838 int i;
839 u32 nritems;
840 u64 item_objectid;
841 u64 blocknr;
842 int slot;
843 int ret;
844
845 if (!path->nodes[1])
846 return;
847 node = btrfs_buffer_node(path->nodes[1]);
848 slot = path->slots[1];
849 nritems = btrfs_header_nritems(&node->header);
850 for (i = slot + 1; i < nritems; i++) {
851 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
852 if (item_objectid != objectid)
853 break;
854 blocknr = btrfs_node_blockptr(node, i);
855 ret = readahead_tree_block(root, blocknr);
856 if (ret)
857 break;
858 }
859}
860static unsigned char btrfs_filetype_table[] = { 796static unsigned char btrfs_filetype_table[] = {
861 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK 797 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
862}; 798};
@@ -890,18 +826,17 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
890 btrfs_set_key_type(&key, key_type); 826 btrfs_set_key_type(&key, key_type);
891 key.offset = filp->f_pos; 827 key.offset = filp->f_pos;
892 path = btrfs_alloc_path(); 828 path = btrfs_alloc_path();
829 path->reada = 1;
893 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 830 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
894 if (ret < 0) 831 if (ret < 0)
895 goto err; 832 goto err;
896 advance = 0; 833 advance = 0;
897 reada_leaves(root, path, inode->i_ino);
898 while(1) { 834 while(1) {
899 leaf = btrfs_buffer_leaf(path->nodes[0]); 835 leaf = btrfs_buffer_leaf(path->nodes[0]);
900 nritems = btrfs_header_nritems(&leaf->header); 836 nritems = btrfs_header_nritems(&leaf->header);
901 slot = path->slots[0]; 837 slot = path->slots[0];
902 if (advance || slot >= nritems) { 838 if (advance || slot >= nritems) {
903 if (slot >= nritems -1) { 839 if (slot >= nritems -1) {
904 reada_leaves(root, path, inode->i_ino);
905 ret = btrfs_next_leaf(root, path); 840 ret = btrfs_next_leaf(root, path);
906 if (ret) 841 if (ret)
907 break; 842 break;