aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
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/ctree.c
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/ctree.c')
-rw-r--r--fs/btrfs/ctree.c77
1 files changed, 77 insertions, 0 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 }