HAMMER VFS - rebalancing, zero unused fields in boundary element
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 16 Mar 2009 04:45:57 +0000 (21:45 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 16 Mar 2009 04:45:57 +0000 (21:45 -0700)
The rebalancer was not zeroing certain unused fields in a newly created
boundary element when truncating an existing internal B-Tree node.

While these fields are not used by the filesystem for boundary elements,
they are still expected to be zero'd out.

sbin/hammer/cmd_rebalance.c
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_ioctl.h
sys/vfs/hammer/hammer_rebalance.c

index cb42061..857b694 100644 (file)
@@ -98,12 +98,12 @@ hammer_cmd_rebalance(char **av, int ac)
        printf("Rebalance:\n"
               "    %lld btree nodes scanned\n"
               "    %lld btree nodes deleted\n"
-              "    %lld btree leaf nodes rebalanced\n"
-              "    %lld btree internal nodes rebalanced\n",
+              "    %lld collision retries\n"
+              "    %lld btree nodes rebalanced\n",
               rebal.stat_ncount,
               rebal.stat_deletions,
-              rebal.stat_lrebal,
-              rebal.stat_irebal
+              rebal.stat_collisions,
+              rebal.stat_nrebal
        );
 }
 
index ff8a7ee..415a4b5 100644 (file)
@@ -982,7 +982,7 @@ int hammer_btree_lock_children(hammer_cursor_t cursor, int depth,
                        hammer_node_lock_t parent);
 void   hammer_btree_lock_copy(hammer_cursor_t cursor,
                        hammer_node_lock_t parent);
-void   hammer_btree_sync_copy(hammer_cursor_t cursor,
+int    hammer_btree_sync_copy(hammer_cursor_t cursor,
                        hammer_node_lock_t parent);
 void   hammer_btree_unlock_children(hammer_cursor_t cursor,
                        hammer_node_lock_t parent);
index bdd5f03..e51f7f7 100644 (file)
@@ -2568,12 +2568,14 @@ hammer_btree_lock_copy(hammer_cursor_t cursor, hammer_node_lock_t parent)
 /*
  * Recursively sync modified copies to the media.
  */
-void
+int
 hammer_btree_sync_copy(hammer_cursor_t cursor, hammer_node_lock_t parent)
 {
        hammer_node_lock_t item;
+       int count = 0;
 
        if (parent->flags & HAMMER_NODE_LOCK_UPDATED) {
+               ++count;
                hammer_modify_node_all(cursor->trans, parent->node);
                *parent->node->ondisk = *parent->copy;
                 hammer_modify_node_done(parent->node);
@@ -2583,8 +2585,9 @@ hammer_btree_sync_copy(hammer_cursor_t cursor, hammer_node_lock_t parent)
                }
        }
        TAILQ_FOREACH(item, &parent->list, entry) {
-               hammer_btree_sync_copy(cursor, item);
+               count += hammer_btree_sync_copy(cursor, item);
        }
+       return(count);
 }
 
 /*
index 904987b..73ab091 100644 (file)
@@ -120,9 +120,9 @@ struct hammer_ioc_rebalance {
 
        int64_t         stat_ncount;    /* number of nodes scanned */
        int64_t         stat_deletions; /* number of nodes deleted */
-       int64_t         stat_collisions;/* number of subtrees skipped */
-       int64_t         stat_lrebal;    /* number of leaf-nodes rebalanced */
-       int64_t         stat_irebal;    /* number of int-nodes rebalanced */
+       int64_t         stat_collisions;/* number of collision retries */
+       int64_t         stat_nrebal;    /* number of btree-nodes rebalanced */
+       int64_t         stat_unused04;
 };
 
 /*
index ab6fb02..7dcd65c 100644 (file)
@@ -169,8 +169,10 @@ retry:
        if (error == ENOENT)
                error = 0;
        hammer_done_cursor(&cursor);
-       if (error == EDEADLK)
+       if (error == EDEADLK) {
+               ++rebal->stat_collisions;
                goto retry;
+       }
        if (error == EINTR) {
                rebal->head.flags |= HAMMER_IOC_HEAD_INTR;
                error = 0;
@@ -417,13 +419,14 @@ rebalance_node(struct hammer_ioc_rebalance *rebal, hammer_cursor_t cursor)
                base_item->flags |= HAMMER_NODE_LOCK_UPDATED;
                if (cursor->index > lockroot.copy->count)
                        --cursor->index;
+               ++rebal->stat_deletions;
        }
 
        /*
         * All done, sync the locked child tree to disk.  This will also
         * flush and delete deleted nodes.
         */
-       hammer_btree_sync_copy(cursor, &lockroot);
+       rebal->stat_nrebal += hammer_btree_sync_copy(cursor, &lockroot);
 done:
        hammer_btree_unlock_children(cursor, &lockroot);
        hammer_cursor_downgrade(cursor);
@@ -470,14 +473,23 @@ rebalance_closeout(hammer_node_lock_t base_item, int base_count,
         * Internal nodes are required to have at least one child,
         * otherwise the left and right boundary would end up being
         * the same element.  Only leaf nodes can be empty.
+        *
+        * Rebalancing may cut-off an internal node such that the
+        * new right hand boundary is the next element anyway, but
+        * we still have to make sure that subtree_offset, btype,
+        * and mirror_tid are all 0.
         */
        if (base_item->copy->type == HAMMER_BTREE_TYPE_INTERNAL) {
                KKASSERT(base_count != 0);
                base_elm = &base_item->copy->elms[base_count];
 
-               if (bcmp(base_elm, elm, sizeof(*elm)) != 0) {
+               if (bcmp(base_elm, elm, sizeof(*elm)) != 0 ||
+                   elm->internal.subtree_offset ||
+                   elm->internal.mirror_tid ||
+                   elm->base.btype) {
                        *base_elm = *elm;
                        base_elm->internal.subtree_offset = 0;
+                       base_elm->internal.mirror_tid = 0;
                        base_elm->base.btype = 0;
                        base_item->flags |= HAMMER_NODE_LOCK_UPDATED;
                        if (hammer_debug_general & 0x1000)