Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nstree: add helper to operate on struct ns_tree_{node,root}

Add helpers that work on the combined rbtree and rculist combined.
This will make the code a lot more managable and legible.

Link: https://patch.msgid.link/20251110-work-namespace-nstree-fixes-v1-4-e8a9264e0fb9@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

+93
+8
include/linux/nstree.h
··· 22 22 extern struct ns_tree user_ns_tree; 23 23 extern struct ns_tree uts_ns_tree; 24 24 25 + void ns_tree_node_init(struct ns_tree_node *node); 26 + void ns_tree_root_init(struct ns_tree_root *root); 27 + bool ns_tree_node_empty(const struct ns_tree_node *node); 28 + struct rb_node *ns_tree_node_add(struct ns_tree_node *node, 29 + struct ns_tree_root *root, 30 + int (*cmp)(struct rb_node *, const struct rb_node *)); 31 + void ns_tree_node_del(struct ns_tree_node *node, struct ns_tree_root *root); 32 + 25 33 #define to_ns_tree(__ns) \ 26 34 _Generic((__ns), \ 27 35 struct cgroup_namespace *: &(cgroup_ns_tree), \
+85
kernel/nstree.c
··· 73 73 .type = CLONE_NEWTIME, 74 74 }; 75 75 76 + /** 77 + * ns_tree_node_init - Initialize a namespace tree node 78 + * @node: The node to initialize 79 + * 80 + * Initializes both the rbtree node and list entry. 81 + */ 82 + void ns_tree_node_init(struct ns_tree_node *node) 83 + { 84 + RB_CLEAR_NODE(&node->ns_node); 85 + INIT_LIST_HEAD(&node->ns_list_entry); 86 + } 87 + 88 + /** 89 + * ns_tree_root_init - Initialize a namespace tree root 90 + * @root: The root to initialize 91 + * 92 + * Initializes both the rbtree root and list head. 93 + */ 94 + void ns_tree_root_init(struct ns_tree_root *root) 95 + { 96 + root->ns_rb = RB_ROOT; 97 + INIT_LIST_HEAD(&root->ns_list_head); 98 + } 99 + 100 + /** 101 + * ns_tree_node_empty - Check if a namespace tree node is empty 102 + * @node: The node to check 103 + * 104 + * Returns true if the node is not in any tree. 105 + */ 106 + bool ns_tree_node_empty(const struct ns_tree_node *node) 107 + { 108 + return RB_EMPTY_NODE(&node->ns_node); 109 + } 110 + 111 + /** 112 + * ns_tree_node_add - Add a node to a namespace tree 113 + * @node: The node to add 114 + * @root: The tree root to add to 115 + * @cmp: Comparison function for rbtree insertion 116 + * 117 + * Adds the node to both the rbtree and the list, maintaining sorted order. 118 + * The list is maintained in the same order as the rbtree to enable efficient 119 + * iteration. 120 + * 121 + * Returns: NULL if insertion succeeded, existing node if duplicate found 122 + */ 123 + struct rb_node *ns_tree_node_add(struct ns_tree_node *node, 124 + struct ns_tree_root *root, 125 + int (*cmp)(struct rb_node *, const struct rb_node *)) 126 + { 127 + struct rb_node *ret, *prev; 128 + 129 + /* Add to rbtree */ 130 + ret = rb_find_add_rcu(&node->ns_node, &root->ns_rb, cmp); 131 + 132 + /* Add to list in sorted order */ 133 + prev = rb_prev(&node->ns_node); 134 + if (!prev) { 135 + /* No previous node, add at head */ 136 + list_add_rcu(&node->ns_list_entry, &root->ns_list_head); 137 + } else { 138 + /* Add after previous node */ 139 + struct ns_tree_node *prev_node; 140 + prev_node = rb_entry(prev, struct ns_tree_node, ns_node); 141 + list_add_rcu(&node->ns_list_entry, &prev_node->ns_list_entry); 142 + } 143 + 144 + return ret; 145 + } 146 + 147 + /** 148 + * ns_tree_node_del - Remove a node from a namespace tree 149 + * @node: The node to remove 150 + * @root: The tree root to remove from 151 + * 152 + * Removes the node from both the rbtree and the list atomically. 153 + */ 154 + void ns_tree_node_del(struct ns_tree_node *node, struct ns_tree_root *root) 155 + { 156 + rb_erase(&node->ns_node, &root->ns_rb); 157 + RB_CLEAR_NODE(&node->ns_node); 158 + list_bidir_del_rcu(&node->ns_list_entry); 159 + } 160 + 76 161 static inline struct ns_common *node_to_ns(const struct rb_node *node) 77 162 { 78 163 if (!node)