[PATCH v2 11/18] kho: add kho_radix_init_tree()

From: Pratyush Yadav

Date: Fri Jun 05 2026 - 14:53:30 EST


From: "Pratyush Yadav (Google)" <pratyush@xxxxxxxxxx>

Move the initialization logic of the radix tree into
kho_radix_init_tree() instead of having users open-code it. Makes the
boundaries cleaner and reduces code duplication when a new user of the
radix tree will be added in a future commit.

Signed-off-by: Pratyush Yadav (Google) <pratyush@xxxxxxxxxx>
---
include/linux/kho_radix_tree.h | 7 ++++
kernel/liveupdate/kexec_handover.c | 66 ++++++++++++++++++++++--------
2 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/include/linux/kho_radix_tree.h b/include/linux/kho_radix_tree.h
index 66ca936b3f06..5d6ae2893684 100644
--- a/include/linux/kho_radix_tree.h
+++ b/include/linux/kho_radix_tree.h
@@ -54,6 +54,7 @@ int kho_radix_add_key(struct kho_radix_tree *tree, unsigned long key);
void kho_radix_del_key(struct kho_radix_tree *tree, unsigned long key);
int kho_radix_walk_tree(struct kho_radix_tree *tree,
const struct kho_radix_walk_cb *cb, void *data);
+int kho_radix_init_tree(struct kho_radix_tree *tree, struct kho_radix_node *root);
void kho_radix_destroy_tree(struct kho_radix_tree *tree);

#else /* #ifdef CONFIG_KEXEC_HANDOVER */
@@ -72,6 +73,12 @@ static inline int kho_radix_walk_tree(struct kho_radix_tree *tree,
return -EOPNOTSUPP;
}

+static inline int kho_radix_init_tree(struct kho_radix_tree *tree,
+ struct kho_radix_node *root)
+{
+ return 0;
+}
+
static inline void kho_radix_destroy_tree(struct kho_radix_tree *tree) { }

#endif /* #ifdef CONFIG_KEXEC_HANDOVER */
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index df3f5eb01bf1..8ab2c7e234e1 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -317,6 +317,34 @@ static void __kho_radix_destroy_tree(struct kho_radix_node *root,
kho_radix_free_node(root);
}

+/**
+ * kho_radix_init_tree - initialize the radix tree.
+ * @tree: the tree to initialize.
+ * @root: root table of the radix tree.
+ *
+ * Initialize the radix tree with the given root node. If root is %NULL, an
+ * empty root table is allocated. If root is not %NULL, it is the caller's
+ * responsibility to make sure the root is valid and in the correct format.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int kho_radix_init_tree(struct kho_radix_tree *tree, struct kho_radix_node *root)
+{
+ /* Already initialized. */
+ if (tree->root)
+ return 0;
+
+ if (!root)
+ root = kho_radix_alloc_node();
+ if (!root)
+ return -ENOMEM;
+
+ tree->root = root;
+ mutex_init(&tree->lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kho_radix_init_tree);
+
/**
* kho_radix_destroy_tree - Destroy the radix tree
* @tree: The radix tree to destroy
@@ -1496,18 +1524,23 @@ static void __init kho_mem_retrieve(void)
* catches that and never sets kho_in.scratch_phys, which stops memory
* retrieval.
*/
- kho_in.radix_tree.root = kho_get_mem_map(fdt);
- mutex_init(&kho_in.radix_tree.lock);
+ err = kho_radix_init_tree(&kho_in.radix_tree, kho_get_mem_map(fdt));
+ if (err)
+ goto err;

err = kho_radix_walk_tree(&kho_in.radix_tree, &cb, NULL);
- if (err) {
- /*
- * Failed to initialize preserved memory. Clear FDT and radix
- * so KHO users don't treat it as a KHO boot.
- */
- kho_in.fdt_phys = 0;
- kho_in.radix_tree.root = NULL;
- }
+ if (err)
+ goto err;
+
+ return;
+
+err:
+ /*
+ * Failed to initialize preserved memory. Clear FDT and radix so KHO
+ * users don't treat it as a KHO boot.
+ */
+ kho_in.fdt_phys = 0;
+ kho_in.radix_tree.root = NULL;
}

static __init int kho_out_fdt_setup(void)
@@ -1633,16 +1666,14 @@ static __init int kho_init(void)
if (!kho_enable)
return 0;

- tree->root = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!tree->root) {
- err = -ENOMEM;
+ err = kho_radix_init_tree(tree, NULL);
+ if (err)
goto err_free_scratch;
- }

kho_out.fdt = kho_alloc_preserve(PAGE_SIZE);
if (IS_ERR(kho_out.fdt)) {
err = PTR_ERR(kho_out.fdt);
- goto err_free_kho_radix_tree_root;
+ goto err_free_kho_radix_tree;
}

err = kho_debugfs_init();
@@ -1693,9 +1724,8 @@ static __init int kho_init(void)

err_free_fdt:
kho_unpreserve_free(kho_out.fdt);
-err_free_kho_radix_tree_root:
- kfree(tree->root);
- tree->root = NULL;
+err_free_kho_radix_tree:
+ kho_radix_destroy_tree(tree);
err_free_scratch:
kho_out.fdt = NULL;
for (int i = 0; i < kho_scratch_cnt; i++) {
--
2.54.0.1032.g2f8565e1d1-goog