Btrfs: Fixup reference counting on cows
authorChris Mason <chris.mason@oracle.com>
Wed, 7 Mar 2007 01:08:01 +0000 (20:08 -0500)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Wed, 7 Mar 2007 01:08:01 +0000 (20:08 -0500)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/Makefile
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/print-tree.c
fs/btrfs/quick-test.c
fs/btrfs/random-test.c

index 756b1cd4cf4dc95cd295b60707ed1385ebdb0b85..ae7f4c00c39cd6a87a0ef88534b487b904bca609 100644 (file)
@@ -1,7 +1,7 @@
 
 CC=gcc
 CFLAGS = -g -Wall
-headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h
+headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
 objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o
 
 # if you don't have sparse installed, use ls instead
index 1118986d7569f07720d71b456a6a410c1e4b693d..72816381d2031e19c5a2ca786ec557b8705badda 100644 (file)
@@ -50,16 +50,17 @@ int btrfs_cow_block(struct ctree_root *root,
        memcpy(&cow->node, &buf->node, sizeof(buf->node));
        cow->node.header.blocknr = cow->blocknr;
        *cow_ret = cow;
+       btrfs_inc_ref(root, buf);
        if (buf == root->node) {
                root->node = cow;
                cow->count++;
+               if (buf != root->commit_root)
+                       free_extent(root, buf->blocknr, 1);
                tree_block_release(root, buf);
        } else {
                parent->node.blockptrs[parent_slot] = cow->blocknr;
                BUG_ON(list_empty(&parent->dirty));
-       }
-       if (0 && root != root->extent_root && !is_leaf(cow->node.header.flags)) {
-               btrfs_inc_ref(root, cow);
+               free_extent(root, buf->blocknr, 1);
        }
        tree_block_release(root, buf);
        return 0;
@@ -1018,7 +1019,6 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path,
        slot = path->slots[0];
        nritems = l->header.nritems;
        mid = (nritems + 1)/ 2;
-
        right_buffer = alloc_free_block(root);
        BUG_ON(!right_buffer);
        BUG_ON(mid == nritems);
@@ -1170,7 +1170,6 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
 
        node = &parent->node;
        nritems = node->header.nritems;
-
        if (slot != nritems -1) {
                memmove(node->keys + slot, node->keys + slot + 1,
                        sizeof(struct key) * (nritems - slot - 1));
index 9fe8ba6e25c135758f69160764ef4e31e9fac7e3..4a7bc4e6e7471a5e6e87a613b96d2096f71e7d5f 100644 (file)
@@ -51,10 +51,12 @@ struct tree_buffer;
  */
 struct ctree_root {
        struct tree_buffer *node;
+       struct tree_buffer *commit_root;
        struct ctree_root *extent_root;
        struct key current_insert;
        int fp;
        struct radix_tree_root cache_radix;
+       struct radix_tree_root pinned_radix;
        struct list_head trans;
        struct list_head cache;
        int cache_size;
@@ -151,4 +153,6 @@ int del_item(struct ctree_root *root, struct ctree_path *path);
 int insert_item(struct ctree_root *root, struct key *key, void *data, int data_size);
 int next_leaf(struct ctree_root *root, struct ctree_path *path);
 int leaf_free_space(struct leaf *leaf);
+int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap);
+int btrfs_finish_extent_commit(struct ctree_root *root);
 #endif
index 0e1c31e682fb444f159b7eabc262365d3a99b1d2..2fe31c3508c147c268fff8ed7d4c9ec3eeb1be75 100644 (file)
@@ -153,13 +153,24 @@ static int __commit_transaction(struct ctree_root *root)
        return ret;
 }
 
-int commit_transaction(struct ctree_root *root)
+int commit_transaction(struct ctree_root *root, struct ctree_super_block *s)
 {
-       int ret;
+       int ret = 0;
+
        ret = __commit_transaction(root);
        if (!ret && root != root->extent_root)
                ret = __commit_transaction(root->extent_root);
        BUG_ON(ret);
+       if (root->commit_root != root->node) {
+               struct tree_buffer *snap = root->commit_root;
+               root->commit_root = root->node;
+               root->node->count++;
+               ret = btrfs_drop_snapshot(root, snap);
+               BUG_ON(ret);
+               tree_block_release(root, snap);
+       }
+        write_ctree_super(root, s);
+       btrfs_finish_extent_commit(root);
        return ret;
 }
 
@@ -168,10 +179,13 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
 {
        INIT_LIST_HEAD(&root->trans);
        INIT_LIST_HEAD(&root->cache);
+       root->cache_size = 0;
        root->fp = fp;
        root->node = NULL;
-       root->node = read_tree_block(root, info->tree_root);
        root->extent_root = extent_root;
+       root->commit_root = NULL;
+       root->node = read_tree_block(root, info->tree_root);
+       memset(&root->current_insert, 0, sizeof(root->current_insert));
        return 0;
 }
 
@@ -188,6 +202,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
                return NULL;
        }
        INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
+       INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL);
+       INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL);
        INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
        ret = pread(fp, super, sizeof(struct ctree_super_block),
                     CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
@@ -204,6 +220,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
        BUG_ON(ret < 0);
        __setup_root(root, extent_root, &super->root_info, fp);
        __setup_root(extent_root, extent_root, &super->extent_info, fp);
+       root->commit_root = root->node;
+       root->node->count++;
        return root;
 }
 
@@ -236,9 +254,11 @@ static int drop_cache(struct ctree_root *root)
        }
        return 0;
 }
-int close_ctree(struct ctree_root *root)
+int close_ctree(struct ctree_root *root, struct ctree_super_block *s)
 {
-       commit_transaction(root);
+       commit_transaction(root, s);
+       __commit_transaction(root->extent_root);
+       write_ctree_super(root, s);
        drop_cache(root->extent_root);
        drop_cache(root);
        BUG_ON(!list_empty(&root->trans));
@@ -249,6 +269,7 @@ int close_ctree(struct ctree_root *root)
                tree_block_release(root, root->node);
        if (root->extent_root->node)
                tree_block_release(root->extent_root, root->extent_root->node);
+       tree_block_release(root, root->commit_root);
        free(root);
        printf("on close %d blocks are allocated\n", allocated_blocks);
        return 0;
index b5dee2fae4daa6297355687a30205f592a9ef493..1c0af7c56c2114255258113fe36c1f55a1594762 100644 (file)
@@ -18,9 +18,9 @@ struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr);
 int write_tree_block(struct ctree_root *root, struct tree_buffer *buf);
 int dirty_tree_block(struct ctree_root *root, struct tree_buffer *buf);
 int clean_tree_block(struct ctree_root *root, struct tree_buffer *buf);
-int commit_transaction(struct ctree_root *root);
+int commit_transaction(struct ctree_root *root, struct ctree_super_block *s);
 struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s);
-int close_ctree(struct ctree_root *root);
+int close_ctree(struct ctree_root *root, struct ctree_super_block *s);
 void tree_block_release(struct ctree_root *root, struct tree_buffer *buf);
 int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s);
 int mkfs(int fd);
index 25d9cd169209d362b4d77ed9a07c5a53bc541344..0723b7f3f0c3022ac5b938565147cdc3cd956e18 100644 (file)
@@ -13,7 +13,8 @@
  * other allocations are done.  The pending tag is also used in the same
  * manner for deletes.
  */
-#define CTREE_EXTENT_PENDING 0
+#define CTREE_EXTENT_PENDING_ADD 0
+#define CTREE_EXTENT_PENDING_DEL 1
 
 static int inc_block_ref(struct ctree_root *root, u64 blocknr)
 {
@@ -27,20 +28,51 @@ static int inc_block_ref(struct ctree_root *root, u64 blocknr)
        key.flags = 0;
        key.offset = 1;
        ret = search_slot(root->extent_root, &key, &path, 0, 1);
+       if (ret != 0)
+               BUG();
        BUG_ON(ret != 0);
        l = &path.nodes[0]->leaf;
        item = (struct extent_item *)(l->data +
                                      l->items[path.slots[0]].offset);
        item->refs++;
+
        BUG_ON(list_empty(&path.nodes[0]->dirty));
        release_path(root->extent_root, &path);
        return 0;
 }
 
+static int lookup_block_ref(struct ctree_root *root, u64 blocknr, int *refs)
+{
+       struct ctree_path path;
+       int ret;
+       struct key key;
+       struct leaf *l;
+       struct extent_item *item;
+       init_path(&path);
+       key.objectid = blocknr;
+       key.flags = 0;
+       key.offset = 1;
+       ret = search_slot(root->extent_root, &key, &path, 0, 0);
+       if (ret != 0)
+               BUG();
+       l = &path.nodes[0]->leaf;
+       item = (struct extent_item *)(l->data +
+                                     l->items[path.slots[0]].offset);
+       *refs = item->refs;
+       release_path(root->extent_root, &path);
+       return 0;
+}
+
 int btrfs_inc_ref(struct ctree_root *root, struct tree_buffer *buf)
 {
        u64 blocknr;
        int i;
+
+       if (root == root->extent_root)
+               return 0;
+       if (is_leaf(buf->node.header.flags))
+               return 0;
+
        for (i = 0; i < buf->node.header.nritems; i++) {
                blocknr = buf->node.blockptrs[i];
                inc_block_ref(root, blocknr);
@@ -48,85 +80,187 @@ int btrfs_inc_ref(struct ctree_root *root, struct tree_buffer *buf)
        return 0;
 }
 
+int btrfs_finish_extent_commit(struct ctree_root *root)
+{
+       struct ctree_root *extent_root = root->extent_root;
+       unsigned long gang[8];
+       int ret;
+       int i;
+
+       while(1) {
+               ret = radix_tree_gang_lookup(&extent_root->pinned_radix,
+                                                (void **)gang, 0,
+                                                ARRAY_SIZE(gang));
+               if (!ret)
+                       break;
+               for (i = 0; i < ret; i++)
+                       radix_tree_delete(&extent_root->pinned_radix, gang[i]);
+       }
+       return 0;
+}
+
 /*
- * find all the blocks marked as pending in the radix tree and remove
- * them from the extent map
+ * remove an extent from the root, returns 0 on success
  */
-static int del_pending_extents(struct ctree_root *extent_root)
+int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
+{
+       struct ctree_path path;
+       struct key key;
+       struct ctree_root *extent_root = root->extent_root;
+       int ret;
+       struct item *item;
+       struct extent_item *ei;
+       key.objectid = blocknr;
+       key.flags = 0;
+       key.offset = num_blocks;
+
+       init_path(&path);
+       ret = search_slot(extent_root, &key, &path, -1, 1);
+       if (ret) {
+               printf("failed to find %Lu\n", key.objectid);
+               print_tree(extent_root, extent_root->node);
+               printf("failed to find %Lu\n", key.objectid);
+               BUG();
+       }
+       item = path.nodes[0]->leaf.items + path.slots[0];
+       ei = (struct extent_item *)(path.nodes[0]->leaf.data + item->offset);
+       BUG_ON(ei->refs == 0);
+       ei->refs--;
+       if (ei->refs == 0) {
+               if (root == extent_root) {
+                       int err;
+                       radix_tree_preload(GFP_KERNEL);
+                       err = radix_tree_insert(&extent_root->pinned_radix,
+                                         blocknr, (void *)blocknr);
+                       BUG_ON(err);
+                       radix_tree_preload_end();
+               }
+               ret = del_item(extent_root, &path);
+               if (ret)
+                       BUG();
+       }
+       release_path(extent_root, &path);
+       return ret;
+}
+
+/*
+ * insert all of the pending extents reserved during the original
+ * allocation.  (CTREE_EXTENT_PENDING).  Returns zero if it all worked out
+ */
+static int insert_pending_extents(struct ctree_root *extent_root)
 {
        int ret;
        struct key key;
+       struct extent_item item;
        struct tree_buffer *gang[4];
        int i;
-       struct ctree_path path;
 
+       // FIXME -ENOSPC
+       item.owner = extent_root->node->node.header.parentid;
+       item.refs = 1;
        while(1) {
                ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
                                                 (void **)gang, 0,
                                                 ARRAY_SIZE(gang),
-                                                CTREE_EXTENT_PENDING);
+                                                CTREE_EXTENT_PENDING_ADD);
                if (!ret)
                        break;
                for (i = 0; i < ret; i++) {
                        key.objectid = gang[i]->blocknr;
                        key.flags = 0;
                        key.offset = 1;
-                       init_path(&path);
-                       ret = search_slot(extent_root, &key, &path, -1, 1);
+                       ret = insert_item(extent_root, &key, &item,
+                                         sizeof(item));
                        if (ret) {
+                               printf("%Lu already in tree\n", key.objectid);
                                print_tree(extent_root, extent_root->node);
-                               printf("unable to find %Lu\n", key.objectid);
                                BUG();
                                // FIXME undo it and return sane
                                return ret;
                        }
-                       ret = del_item(extent_root, &path);
-                       if (ret) {
-                               BUG();
-                               return ret;
-                       }
-                       release_path(extent_root, &path);
+                       radix_tree_tag_clear(&extent_root->cache_radix,
+                                            gang[i]->blocknr,
+                                            CTREE_EXTENT_PENDING_ADD);
+                       tree_block_release(extent_root, gang[i]);
+               }
+       }
+       return 0;
+}
+
+/*
+ * find all the blocks marked as pending in the radix tree and remove
+ * them from the extent map
+ */
+static int del_pending_extents(struct ctree_root *extent_root)
+{
+       int ret;
+       struct tree_buffer *gang[4];
+       int i;
+
+       while(1) {
+               ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
+                                                (void **)gang, 0,
+                                                ARRAY_SIZE(gang),
+                                                CTREE_EXTENT_PENDING_DEL);
+               if (!ret)
+                       break;
+               for (i = 0; i < ret; i++) {
+                       ret = __free_extent(extent_root, gang[i]->blocknr, 1);
                        radix_tree_tag_clear(&extent_root->cache_radix,
                                                gang[i]->blocknr,
-                                               CTREE_EXTENT_PENDING);
+                                               CTREE_EXTENT_PENDING_DEL);
                        tree_block_release(extent_root, gang[i]);
                }
        }
        return 0;
 }
 
+static int run_pending(struct ctree_root *extent_root)
+{
+       while(radix_tree_tagged(&extent_root->cache_radix,
+                               CTREE_EXTENT_PENDING_DEL) ||
+             radix_tree_tagged(&extent_root->cache_radix,
+                               CTREE_EXTENT_PENDING_ADD)) {
+               insert_pending_extents(extent_root);
+               del_pending_extents(extent_root);
+       }
+       return 0;
+}
+
+
 /*
  * remove an extent from the root, returns 0 on success
  */
 int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
 {
-       struct ctree_path path;
        struct key key;
        struct ctree_root *extent_root = root->extent_root;
        struct tree_buffer *t;
        int pending_ret;
        int ret;
-       key.objectid = blocknr;
-       key.flags = 0;
-       key.offset = num_blocks;
+
        if (root == extent_root) {
-               t = read_tree_block(root, key.objectid);
-               radix_tree_tag_set(&root->cache_radix, key.objectid,
-                                  CTREE_EXTENT_PENDING);
+               t = find_tree_block(root, blocknr);
+               if (radix_tree_tag_get(&root->cache_radix, blocknr,
+                                     CTREE_EXTENT_PENDING_ADD)) {
+                       radix_tree_tag_clear(&root->cache_radix,
+                                            blocknr,
+                                            CTREE_EXTENT_PENDING_ADD);
+                       /* once for us */
+                       tree_block_release(root, t);
+                       /* once for the pending add */
+                       tree_block_release(root, t);
+               } else {
+                       radix_tree_tag_set(&root->cache_radix, blocknr,
+                                  CTREE_EXTENT_PENDING_DEL);
+               }
                return 0;
        }
-       init_path(&path);
-       ret = search_slot(extent_root, &key, &path, -1, 1);
-       if (ret) {
-               print_tree(extent_root, extent_root->node);
-               printf("failed to find %Lu\n", key.objectid);
-               BUG();
-       }
-       ret = del_item(extent_root, &path);
-       if (ret)
-               BUG();
-       release_path(extent_root, &path);
-       pending_ret = del_pending_extents(root->extent_root);
+       key.objectid = blocknr;
+       key.flags = 0;
+       key.offset = num_blocks;
+       ret = __free_extent(root, blocknr, num_blocks);
+       pending_ret = run_pending(root->extent_root);
        return ret ? ret : pending_ret;
 }
 
@@ -203,7 +337,7 @@ check_pending:
         */
        release_path(root, &path);
        BUG_ON(ins->objectid < search_start);
-       if (orig_root->extent_root == orig_root) {
+       if (1 || orig_root->extent_root == orig_root) {
                BUG_ON(num_blocks != 1);
                if ((root->current_insert.objectid <= ins->objectid &&
                    root->current_insert.objectid +
@@ -211,8 +345,9 @@ check_pending:
                   (root->current_insert.objectid > ins->objectid &&
                    root->current_insert.objectid <= ins->objectid +
                    ins->offset) ||
+                  radix_tree_lookup(&root->pinned_radix, ins->objectid) ||
                   radix_tree_tag_get(&root->cache_radix, ins->objectid,
-                                     CTREE_EXTENT_PENDING)) {
+                                     CTREE_EXTENT_PENDING_ADD)) {
                        search_start = ins->objectid + 1;
                        goto check_failed;
                }
@@ -225,51 +360,6 @@ error:
        return ret;
 }
 
-/*
- * insert all of the pending extents reserved during the original
- * allocation.  (CTREE_EXTENT_PENDING).  Returns zero if it all worked out
- */
-static int insert_pending_extents(struct ctree_root *extent_root)
-{
-       int ret;
-       struct key key;
-       struct extent_item item;
-       struct tree_buffer *gang[4];
-       int i;
-
-       // FIXME -ENOSPC
-       item.refs = 1;
-       item.owner = extent_root->node->node.header.parentid;
-       while(1) {
-               ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
-                                                (void **)gang, 0,
-                                                ARRAY_SIZE(gang),
-                                                CTREE_EXTENT_PENDING);
-               if (!ret)
-                       break;
-               for (i = 0; i < ret; i++) {
-                       key.objectid = gang[i]->blocknr;
-                       key.flags = 0;
-                       key.offset = 1;
-                       ret = insert_item(extent_root, &key, &item,
-                                         sizeof(item));
-                       if (ret) {
-                               printf("%Lu already in tree\n", key.objectid);
-                               print_tree(extent_root, extent_root->node);
-                               BUG();
-                               // FIXME undo it and return sane
-                               return ret;
-                       }
-                       radix_tree_tag_clear(&extent_root->cache_radix,
-                                            gang[i]->blocknr,
-                                            CTREE_EXTENT_PENDING);
-                       printf("%Lu is not pending\n", gang[i]->blocknr);
-                       tree_block_release(extent_root, gang[i]);
-               }
-       }
-       return 0;
-}
-
 /*
  * finds a free extent and does all the dirty work required for allocation
  * returns the key for the extent through ins, and a tree buffer for
@@ -296,7 +386,7 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
                                  sizeof(extent_item));
                memset(&root->extent_root->current_insert, 0,
                       sizeof(struct key));
-               pending_ret = insert_pending_extents(root->extent_root);
+               pending_ret = run_pending(root->extent_root);
                if (ret)
                        return ret;
                if (pending_ret)
@@ -309,9 +399,8 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start,
        BUG_ON(ins->offset != 1);
        *buf = find_tree_block(root, ins->objectid);
        BUG_ON(!*buf);
-       printf("%Lu is pending\n", ins->objectid);
        radix_tree_tag_set(&root->cache_radix, ins->objectid,
-                          CTREE_EXTENT_PENDING);
+                          CTREE_EXTENT_PENDING_ADD);
        (*buf)->count++;
        dirty_tree_block(root, *buf);
        return 0;
@@ -331,13 +420,41 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root)
        ret = alloc_extent(root, 1, 0, (unsigned long)-1,
                           root->node->node.header.parentid,
                           &ins, &buf);
-
        if (ret) {
                BUG();
                return NULL;
        }
        if (root != root->extent_root)
                BUG_ON(radix_tree_tag_get(&root->extent_root->cache_radix,
-                                         buf->blocknr, CTREE_EXTENT_PENDING));
+                                         buf->blocknr,
+                                         CTREE_EXTENT_PENDING_ADD));
        return buf;
 }
+
+int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
+{
+       int ret;
+       int level;
+       int refs;
+       u64 blocknr = snap->blocknr;
+
+       level = node_level(snap->node.header.flags);
+       ret = lookup_block_ref(root, snap->blocknr, &refs);
+       BUG_ON(ret);
+       if (refs == 1 && level != 0) {
+               struct node *n = &snap->node;
+               struct tree_buffer *b;
+               int i;
+               for (i = 0; i < n->header.nritems; i++) {
+                       b = read_tree_block(root, n->blockptrs[i]);
+                       /* FIXME, don't recurse here */
+                       ret = btrfs_drop_snapshot(root, b);
+                       BUG_ON(ret);
+                       tree_block_release(root, b);
+               }
+       }
+       ret = free_extent(root, blocknr, 1);
+       BUG_ON(ret);
+       return 0;
+}
+
index dda08f32c154e918ab1f60d390b1603fa7a85323..e32a959dd3e5b93831eef9e1d357726c01f2e48c 100644 (file)
@@ -21,9 +21,11 @@ void print_leaf(struct leaf *l)
                        item->key.objectid, item->key.flags, item->key.offset,
                        item->offset, item->size);
                fflush(stdout);
-               printf("\t\titem data %.*s\n", item->size, l->data+item->offset);
+               printf("\t\titem data %.*s\n", item->size,
+                       l->data+item->offset);
                ei = (struct extent_item *)(l->data + item->offset);
-               printf("\t\textent data %u %Lu\n", ei->refs, ei->owner);
+               printf("\t\textent data refs %u owner %Lu\n", ei->refs,
+                       ei->owner);
                fflush(stdout);
        }
 }
index 8255f79ceca59bdd15d4a102a752a2313bf92ad2..6400c7100a6a43a122a1ac4e5f8deb369341dae6 100644 (file)
@@ -19,7 +19,7 @@ int main(int ac, char **av) {
        int i;
        int num;
        int ret;
-       int run_size = 1024;
+       int run_size = 100000;
        int max_key =  100000000;
        int tree_size = 0;
        struct ctree_path path;
@@ -44,9 +44,9 @@ int main(int ac, char **av) {
                if (!ret)
                        tree_size++;
                free(buf);
+
        }
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
 
        root = open_ctree("dbfile", &super);
        printf("starting search\n");
@@ -65,8 +65,7 @@ int main(int ac, char **av) {
                }
                release_path(root, &path);
        }
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
        root = open_ctree("dbfile", &super);
        printf("node %p level %d total ptrs %d free spc %lu\n", root->node,
                node_level(root->node->node.header.flags),
@@ -90,8 +89,7 @@ int main(int ac, char **av) {
                }
                release_path(root, &path);
        }
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
        root = open_ctree("dbfile", &super);
        srand(128);
        for (i = 0; i < run_size; i++) {
@@ -106,8 +104,7 @@ int main(int ac, char **av) {
                        tree_size++;
                free(buf);
        }
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
        root = open_ctree("dbfile", &super);
        srand(128);
        printf("starting search2\n");
@@ -156,10 +153,17 @@ int main(int ac, char **av) {
                }
                release_path(root, &path);
        }
+       /*
+       printf("previous tree:\n");
+       print_tree(root, root->commit_root);
+       printf("map before commit\n");
+       print_tree(root->extent_root, root->extent_root->node);
+       */
+       commit_transaction(root, &super);
        printf("tree size is now %d\n", tree_size);
+       printf("root %p commit root %p\n", root->node, root->commit_root);
        printf("map tree\n");
        print_tree(root->extent_root, root->extent_root->node);
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
        return 0;
 }
index dcc852ad67373c36074e79f6e642cb0eebea3d3d..7b37b6bae105031d801e4aa47a9a3505dffa9f3a 100644 (file)
@@ -8,6 +8,7 @@
 #include "print-tree.h"
 
 int keep_running = 1;
+struct ctree_super_block super;
 
 static int setup_key(struct radix_tree_root *root, struct key *key, int exists)
 {
@@ -59,11 +60,6 @@ error:
        return -1;
 }
 
-static int run_commit(struct ctree_root *root, struct radix_tree_root *radix)
-{
-       return commit_transaction(root);
-}
-
 static int insert_dup(struct ctree_root *root, struct radix_tree_root *radix)
 {
        struct ctree_path path;
@@ -210,7 +206,7 @@ static int fill_tree(struct ctree_root *root, struct radix_tree_root *radix,
                        goto out;
                }
                if (i % 1000 == 0) {
-                       ret = commit_transaction(root);
+                       ret = commit_transaction(root, &super);
                        if (ret) {
                                fprintf(stderr, "fill commit failed\n");
                                return ret;
@@ -229,7 +225,7 @@ out:
 static int bulk_op(struct ctree_root *root, struct radix_tree_root *radix)
 {
        int ret;
-       int nr = rand() % 20000;
+       int nr = rand() % 5000;
        static int run_nr = 0;
 
        /* do the bulk op much less frequently */
@@ -247,7 +243,7 @@ static int bulk_op(struct ctree_root *root, struct radix_tree_root *radix)
 
 int (*ops[])(struct ctree_root *root, struct radix_tree_root *radix) =
        { ins_one, insert_dup, del_one, lookup_item,
-         lookup_enoent, bulk_op, run_commit };
+         lookup_enoent, bulk_op };
 
 static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix)
 {
@@ -314,7 +310,6 @@ int print_usage(void)
 int main(int ac, char **av)
 {
        RADIX_TREE(radix, GFP_KERNEL);
-       struct ctree_super_block super;
        struct ctree_root *root;
        int i;
        int ret;
@@ -365,8 +360,7 @@ int main(int ac, char **av)
                        printf("open & close, root level %d nritems %d\n",
                                node_level(root->node->node.header.flags),
                                root->node->node.header.nritems);
-                       write_ctree_super(root, &super);
-                       close_ctree(root);
+                       close_ctree(root, &super);
                        root = open_ctree("dbfile", &super);
                }
                while(count--) {
@@ -380,7 +374,7 @@ int main(int ac, char **av)
                                err = ret;
                                goto out;
                        }
-                       if (ops[op] == bulk_op || ops[op] == run_commit)
+                       if (ops[op] == bulk_op)
                                break;
                        if (keep_running == 0) {
                                err = 0;
@@ -389,8 +383,7 @@ int main(int ac, char **av)
                }
        }
 out:
-       write_ctree_super(root, &super);
-       close_ctree(root);
+       close_ctree(root, &super);
        return err;
 }