@@ -73,7 +73,6 @@ void ulist_fini(struct ulist *ulist)
if (ulist->nodes_alloced > ULIST_SIZE)
kfree(ulist->nodes);
ulist->nodes_alloced = 0; /* in case ulist_fini is called twice */
- ulist->root = RB_ROOT;
}
EXPORT_SYMBOL(ulist_fini);
@@ -205,6 +204,7 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
u64 new_alloced = ulist->nodes_alloced + 128;
struct ulist_node *new_nodes;
void *old = NULL;
+ int i;
/*
* if nodes_alloced == ULIST_SIZE no memory has been allocated
@@ -222,6 +222,17 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
memcpy(new_nodes, ulist->int_nodes,
sizeof(ulist->int_nodes));
+ /*
+ * krealloc actually uses memcpy, which does not copy rb_node
+ * pointers, so we have to do it ourselves. Otherwise we may
+ * be bitten by crashes.
+ */
+ for (i = 0; i < ulist->nnodes; i++) {
+ rb_erase(&ulist->nodes[i].rb_node, &ulist->root);
+ ret = ulist_rbtree_insert(ulist, &new_nodes[i]);
+ BUG_ON(ret);
+ }
+
ulist->nodes = new_nodes;
ulist->nodes_alloced = new_alloced;
}