/* * Reblock a B-Tree internal node. The parent must be adjusted to point to * the new copy of the internal node, and the node's children's parent * pointers must also be adjusted to point to the new copy. * * elm is a pointer to the parent element pointing at cursor.node. */ static int hammer_reblock_int_node(struct hammer_ioc_reblock *reblock, hammer_cursor_t cursor, hammer_btree_elm_t elm) { struct hammer_node_lock lockroot; hammer_node_t onode; hammer_node_t nnode; int error; hammer_node_lock_init(&lockroot, cursor->node); error = hammer_btree_lock_children(cursor, 1, &lockroot, NULL); if (error) goto done; /* * Don't supply a hint when allocating the leaf. Fills are done * from the leaf upwards. */ onode = cursor->node; nnode = hammer_alloc_btree(cursor->trans, 0, &error); if (nnode == NULL) goto done; hammer_lock_ex(&nnode->lock); hammer_modify_node_noundo(cursor->trans, nnode); hammer_move_node(cursor, elm, onode, nnode); /* * Clean up. * * The new node replaces the current node in the cursor. The cursor * expects it to be locked so leave it locked. Discard onode. */ hammer_cursor_replaced_node(onode, nnode); hammer_delete_node(cursor->trans, onode); if (hammer_debug_general & 0x4000) { hdkprintf("%08x %016jx -> %016jx\n", (elm ? elm->base.localization : -1), (intmax_t)onode->node_offset, (intmax_t)nnode->node_offset); } hammer_modify_node_done(nnode); cursor->node = nnode; hammer_unlock(&onode->lock); hammer_rel_node(onode); done: hammer_btree_unlock_children(cursor->trans->hmp, &lockroot, NULL); return (error); }
/* * Reblock a B-Tree internal node. The parent must be adjusted to point to * the new copy of the internal node, and the node's children's parent * pointers must also be adjusted to point to the new copy. * * elm is a pointer to the parent element pointing at cursor.node. */ static int hammer_reblock_int_node(struct hammer_ioc_reblock *reblock, hammer_cursor_t cursor, hammer_btree_elm_t elm) { struct hammer_node_lock lockroot; hammer_node_t onode; hammer_node_t nnode; int error; int i; hammer_node_lock_init(&lockroot, cursor->node); error = hammer_btree_lock_children(cursor, 1, &lockroot, NULL); if (error) goto done; onode = cursor->node; nnode = hammer_alloc_btree(cursor->trans, 0, &error); if (nnode == NULL) goto done; /* * Move the node. Adjust the parent's pointer to us first. */ hammer_lock_ex(&nnode->lock); hammer_modify_node_noundo(cursor->trans, nnode); bcopy(onode->ondisk, nnode->ondisk, sizeof(*nnode->ondisk)); if (elm) { /* * We are not the root of the B-Tree */ hammer_modify_node(cursor->trans, cursor->parent, &elm->internal.subtree_offset, sizeof(elm->internal.subtree_offset)); elm->internal.subtree_offset = nnode->node_offset; hammer_modify_node_done(cursor->parent); } else { /* * We are the root of the B-Tree */ hammer_volume_t volume; volume = hammer_get_root_volume(cursor->trans->hmp, &error); KKASSERT(error == 0); hammer_modify_volume_field(cursor->trans, volume, vol0_btree_root); volume->ondisk->vol0_btree_root = nnode->node_offset; hammer_modify_volume_done(volume); hammer_rel_volume(volume, 0); } /* * Now adjust our children's pointers to us. */ for (i = 0; i < nnode->ondisk->count; ++i) { elm = &nnode->ondisk->elms[i]; error = btree_set_parent(cursor->trans, nnode, elm); if (error) panic("reblock internal node: fixup problem"); } /* * Clean up. * * The new node replaces the current node in the cursor. The cursor * expects it to be locked so leave it locked. Discard onode. */ hammer_cursor_replaced_node(onode, nnode); hammer_delete_node(cursor->trans, onode); if (hammer_debug_general & 0x4000) { kprintf("REBLOCK INODE %016llx -> %016llx\n", (long long)onode->node_offset, (long long)nnode->node_offset); } hammer_modify_node_done(nnode); cursor->node = nnode; hammer_unlock(&onode->lock); hammer_rel_node(onode); done: hammer_btree_unlock_children(cursor->trans->hmp, &lockroot, NULL); return (error); }