diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-08-07 15:52:22 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-08-07 15:52:22 -0400 |
commit | 3c69faecb8d83cb2ef085a98b196a3fecea67725 (patch) | |
tree | d764502dd93bcd767c2130518d0c1fe00a7e96ff /fs/btrfs/ctree.c | |
parent | 9f3a742736cecda5a8778be70faa2f779458839f (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.c | 77 |
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 | */ | ||
645 | static 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 | } |