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

Configure Feed

Select the types of activity you want to include in your feed.

nstree: assign fixed ids to the initial namespaces

The initial set of namespace comes with fixed inode numbers making it
easy for userspace to identify them solely based on that information.
This has long preceeded anything here.

Similarly, let's assign fixed namespace ids for the initial namespaces.

Kill the cookie and use a sequentially increasing number. This has the
nice side-effect that the owning user namespace will always have a
namespace id that is smaller than any of it's descendant namespaces.

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

+47 -12
+1 -1
fs/namespace.c
··· 4094 4094 return ERR_PTR(ret); 4095 4095 } 4096 4096 if (!anon) 4097 - ns_tree_gen_id(&new_ns->ns); 4097 + ns_tree_gen_id(new_ns); 4098 4098 refcount_set(&new_ns->passive, 1); 4099 4099 new_ns->mounts = RB_ROOT; 4100 4100 init_waitqueue_head(&new_ns->poll);
+12 -1
include/linux/ns_common.h
··· 173 173 struct user_namespace *: &init_user_ns, \ 174 174 struct uts_namespace *: &init_uts_ns) 175 175 176 + #define ns_init_id(__ns) \ 177 + _Generic((__ns), \ 178 + struct cgroup_namespace *: CGROUP_NS_INIT_ID, \ 179 + struct ipc_namespace *: IPC_NS_INIT_ID, \ 180 + struct mnt_namespace *: MNT_NS_INIT_ID, \ 181 + struct net *: NET_NS_INIT_ID, \ 182 + struct pid_namespace *: PID_NS_INIT_ID, \ 183 + struct time_namespace *: TIME_NS_INIT_ID, \ 184 + struct user_namespace *: USER_NS_INIT_ID, \ 185 + struct uts_namespace *: UTS_NS_INIT_ID) 186 + 176 187 #define to_ns_operations(__ns) \ 177 188 _Generic((__ns), \ 178 189 struct cgroup_namespace *: (IS_ENABLED(CONFIG_CGROUPS) ? &cgroupns_operations : NULL), \ ··· 209 198 #define NS_COMMON_INIT(nsname, refs) \ 210 199 { \ 211 200 .ns_type = ns_common_type(&nsname), \ 212 - .ns_id = 0, \ 201 + .ns_id = ns_init_id(&nsname), \ 213 202 .inum = ns_init_inum(&nsname), \ 214 203 .ops = to_ns_operations(&nsname), \ 215 204 .stashed = NULL, \
+11 -4
include/linux/nstree.h
··· 9 9 #include <linux/seqlock.h> 10 10 #include <linux/rculist.h> 11 11 #include <linux/cookie.h> 12 + #include <uapi/linux/nsfs.h> 12 13 13 14 extern struct ns_tree cgroup_ns_tree; 14 15 extern struct ns_tree ipc_ns_tree; ··· 31 30 struct user_namespace *: &(user_ns_tree), \ 32 31 struct uts_namespace *: &(uts_ns_tree)) 33 32 34 - u64 ns_tree_gen_id(struct ns_common *ns); 33 + #define ns_tree_gen_id(__ns) \ 34 + __ns_tree_gen_id(to_ns_common(__ns), \ 35 + (((__ns) == ns_init_ns(__ns)) ? ns_init_id(__ns) : 0)) 36 + 37 + u64 __ns_tree_gen_id(struct ns_common *ns, u64 id); 35 38 void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree); 36 39 void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree); 37 40 struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type); ··· 43 38 struct ns_tree *ns_tree, 44 39 bool previous); 45 40 46 - static inline void __ns_tree_add(struct ns_common *ns, struct ns_tree *ns_tree) 41 + static inline void __ns_tree_add(struct ns_common *ns, struct ns_tree *ns_tree, u64 id) 47 42 { 48 - ns_tree_gen_id(ns); 43 + __ns_tree_gen_id(ns, id); 49 44 __ns_tree_add_raw(ns, ns_tree); 50 45 } 51 46 ··· 65 60 * This function assigns a new id to the namespace and adds it to the 66 61 * appropriate namespace tree and list. 67 62 */ 68 - #define ns_tree_add(__ns) __ns_tree_add(to_ns_common(__ns), to_ns_tree(__ns)) 63 + #define ns_tree_add(__ns) \ 64 + __ns_tree_add(to_ns_common(__ns), to_ns_tree(__ns), \ 65 + (((__ns) == ns_init_ns(__ns)) ? ns_init_id(__ns) : 0)) 69 66 70 67 /** 71 68 * ns_tree_remove - Remove a namespace from a namespace tree
+14
include/uapi/linux/nsfs.h
··· 67 67 #define NSFS_FILE_HANDLE_SIZE_VER0 16 /* sizeof first published struct */ 68 68 #define NSFS_FILE_HANDLE_SIZE_LATEST sizeof(struct nsfs_file_handle) /* sizeof latest published struct */ 69 69 70 + enum init_ns_id { 71 + IPC_NS_INIT_ID = 1ULL, 72 + UTS_NS_INIT_ID = 2ULL, 73 + USER_NS_INIT_ID = 3ULL, 74 + PID_NS_INIT_ID = 4ULL, 75 + CGROUP_NS_INIT_ID = 5ULL, 76 + TIME_NS_INIT_ID = 6ULL, 77 + NET_NS_INIT_ID = 7ULL, 78 + MNT_NS_INIT_ID = 8ULL, 79 + #ifdef __KERNEL__ 80 + NS_LAST_INIT_ID = MNT_NS_INIT_ID, 81 + #endif 82 + }; 83 + 70 84 #endif /* __LINUX_NSFS_H */
+8 -5
kernel/nstree.c
··· 69 69 .type = CLONE_NEWTIME, 70 70 }; 71 71 72 - DEFINE_COOKIE(namespace_cookie); 73 - 74 72 static inline struct ns_common *node_to_ns(const struct rb_node *node) 75 73 { 76 74 if (!node) ··· 283 285 /** 284 286 * ns_tree_gen_id - generate a new namespace id 285 287 * @ns: namespace to generate id for 288 + * @id: if non-zero, this is the initial namespace and this is a fixed id 286 289 * 287 290 * Generates a new namespace id and assigns it to the namespace. All 288 291 * namespaces types share the same id space and thus can be compared 289 292 * directly. IOW, when two ids of two namespace are equal, they are 290 293 * identical. 291 294 */ 292 - u64 ns_tree_gen_id(struct ns_common *ns) 295 + u64 __ns_tree_gen_id(struct ns_common *ns, u64 id) 293 296 { 294 - guard(preempt)(); 295 - ns->ns_id = gen_cookie_next(&namespace_cookie); 297 + static atomic64_t namespace_cookie = ATOMIC64_INIT(NS_LAST_INIT_ID + 1); 298 + 299 + if (id) 300 + ns->ns_id = id; 301 + else 302 + ns->ns_id = atomic64_inc_return(&namespace_cookie); 296 303 return ns->ns_id; 297 304 }
+1 -1
net/core/net_namespace.c
··· 439 439 LIST_HEAD(net_exit_list); 440 440 int error = 0; 441 441 442 - net->net_cookie = ns_tree_gen_id(&net->ns); 442 + net->net_cookie = ns_tree_gen_id(net); 443 443 444 444 list_for_each_entry(ops, &pernet_list, list) { 445 445 error = ops_init(ops, net);