summaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/btree.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-07-18 10:42:24 +0900
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-07-23 10:02:15 +0900
commit464ece88630d0fb715ca942eabb1da825046a534 (patch)
tree254185629ce58cf314c5b22b846969a3c26984ed /fs/nilfs2/btree.c
parent26dfdd8e29f28c08aa67861b3c83d0f3f7d30cee (diff)
downloadlinux-464ece88630d0fb715ca942eabb1da825046a534.tar.bz2
nilfs2: add btree get block function with readahead option
This adds __nilfs_btree_get_block() function that can issue a series of read-ahead requests for sibling btree nodes. This read-ahead needs parent node block, so nilfs_btree_readahead_info structure is added to pass the information that __nilfs_btree_get_block() needs. This also replaces the previous nilfs_btree_get_block() implementation with a wrapper function of __nilfs_btree_get_block(). Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/btree.c')
-rw-r--r--fs/nilfs2/btree.c94
1 files changed, 68 insertions, 26 deletions
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 4669389bf686..1b5321c0bcac 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -66,32 +66,6 @@ static void nilfs_btree_free_path(struct nilfs_btree_path *path)
/*
* B-tree node operations
*/
-static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
- struct buffer_head **bhp)
-{
- struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
- struct buffer_head *bh;
- sector_t pbn = 0;
- int err;
-
- err = nilfs_btnode_submit_block(btnc, ptr, pbn, READ, bhp, &pbn);
- if (err)
- return err == -EEXIST ? 0 : err;
-
- bh = *bhp;
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return -EIO;
- }
- if (nilfs_btree_broken_node_block(bh)) {
- clear_buffer_uptodate(bh);
- brelse(bh);
- return -EINVAL;
- }
- return 0;
-}
-
static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
__u64 ptr, struct buffer_head **bhp)
{
@@ -452,6 +426,74 @@ nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
return 0;
}
+struct nilfs_btree_readahead_info {
+ struct nilfs_btree_node *node; /* parent node */
+ int max_ra_blocks; /* max nof blocks to read ahead */
+ int index; /* current index on the parent node */
+ int ncmax; /* nof children in the parent node */
+};
+
+static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
+ struct buffer_head **bhp,
+ const struct nilfs_btree_readahead_info *ra)
+{
+ struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
+ struct buffer_head *bh, *ra_bh;
+ sector_t submit_ptr = 0;
+ int ret;
+
+ ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr);
+ if (ret) {
+ if (ret != -EEXIST)
+ return ret;
+ goto out_check;
+ }
+
+ if (ra) {
+ int i, n;
+ __u64 ptr2;
+
+ /* read ahead sibling nodes */
+ for (n = ra->max_ra_blocks, i = ra->index + 1;
+ n > 0 && i < ra->ncmax; n--, i++) {
+ ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax);
+
+ ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA,
+ &ra_bh, &submit_ptr);
+ if (likely(!ret || ret == -EEXIST))
+ brelse(ra_bh);
+ else if (ret != -EBUSY)
+ break;
+ if (!buffer_locked(bh))
+ goto out_no_wait;
+ }
+ }
+
+ wait_on_buffer(bh);
+
+ out_no_wait:
+ if (!buffer_uptodate(bh)) {
+ brelse(bh);
+ return -EIO;
+ }
+
+ out_check:
+ if (nilfs_btree_broken_node_block(bh)) {
+ clear_buffer_uptodate(bh);
+ brelse(bh);
+ return -EINVAL;
+ }
+
+ *bhp = bh;
+ return 0;
+}
+
+static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
+ struct buffer_head **bhp)
+{
+ return __nilfs_btree_get_block(btree, ptr, bhp, NULL);
+}
+
static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
struct nilfs_btree_path *path,
__u64 key, __u64 *ptrp, int minlevel)