NFSv4: Eliminate nfs4_path_walk()
[safe/jmp/linux-2.6] / fs / nilfs2 / btree.c
index 115b157..76c38e3 100644 (file)
@@ -114,7 +114,18 @@ static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
 {
        struct address_space *btnc =
                &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
-       return nilfs_btnode_get(btnc, ptr, 0, bhp, 0);
+       int err;
+
+       err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
+       if (err)
+               return err == -EEXIST ? 0 : err;
+
+       wait_on_buffer(*bhp);
+       if (!buffer_uptodate(*bhp)) {
+               brelse(*bhp);
+               return -EIO;
+       }
+       return 0;
 }
 
 static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
@@ -122,12 +133,15 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
 {
        struct address_space *btnc =
                &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
-       int ret;
+       struct buffer_head *bh;
 
-       ret = nilfs_btnode_get(btnc, ptr, 0, bhp, 1);
-       if (!ret)
-               set_buffer_nilfs_volatile(*bhp);
-       return ret;
+       bh = nilfs_btnode_create_block(btnc, ptr);
+       if (!bh)
+               return -ENOMEM;
+
+       set_buffer_nilfs_volatile(bh);
+       *bhp = bh;
+       return 0;
 }
 
 static inline int
@@ -444,6 +458,18 @@ nilfs_btree_get_node(const struct nilfs_btree *btree,
                nilfs_btree_get_nonroot_node(path, level);
 }
 
+static inline int
+nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
+{
+       if (unlikely(nilfs_btree_node_get_level(node) != level)) {
+               dump_stack();
+               printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
+                      nilfs_btree_node_get_level(node), level);
+               return 1;
+       }
+       return 0;
+}
+
 static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
                                 struct nilfs_btree_path *path,
                                 __u64 key, __u64 *ptrp, int minlevel)
@@ -467,7 +493,8 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
                if (ret < 0)
                        return ret;
                node = nilfs_btree_get_nonroot_node(path, level);
-               BUG_ON(level != nilfs_btree_node_get_level(node));
+               if (nilfs_btree_bad_node(node, level))
+                       return -EINVAL;
                if (!found)
                        found = nilfs_btree_node_lookup(node, key, &index);
                else
@@ -512,7 +539,8 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
                if (ret < 0)
                        return ret;
                node = nilfs_btree_get_nonroot_node(path, level);
-               BUG_ON(level != nilfs_btree_node_get_level(node));
+               if (nilfs_btree_bad_node(node, level))
+                       return -EINVAL;
                index = nilfs_btree_node_get_nchildren(node) - 1;
                ptr = nilfs_btree_node_get_ptr(btree, node, index);
                path[level].bp_index = index;
@@ -638,13 +666,11 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree,
 {
        if (level < nilfs_btree_height(btree) - 1) {
                do {
-                       lock_buffer(path[level].bp_bh);
                        nilfs_btree_node_set_key(
                                nilfs_btree_get_nonroot_node(path, level),
                                path[level].bp_index, key);
                        if (!buffer_dirty(path[level].bp_bh))
                                nilfs_btnode_mark_dirty(path[level].bp_bh);
-                       unlock_buffer(path[level].bp_bh);
                } while ((path[level].bp_index == 0) &&
                         (++level < nilfs_btree_height(btree) - 1));
        }
@@ -663,13 +689,11 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree,
        struct nilfs_btree_node *node;
 
        if (level < nilfs_btree_height(btree) - 1) {
-               lock_buffer(path[level].bp_bh);
                node = nilfs_btree_get_nonroot_node(path, level);
                nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
                                        path[level].bp_index);
                if (!buffer_dirty(path[level].bp_bh))
                        nilfs_btnode_mark_dirty(path[level].bp_bh);
-               unlock_buffer(path[level].bp_bh);
 
                if (path[level].bp_index == 0)
                        nilfs_btree_promote_key(btree, path, level + 1,
@@ -689,9 +713,6 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
        struct nilfs_btree_node *node, *left;
        int nchildren, lnchildren, n, move;
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        left = nilfs_btree_get_sib_node(path, level);
        nchildren = nilfs_btree_node_get_nchildren(node);
@@ -712,9 +733,6 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        nilfs_btree_promote_key(btree, path, level + 1,
                                nilfs_btree_node_get_key(node, 0));
 
@@ -740,9 +758,6 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
        struct nilfs_btree_node *node, *right;
        int nchildren, rnchildren, n, move;
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        right = nilfs_btree_get_sib_node(path, level);
        nchildren = nilfs_btree_node_get_nchildren(node);
@@ -763,9 +778,6 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        path[level + 1].bp_index++;
        nilfs_btree_promote_key(btree, path, level + 1,
                                nilfs_btree_node_get_key(right, 0));
@@ -794,9 +806,6 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
        __u64 newptr;
        int nchildren, n, move;
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        right = nilfs_btree_get_sib_node(path, level);
        nchildren = nilfs_btree_node_get_nchildren(node);
@@ -815,9 +824,6 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        newkey = nilfs_btree_node_get_key(right, 0);
        newptr = path[level].bp_newreq.bpr_ptr;
 
@@ -852,8 +858,6 @@ static void nilfs_btree_grow(struct nilfs_btree *btree,
        struct nilfs_btree_node *root, *child;
        int n;
 
-       lock_buffer(path[level].bp_sib_bh);
-
        root = nilfs_btree_get_root(btree);
        child = nilfs_btree_get_sib_node(path, level);
 
@@ -865,8 +869,6 @@ static void nilfs_btree_grow(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_sib_bh);
-
        path[level].bp_bh = path[level].bp_sib_bh;
        path[level].bp_sib_bh = NULL;
 
@@ -940,17 +942,20 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
        struct nilfs_btree_node *node, *parent, *sib;
        __u64 sibptr;
        int pindex, level, ret;
+       struct inode *dat = NULL;
 
        stats->bs_nblocks = 0;
        level = NILFS_BTREE_LEVEL_DATA;
 
        /* allocate a new ptr for data block */
-       if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
+       if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
                path[level].bp_newreq.bpr_ptr =
                        nilfs_btree_find_target_v(btree, path, key);
+               dat = nilfs_bmap_get_dat(&btree->bt_bmap);
+       }
 
        ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
-                                          &path[level].bp_newreq);
+                                          &path[level].bp_newreq, dat);
        if (ret < 0)
                goto err_out_data;
 
@@ -1009,7 +1014,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
                path[level].bp_newreq.bpr_ptr =
                        path[level - 1].bp_newreq.bpr_ptr + 1;
                ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
-                                                  &path[level].bp_newreq);
+                                                  &path[level].bp_newreq, dat);
                if (ret < 0)
                        goto err_out_child_node;
                ret = nilfs_btree_get_new_block(btree,
@@ -1020,11 +1025,9 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
 
                stats->bs_nblocks++;
 
-               lock_buffer(bh);
                nilfs_btree_node_init(btree,
                                      (struct nilfs_btree_node *)bh->b_data,
                                      0, level, 0, NULL, NULL);
-               unlock_buffer(bh);
                path[level].bp_sib_bh = bh;
                path[level].bp_op = nilfs_btree_split;
        }
@@ -1041,7 +1044,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
        /* grow */
        path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
        ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
-                                          &path[level].bp_newreq);
+                                          &path[level].bp_newreq, dat);
        if (ret < 0)
                goto err_out_child_node;
        ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
@@ -1049,10 +1052,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
        if (ret < 0)
                goto err_out_curr_node;
 
-       lock_buffer(bh);
        nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
                              0, level, 0, NULL, NULL);
-       unlock_buffer(bh);
        path[level].bp_sib_bh = bh;
        path[level].bp_op = nilfs_btree_grow;
 
@@ -1069,16 +1070,18 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
 
        /* error */
  err_out_curr_node:
-       nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
+       nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
+                                  dat);
  err_out_child_node:
        for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
                nilfs_btnode_delete(path[level].bp_sib_bh);
                nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
-                                          &path[level].bp_newreq);
+                                          &path[level].bp_newreq, dat);
 
        }
 
-       nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
+       nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
+                                  dat);
  err_out_data:
        *levelp = level;
        stats->bs_nblocks = 0;
@@ -1089,16 +1092,19 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
                                      struct nilfs_btree_path *path,
                                      int maxlevel, __u64 key, __u64 ptr)
 {
+       struct inode *dat = NULL;
        int level;
 
        set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
        ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
-       if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
+       if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
                nilfs_btree_set_target_v(btree, key, ptr);
+               dat = nilfs_bmap_get_dat(&btree->bt_bmap);
+       }
 
        for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
                nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
-                                           &path[level - 1].bp_newreq);
+                                           &path[level - 1].bp_newreq, dat);
                path[level].bp_op(btree, path, level, &key, &ptr);
        }
 
@@ -1146,13 +1152,11 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree,
        struct nilfs_btree_node *node;
 
        if (level < nilfs_btree_height(btree) - 1) {
-               lock_buffer(path[level].bp_bh);
                node = nilfs_btree_get_nonroot_node(path, level);
                nilfs_btree_node_delete(btree, node, keyp, ptrp,
                                        path[level].bp_index);
                if (!buffer_dirty(path[level].bp_bh))
                        nilfs_btnode_mark_dirty(path[level].bp_bh);
-               unlock_buffer(path[level].bp_bh);
                if (path[level].bp_index == 0)
                        nilfs_btree_promote_key(btree, path, level + 1,
                                nilfs_btree_node_get_key(node, 0));
@@ -1172,9 +1176,6 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
 
        nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        left = nilfs_btree_get_sib_node(path, level);
        nchildren = nilfs_btree_node_get_nchildren(node);
@@ -1189,9 +1190,6 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        nilfs_btree_promote_key(btree, path, level + 1,
                                nilfs_btree_node_get_key(node, 0));
 
@@ -1209,9 +1207,6 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
 
        nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        right = nilfs_btree_get_sib_node(path, level);
        nchildren = nilfs_btree_node_get_nchildren(node);
@@ -1226,9 +1221,6 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        path[level + 1].bp_index++;
        nilfs_btree_promote_key(btree, path, level + 1,
                                nilfs_btree_node_get_key(right, 0));
@@ -1247,9 +1239,6 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
 
        nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        left = nilfs_btree_get_sib_node(path, level);
 
@@ -1260,9 +1249,6 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_sib_bh))
                nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        nilfs_btnode_delete(path[level].bp_bh);
        path[level].bp_bh = path[level].bp_sib_bh;
        path[level].bp_sib_bh = NULL;
@@ -1278,9 +1264,6 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree,
 
        nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
 
-       lock_buffer(path[level].bp_bh);
-       lock_buffer(path[level].bp_sib_bh);
-
        node = nilfs_btree_get_nonroot_node(path, level);
        right = nilfs_btree_get_sib_node(path, level);
 
@@ -1291,9 +1274,6 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree,
        if (!buffer_dirty(path[level].bp_bh))
                nilfs_btnode_mark_dirty(path[level].bp_bh);
 
-       unlock_buffer(path[level].bp_bh);
-       unlock_buffer(path[level].bp_sib_bh);
-
        nilfs_btnode_delete(path[level].bp_sib_bh);
        path[level].bp_sib_bh = NULL;
        path[level + 1].bp_index++;
@@ -1308,7 +1288,6 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
 
        nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
 
-       lock_buffer(path[level].bp_bh);
        root = nilfs_btree_get_root(btree);
        child = nilfs_btree_get_nonroot_node(path, level);
 
@@ -1316,7 +1295,6 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
        nilfs_btree_node_set_level(root, level);
        n = nilfs_btree_node_get_nchildren(child);
        nilfs_btree_node_move_left(btree, root, child, n);
-       unlock_buffer(path[level].bp_bh);
 
        nilfs_btnode_delete(path[level].bp_bh);
        path[level].bp_bh = NULL;
@@ -1326,7 +1304,8 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
 static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
                                      struct nilfs_btree_path *path,
                                      int *levelp,
-                                     struct nilfs_bmap_stats *stats)
+                                     struct nilfs_bmap_stats *stats,
+                                     struct inode *dat)
 {
        struct buffer_head *bh;
        struct nilfs_btree_node *node, *parent, *sib;
@@ -1343,7 +1322,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
                        nilfs_btree_node_get_ptr(btree, node,
                                                 path[level].bp_index);
                ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
-                                                &path[level].bp_oldreq);
+                                                &path[level].bp_oldreq, dat);
                if (ret < 0)
                        goto err_out_child_node;
 
@@ -1421,7 +1400,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
                nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
 
        ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
-                                        &path[level].bp_oldreq);
+                                        &path[level].bp_oldreq, dat);
        if (ret < 0)
                goto err_out_child_node;
 
@@ -1436,12 +1415,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
 
        /* error */
  err_out_curr_node:
-       nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq);
+       nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
  err_out_child_node:
        for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
                brelse(path[level].bp_sib_bh);
                nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
-                                        &path[level].bp_oldreq);
+                                        &path[level].bp_oldreq, dat);
        }
        *levelp = level;
        stats->bs_nblocks = 0;
@@ -1450,13 +1429,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
 
 static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
                                      struct nilfs_btree_path *path,
-                                     int maxlevel)
+                                     int maxlevel, struct inode *dat)
 {
        int level;
 
        for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
                nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
-                                         &path[level].bp_oldreq);
+                                         &path[level].bp_oldreq, dat);
                path[level].bp_op(btree, path, level, NULL, NULL);
        }
 
@@ -1470,6 +1449,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
        struct nilfs_btree *btree;
        struct nilfs_btree_path *path;
        struct nilfs_bmap_stats stats;
+       struct inode *dat;
        int level, ret;
 
        btree = (struct nilfs_btree *)bmap;
@@ -1482,10 +1462,14 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
        if (ret < 0)
                goto out;
 
-       ret = nilfs_btree_prepare_delete(btree, path, &level, &stats);
+
+       dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
+               nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
+
+       ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
        if (ret < 0)
                goto out;
-       nilfs_btree_commit_delete(btree, path, level);
+       nilfs_btree_commit_delete(btree, path, level, dat);
        nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
 
 out:
@@ -1610,18 +1594,20 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
                                       struct nilfs_bmap_stats *stats)
 {
        struct buffer_head *bh;
-       struct nilfs_btree *btree;
+       struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
+       struct inode *dat = NULL;
        int ret;
 
-       btree = (struct nilfs_btree *)bmap;
        stats->bs_nblocks = 0;
 
        /* for data */
        /* cannot find near ptr */
-       if (NILFS_BMAP_USE_VBN(bmap))
+       if (NILFS_BMAP_USE_VBN(bmap)) {
                dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
+               dat = nilfs_bmap_get_dat(bmap);
+       }
 
-       ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq);
+       ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
        if (ret < 0)
                return ret;
 
@@ -1629,7 +1615,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
        stats->bs_nblocks++;
        if (nreq != NULL) {
                nreq->bpr_ptr = dreq->bpr_ptr + 1;
-               ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq);
+               ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
                if (ret < 0)
                        goto err_out_dreq;
 
@@ -1646,9 +1632,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
 
        /* error */
  err_out_nreq:
-       nilfs_bmap_abort_alloc_ptr(bmap, nreq);
+       nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
  err_out_dreq:
-       nilfs_bmap_abort_alloc_ptr(bmap, dreq);
+       nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
        stats->bs_nblocks = 0;
        return ret;
 
@@ -1663,8 +1649,9 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
                                      union nilfs_bmap_ptr_req *nreq,
                                      struct buffer_head *bh)
 {
-       struct nilfs_btree *btree;
+       struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
        struct nilfs_btree_node *node;
+       struct inode *dat;
        __u64 tmpptr;
 
        /* free resources */
@@ -1675,14 +1662,13 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
        set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
 
        /* convert and insert */
-       btree = (struct nilfs_btree *)bmap;
+       dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
        nilfs_btree_init(bmap);
        if (nreq != NULL) {
-               nilfs_bmap_commit_alloc_ptr(bmap, dreq);
-               nilfs_bmap_commit_alloc_ptr(bmap, nreq);
+               nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
+               nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
 
                /* create child node at level 1 */
-               lock_buffer(bh);
                node = (struct nilfs_btree_node *)bh->b_data;
                nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
                nilfs_btree_node_insert(btree, node,
@@ -1692,7 +1678,6 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
                if (!nilfs_bmap_dirty(bmap))
                        nilfs_bmap_set_dirty(bmap);
 
-               unlock_buffer(bh);
                brelse(bh);
 
                /* create root node at level 2 */
@@ -1701,7 +1686,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
                nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
                                      2, 1, &keys[0], &tmpptr);
        } else {
-               nilfs_bmap_commit_alloc_ptr(bmap, dreq);
+               nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
 
                /* create root node at level 1 */
                node = nilfs_btree_get_root(btree);
@@ -1772,7 +1757,7 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
 
 static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
                                        struct nilfs_btree_path *path,
-                                       int level)
+                                       int level, struct inode *dat)
 {
        struct nilfs_btree_node *parent;
        int ret;
@@ -1782,9 +1767,8 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
                nilfs_btree_node_get_ptr(btree, parent,
                                         path[level + 1].bp_index);
        path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
-       ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap,
-                                         &path[level].bp_oldreq,
-                                         &path[level].bp_newreq);
+       ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
+                                      &path[level].bp_newreq.bpr_req);
        if (ret < 0)
                return ret;
 
@@ -1796,9 +1780,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
                        &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
                        &path[level].bp_ctxt);
                if (ret < 0) {
-                       nilfs_bmap_abort_update_v(&btree->bt_bmap,
-                                                 &path[level].bp_oldreq,
-                                                 &path[level].bp_newreq);
+                       nilfs_dat_abort_update(dat,
+                                              &path[level].bp_oldreq.bpr_req,
+                                              &path[level].bp_newreq.bpr_req);
                        return ret;
                }
        }
@@ -1808,13 +1792,13 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
 
 static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
                                        struct nilfs_btree_path *path,
-                                       int level)
+                                       int level, struct inode *dat)
 {
        struct nilfs_btree_node *parent;
 
-       nilfs_bmap_commit_update_v(&btree->bt_bmap,
-                                  &path[level].bp_oldreq,
-                                  &path[level].bp_newreq);
+       nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
+                               &path[level].bp_newreq.bpr_req,
+                               btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
 
        if (buffer_nilfs_node(path[level].bp_bh)) {
                nilfs_btnode_commit_change_key(
@@ -1831,11 +1815,10 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
 
 static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
                                       struct nilfs_btree_path *path,
-                                      int level)
+                                      int level, struct inode *dat)
 {
-       nilfs_bmap_abort_update_v(&btree->bt_bmap,
-                                 &path[level].bp_oldreq,
-                                 &path[level].bp_newreq);
+       nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
+                              &path[level].bp_newreq.bpr_req);
        if (buffer_nilfs_node(path[level].bp_bh))
                nilfs_btnode_abort_change_key(
                        &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
@@ -1844,14 +1827,14 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
 
 static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
                                           struct nilfs_btree_path *path,
-                                          int minlevel,
-                                          int *maxlevelp)
+                                          int minlevel, int *maxlevelp,
+                                          struct inode *dat)
 {
        int level, ret;
 
        level = minlevel;
        if (!buffer_nilfs_volatile(path[level].bp_bh)) {
-               ret = nilfs_btree_prepare_update_v(btree, path, level);
+               ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
                if (ret < 0)
                        return ret;
        }
@@ -1859,7 +1842,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
               !buffer_dirty(path[level].bp_bh)) {
 
                WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
-               ret = nilfs_btree_prepare_update_v(btree, path, level);
+               ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
                if (ret < 0)
                        goto out;
        }
@@ -1871,39 +1854,40 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
        /* error */
  out:
        while (--level > minlevel)
-               nilfs_btree_abort_update_v(btree, path, level);
+               nilfs_btree_abort_update_v(btree, path, level, dat);
        if (!buffer_nilfs_volatile(path[level].bp_bh))
-               nilfs_btree_abort_update_v(btree, path, level);
+               nilfs_btree_abort_update_v(btree, path, level, dat);
        return ret;
 }
 
 static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
                                           struct nilfs_btree_path *path,
-                                          int minlevel,
-                                          int maxlevel,
-                                          struct buffer_head *bh)
+                                          int minlevel, int maxlevel,
+                                          struct buffer_head *bh,
+                                          struct inode *dat)
 {
        int level;
 
        if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
-               nilfs_btree_commit_update_v(btree, path, minlevel);
+               nilfs_btree_commit_update_v(btree, path, minlevel, dat);
 
        for (level = minlevel + 1; level <= maxlevel; level++)
-               nilfs_btree_commit_update_v(btree, path, level);
+               nilfs_btree_commit_update_v(btree, path, level, dat);
 }
 
 static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
                                   struct nilfs_btree_path *path,
-                                  int level,
-                                  struct buffer_head *bh)
+                                  int level, struct buffer_head *bh)
 {
-       int maxlevel, ret;
+       int maxlevel = 0, ret;
        struct nilfs_btree_node *parent;
+       struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
        __u64 ptr;
 
        get_bh(bh);
        path[level].bp_bh = bh;
-       ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel);
+       ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
+                                             dat);
        if (ret < 0)
                goto out;
 
@@ -1911,12 +1895,12 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
                parent = nilfs_btree_get_node(btree, path, level + 1);
                ptr = nilfs_btree_node_get_ptr(btree, parent,
                                               path[level + 1].bp_index);
-               ret = nilfs_bmap_mark_dirty(&btree->bt_bmap, ptr);
+               ret = nilfs_dat_mark_dirty(dat, ptr);
                if (ret < 0)
                        goto out;
        }
 
-       nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh);
+       nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
 
  out:
        brelse(path[level].bp_bh);
@@ -1972,7 +1956,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
 static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
                                    struct buffer_head *bh)
 {
-       return nilfs_bmap_mark_dirty(bmap, bh->b_blocknr);
+       return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
 }
 
 static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
@@ -2034,7 +2018,7 @@ static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
        for (level = NILFS_BTREE_LEVEL_NODE_MIN;
             level < NILFS_BTREE_LEVEL_MAX;
             level++)
-               list_splice(&lists[level], listp->prev);
+               list_splice_tail(&lists[level], listp);
 }
 
 static int nilfs_btree_assign_p(struct nilfs_btree *btree,
@@ -2086,6 +2070,7 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
                                union nilfs_binfo *binfo)
 {
        struct nilfs_btree_node *parent;
+       struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
        __u64 key;
        __u64 ptr;
        union nilfs_bmap_ptr_req req;
@@ -2095,9 +2080,10 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
        ptr = nilfs_btree_node_get_ptr(btree, parent,
                                       path[level + 1].bp_index);
        req.bpr_ptr = ptr;
-       ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr);
-       if (unlikely(ret < 0))
+       ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
+       if (ret < 0)
                return ret;
+       nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
 
        key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
        /* on-disk format */
@@ -2155,13 +2141,12 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
                                 sector_t blocknr,
                                 union nilfs_binfo *binfo)
 {
-       struct nilfs_btree *btree;
        struct nilfs_btree_node *node;
        __u64 key;
        int ret;
 
-       btree = (struct nilfs_btree *)bmap;
-       ret = nilfs_bmap_move_v(bmap, (*bh)->b_blocknr, blocknr);
+       ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
+                            blocknr);
        if (ret < 0)
                return ret;