static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
                                 struct nilfs_btree_path *path,
-                                __u64 key, __u64 *ptrp, int minlevel)
+                                __u64 key, __u64 *ptrp, int minlevel,
+                                int readahead)
 {
        struct nilfs_btree_node *node;
+       struct nilfs_btree_readahead_info p, *ra;
        __u64 ptr;
        int level, index, found, ncmax, ret;
 
 
        ncmax = nilfs_btree_nchildren_per_block(btree);
 
-       for (level--; level >= minlevel; level--) {
-               ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
+       while (--level >= minlevel) {
+               ra = NULL;
+               if (level == NILFS_BTREE_LEVEL_NODE_MIN && readahead) {
+                       p.node = nilfs_btree_get_node(btree, path, level + 1,
+                                                     &p.ncmax);
+                       p.index = index;
+                       p.max_ra_blocks = 7;
+                       ra = &p;
+               }
+               ret = __nilfs_btree_get_block(btree, ptr, &path[level].bp_bh,
+                                             ra);
                if (ret < 0)
                        return ret;
+
                node = nilfs_btree_get_nonroot_node(path, level);
                if (nilfs_btree_bad_node(node, level))
                        return -EINVAL;
        if (path == NULL)
                return -ENOMEM;
 
-       ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level);
+       ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level, 0);
 
        nilfs_btree_free_path(path);
 
        sector_t blocknr;
        int level = NILFS_BTREE_LEVEL_NODE_MIN;
        int ret, cnt, index, maxlevel, ncmax;
+       struct nilfs_btree_readahead_info p;
 
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
 
-       ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
+       ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level, 1);
        if (ret < 0)
                goto out;
 
                        break;
 
                /* look-up right sibling node */
-               node = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
-               index = path[level + 1].bp_index + 1;
-               if (index >= nilfs_btree_node_get_nchildren(node) ||
-                   nilfs_btree_node_get_key(node, index) != key + cnt)
+               p.node = nilfs_btree_get_node(btree, path, level + 1, &p.ncmax);
+               p.index = path[level + 1].bp_index + 1;
+               p.max_ra_blocks = 7;
+               if (p.index >= nilfs_btree_node_get_nchildren(p.node) ||
+                   nilfs_btree_node_get_key(p.node, p.index) != key + cnt)
                        break;
-               ptr2 = nilfs_btree_node_get_ptr(node, index, ncmax);
-               path[level + 1].bp_index = index;
+               ptr2 = nilfs_btree_node_get_ptr(p.node, p.index, p.ncmax);
+               path[level + 1].bp_index = p.index;
 
                brelse(path[level].bp_bh);
                path[level].bp_bh = NULL;
-               ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
+
+               ret = __nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh,
+                                             &p);
                if (ret < 0)
                        goto out;
                node = nilfs_btree_get_nonroot_node(path, level);
                return -ENOMEM;
 
        ret = nilfs_btree_do_lookup(btree, path, key, NULL,
-                                   NILFS_BTREE_LEVEL_NODE_MIN);
+                                   NILFS_BTREE_LEVEL_NODE_MIN, 0);
        if (ret != -ENOENT) {
                if (ret == 0)
                        ret = -EEXIST;
                return -ENOMEM;
 
        ret = nilfs_btree_do_lookup(btree, path, key, NULL,
-                                   NILFS_BTREE_LEVEL_NODE_MIN);
+                                   NILFS_BTREE_LEVEL_NODE_MIN, 0);
        if (ret < 0)
                goto out;
 
                level = NILFS_BTREE_LEVEL_DATA;
        }
 
-       ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
+       ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
        if (ret < 0) {
                if (unlikely(ret == -ENOENT))
                        printk(KERN_CRIT "%s: key = %llu, level == %d\n",
                level = NILFS_BTREE_LEVEL_DATA;
        }
 
-       ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
+       ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
        if (ret < 0) {
                WARN_ON(ret == -ENOENT);
                goto out;
        if (path == NULL)
                return -ENOMEM;
 
-       ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
+       ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1, 0);
        if (ret < 0) {
                WARN_ON(ret == -ENOENT);
                goto out;