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

nstree: add unified namespace list

Allow to walk the unified namespace list completely locklessly.

Link: https://patch.msgid.link/20251029-work-namespace-nstree-listns-v4-18-2e6f823ebdc0@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

+15 -1
+2
include/linux/ns_common.h
··· 111 111 u64 ns_id; 112 112 struct /* global namespace rbtree and list */ { 113 113 struct rb_node ns_unified_tree_node; 114 + struct list_head ns_unified_list_node; 114 115 }; 115 116 struct /* per type rbtree and list */ { 116 117 struct rb_node ns_tree_node; ··· 225 224 .ns_list_node = LIST_HEAD_INIT(nsname.ns.ns_list_node), \ 226 225 .ns_owner_entry = LIST_HEAD_INIT(nsname.ns.ns_owner_entry), \ 227 226 .ns_owner = LIST_HEAD_INIT(nsname.ns.ns_owner), \ 227 + .ns_unified_list_node = LIST_HEAD_INIT(nsname.ns.ns_unified_list_node), \ 228 228 } 229 229 230 230 #define ns_common_init(__ns) \
+1
kernel/nscommon.c
··· 65 65 RB_CLEAR_NODE(&ns->ns_unified_tree_node); 66 66 RB_CLEAR_NODE(&ns->ns_owner_tree_node); 67 67 INIT_LIST_HEAD(&ns->ns_list_node); 68 + INIT_LIST_HEAD(&ns->ns_unified_list_node); 68 69 ns->ns_owner_tree = RB_ROOT; 69 70 INIT_LIST_HEAD(&ns->ns_owner); 70 71 INIT_LIST_HEAD(&ns->ns_owner_entry);
+12 -1
kernel/nstree.c
··· 9 9 10 10 static __cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock); 11 11 static struct rb_root ns_unified_tree = RB_ROOT; /* protected by ns_tree_lock */ 12 + static LIST_HEAD(ns_unified_list); /* protected by ns_tree_lock */ 12 13 13 14 /** 14 15 * struct ns_tree - Namespace tree ··· 138 137 else 139 138 list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node); 140 139 140 + /* Add to unified tree and list */ 141 141 rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unified); 142 + prev = rb_prev(&ns->ns_unified_tree_node); 143 + if (!prev) 144 + list_add_rcu(&ns->ns_unified_list_node, &ns_unified_list); 145 + else 146 + list_add_rcu(&ns->ns_unified_list_node, &node_to_ns_unified(prev)->ns_unified_list_node); 142 147 143 148 if (ops) { 144 149 struct user_namespace *user_ns; ··· 193 186 194 187 write_seqlock(&ns_tree_lock); 195 188 rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree); 196 - rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); 197 189 RB_CLEAR_NODE(&ns->ns_tree_node); 198 190 199 191 list_bidir_del_rcu(&ns->ns_list_node); 192 + 193 + rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); 194 + RB_CLEAR_NODE(&ns->ns_unified_tree_node); 195 + 196 + list_bidir_del_rcu(&ns->ns_unified_list_node); 200 197 201 198 /* Remove from owner's rbtree if this namespace has an owner */ 202 199 if (ops) {