Merge branch 'bkl/ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[safe/jmp/linux-2.6] / fs / nilfs2 / btree.c
index 7b0cc4f..b27a342 100644 (file)
 #include "alloc.h"
 #include "dat.h"
 
-/**
- * struct nilfs_btree_path - A path on which B-tree operations are executed
- * @bp_bh: buffer head of node block
- * @bp_sib_bh: buffer head of sibling node block
- * @bp_index: index of child node
- * @bp_oldreq: ptr end request for old ptr
- * @bp_newreq: ptr alloc request for new ptr
- * @bp_op: rebalance operation
- */
-struct nilfs_btree_path {
-       struct buffer_head *bp_bh;
-       struct buffer_head *bp_sib_bh;
-       int bp_index;
-       union nilfs_bmap_ptr_req bp_oldreq;
-       union nilfs_bmap_ptr_req bp_newreq;
-       struct nilfs_btnode_chkey_ctxt bp_ctxt;
-       void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *,
-                     int, __u64 *, __u64 *);
-};
-
-/*
- * B-tree path operations
- */
-
-static struct kmem_cache *nilfs_btree_path_cache;
-
-int __init nilfs_btree_path_cache_init(void)
+static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
 {
-       nilfs_btree_path_cache =
-               kmem_cache_create("nilfs2_btree_path_cache",
-                                 sizeof(struct nilfs_btree_path) *
-                                 NILFS_BTREE_LEVEL_MAX, 0, 0, NULL);
-       return (nilfs_btree_path_cache != NULL) ? 0 : -ENOMEM;
-}
-
-void nilfs_btree_path_cache_destroy(void)
-{
-       kmem_cache_destroy(nilfs_btree_path_cache);
-}
-
-static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void)
-{
-       return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
-}
-
-static inline void nilfs_btree_free_path(struct nilfs_btree_path *path)
-{
-       kmem_cache_free(nilfs_btree_path_cache, path);
-}
+       struct nilfs_btree_path *path;
+       int level = NILFS_BTREE_LEVEL_DATA;
 
-static void nilfs_btree_init_path(struct nilfs_btree_path *path)
-{
-       int level;
+       path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
+       if (path == NULL)
+               goto out;
 
-       for (level = NILFS_BTREE_LEVEL_DATA;
-            level < NILFS_BTREE_LEVEL_MAX;
-            level++) {
+       for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
                path[level].bp_bh = NULL;
                path[level].bp_sib_bh = NULL;
                path[level].bp_index = 0;
@@ -95,15 +48,19 @@ static void nilfs_btree_init_path(struct nilfs_btree_path *path)
                path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
                path[level].bp_op = NULL;
        }
+
+out:
+       return path;
 }
 
-static void nilfs_btree_release_path(struct nilfs_btree_path *path)
+static void nilfs_btree_free_path(struct nilfs_btree_path *path)
 {
-       int level;
+       int level = NILFS_BTREE_LEVEL_DATA;
 
-       for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX;
-            level++)
+       for (; level < NILFS_BTREE_LEVEL_MAX; level++)
                brelse(path[level].bp_bh);
+
+       kmem_cache_free(nilfs_btree_path_cache, path);
 }
 
 /*
@@ -114,7 +71,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,
@@ -555,14 +523,12 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
 
        if (ptrp != NULL)
                *ptrp = ptr;
 
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
 
        return ret;
@@ -583,7 +549,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
+
        ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
        if (ret < 0)
                goto out;
@@ -644,7 +610,6 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
        *ptrp = ptr;
        ret = cnt;
  out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
        return ret;
 }
@@ -1112,7 +1077,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        ret = nilfs_btree_do_lookup(btree, path, key, NULL,
                                    NILFS_BTREE_LEVEL_NODE_MIN);
@@ -1129,7 +1093,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
        nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
 
  out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
        return ret;
 }
@@ -1445,7 +1408,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
+
        ret = nilfs_btree_do_lookup(btree, path, key, NULL,
                                    NILFS_BTREE_LEVEL_NODE_MIN);
        if (ret < 0)
@@ -1462,7 +1425,6 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
        nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
 
 out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
        return ret;
 }
@@ -1477,11 +1439,9 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
 
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
 
        return ret;
@@ -1868,7 +1828,7 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
                                   struct nilfs_btree_path *path,
                                   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;
@@ -1912,7 +1872,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        if (buffer_nilfs_node(bh)) {
                node = (struct nilfs_btree_node *)bh->b_data;
@@ -1936,7 +1895,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
                nilfs_btree_propagate_p(btree, path, level, bh);
 
  out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
 
        return ret;
@@ -2007,7 +1965,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,
@@ -2097,7 +2055,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        if (buffer_nilfs_node(*bh)) {
                node = (struct nilfs_btree_node *)(*bh)->b_data;
@@ -2119,7 +2076,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
                nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
 
  out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
 
        return ret;
@@ -2164,7 +2120,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
        path = nilfs_btree_alloc_path();
        if (path == NULL)
                return -ENOMEM;
-       nilfs_btree_init_path(path);
 
        ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
        if (ret < 0) {
@@ -2184,7 +2139,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
                nilfs_bmap_set_dirty(&btree->bt_bmap);
 
  out:
-       nilfs_btree_release_path(path);
        nilfs_btree_free_path(path);
        return ret;
 }