static void level_redirect_blockput(struct cursor *cursor, int level, struct buffer_head *clone) { struct buffer_head *buffer = cursor->path[level].buffer; struct index_entry *next = cursor->path[level].next; /* If this level has ->next, update ->next to the clone buffer */ if (next) next = ptr_redirect(next, bufdata(buffer), bufdata(clone)); memcpy(bufdata(clone), bufdata(buffer), bufsize(clone)); level_replace_blockput(cursor, level, clone, next); }
static void level_redirect_blockput(struct cursor *cursor, int level, struct buffer_head *clone) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct buffer_head *buffer = cursor->path[level].buffer; struct index_entry *next = cursor->path[level].next; /* If this level has ->next, update ->next to the clone buffer */ if (next) next = ptr_redirect(next, bufdata(buffer), bufdata(clone)); memcpy(bufdata(clone), bufdata(buffer), bufsize(clone)); level_replace_blockput(cursor, level, clone, next); }
/* * Insert new leaf to next cursor position. * keep == 1: keep current cursor position. * keep == 0, set cursor position to new leaf. */ static int insert_leaf(struct cursor *cursor, tuxkey_t childkey, struct buffer_head *leafbuf, int keep) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct btree *btree = cursor->btree; struct sb *sb = btree->sb; int level = btree->root.depth; block_t childblock = bufindex(leafbuf); if (keep) blockput(leafbuf); else { cursor_pop_blockput(cursor); cursor_push(cursor, leafbuf, NULL); } while (level--) { struct path_level *at = &cursor->path[level]; struct buffer_head *parentbuf = at->buffer; struct bnode *parent = bufdata(parentbuf); /* insert and exit if not full */ if (bcount(parent) < btree->sb->entries_per_node) { bnode_add_index(parent, at->next, childblock, childkey); if (!keep) at->next++; log_bnode_add(sb, bufindex(parentbuf), childblock, childkey); mark_buffer_unify_non(parentbuf); cursor_check(cursor); return 0; } /* split a full index node */ struct buffer_head *newbuf = new_node(btree); if (IS_ERR(newbuf)) return PTR_ERR(newbuf); struct bnode *newnode = bufdata(newbuf); unsigned half = bcount(parent) / 2; u64 newkey = be64_to_cpu(parent->entries[half].key); bnode_split(parent, half, newnode); log_bnode_split(sb, bufindex(parentbuf), half, bufindex(newbuf)); /* if the cursor is in the new node, use that as the parent */ int child_is_left = at->next <= parent->entries + half; if (!child_is_left) { struct index_entry *newnext; mark_buffer_unify_non(parentbuf); newnext = newnode->entries + (at->next - &parent->entries[half]); get_bh(newbuf); level_replace_blockput(cursor, level, newbuf, newnext); parentbuf = newbuf; parent = newnode; } else mark_buffer_unify_non(newbuf); bnode_add_index(parent, at->next, childblock, childkey); if (!keep) at->next++; log_bnode_add(sb, bufindex(parentbuf), childblock, childkey); mark_buffer_unify_non(parentbuf); childkey = newkey; childblock = bufindex(newbuf); blockput(newbuf); /* * If child is in left bnode, we should keep the * cursor position to child, otherwise adjust cursor * to new bnode. */ keep = child_is_left; } /* Make new root bnode */ trace("add tree level"); struct buffer_head *newbuf = new_node(btree); if (IS_ERR(newbuf)) return PTR_ERR(newbuf); struct bnode *newroot = bufdata(newbuf); block_t newrootblock = bufindex(newbuf); block_t oldrootblock = btree->root.block; int left_node = bufindex(cursor->path[0].buffer) != childblock; bnode_init_root(newroot, 2, oldrootblock, childblock, childkey); cursor_root_add(cursor, newbuf, newroot->entries + 1 + !left_node); log_bnode_root(sb, newrootblock, 2, oldrootblock, childblock, childkey); /* Change btree to point the new root */ btree->root.block = newrootblock; btree->root.depth++; mark_buffer_unify_non(newbuf); tux3_mark_btree_dirty(btree); cursor_check(cursor); return 0; }