summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2025-11-11 10:01:37 +0100
committerChristian Brauner <brauner@kernel.org>2025-11-11 10:01:37 +0100
commit18b5c400482f3f42875ad3b64961bf479ea4dfaa (patch)
tree0ab77c53bf77599d062cd1b3c4a08a0e6994b039 /kernel
parenta67ee4e2ba7643b2ff2b808155429aa4f51d57a4 (diff)
parent6453937581abc05c5e54525c65abb46955a91cd3 (diff)
Merge patch series "ns: header cleanups and initial namespace reference count improvements"
Christian Brauner <brauner@kernel.org> says: Cleanup the namespace headers by splitting them into types and helpers. Better separate common namepace types and functions from namespace tree types and functions. Fix the reference counts of initial namespaces so we don't do any pointless cacheline ping-pong for them when we know they can never go away. Add a bunch of asserts for both the passive and active reference counts to catch any changes that would break it. * patches from https://patch.msgid.link/20251110-work-namespace-nstree-fixes-v1-0-e8a9264e0fb9@kernel.org: selftests/namespaces: fix nsid tests ns: drop custom reference count initialization for initial namespaces pid: rely on common reference count behavior ns: add asserts for initial namespace active reference counts ns: add asserts for initial namespace reference counts ns: make all reference counts on initial namespace a nop ipc: enable is_ns_init_id() assertions fs: use boolean to indicate anonymous mount namespace ns: rename is_initial_namespace() ns: make is_initial_namespace() argument const nstree: use guards for ns_tree_lock nstree: simplify owner list iteration nstree: switch to new structures nstree: add helper to operate on struct ns_tree_{node,root} nstree: move nstree types into separate header nstree: decouple from ns_common header ns: move namespace types into separate header Link: https://patch.msgid.link/20251110-work-namespace-nstree-fixes-v1-0-e8a9264e0fb9@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup/cgroup.c2
-rw-r--r--kernel/nscommon.c15
-rw-r--r--kernel/nstree.c304
-rw-r--r--kernel/pid.c2
-rw-r--r--kernel/pid_namespace.c2
-rw-r--r--kernel/time/namespace.c2
-rw-r--r--kernel/user.c2
7 files changed, 187 insertions, 142 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 20ab84b2cf4e..2bf3951ca88f 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -250,7 +250,7 @@ bool cgroup_enable_per_threadgroup_rwsem __read_mostly;
/* cgroup namespace for init task */
struct cgroup_namespace init_cgroup_ns = {
- .ns = NS_COMMON_INIT(init_cgroup_ns, 2),
+ .ns = NS_COMMON_INIT(init_cgroup_ns),
.user_ns = &init_user_ns,
.root_cset = &init_css_set,
};
diff --git a/kernel/nscommon.c b/kernel/nscommon.c
index c910b979e433..bdc3c86231d3 100644
--- a/kernel/nscommon.c
+++ b/kernel/nscommon.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2025 Christian Brauner <brauner@kernel.org> */
#include <linux/ns_common.h>
+#include <linux/nstree.h>
#include <linux/proc_ns.h>
#include <linux/user_namespace.h>
#include <linux/vfsdebug.h>
@@ -61,14 +62,10 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
ns->ops = ops;
ns->ns_id = 0;
ns->ns_type = ns_type;
- RB_CLEAR_NODE(&ns->ns_tree_node);
- RB_CLEAR_NODE(&ns->ns_unified_tree_node);
- RB_CLEAR_NODE(&ns->ns_owner_tree_node);
- INIT_LIST_HEAD(&ns->ns_list_node);
- INIT_LIST_HEAD(&ns->ns_unified_list_node);
- ns->ns_owner_tree = RB_ROOT;
- INIT_LIST_HEAD(&ns->ns_owner);
- INIT_LIST_HEAD(&ns->ns_owner_entry);
+ ns_tree_node_init(&ns->ns_tree_node);
+ ns_tree_node_init(&ns->ns_unified_node);
+ ns_tree_node_init(&ns->ns_owner_node);
+ ns_tree_root_init(&ns->ns_owner_root);
#ifdef CONFIG_DEBUG_VFS
ns_debug(ns, ops);
@@ -85,7 +82,7 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
* active use (installed in nsproxy) and decremented when all
* active uses are gone. Initial namespaces are always active.
*/
- if (is_initial_namespace(ns))
+ if (is_ns_init_inum(ns))
atomic_set(&ns->__ns_ref_active, 1);
else
atomic_set(&ns->__ns_ref_active, 0);
diff --git a/kernel/nstree.c b/kernel/nstree.c
index 97404fb90749..5270e0fa67a2 100644
--- a/kernel/nstree.c
+++ b/kernel/nstree.c
@@ -9,89 +9,165 @@
#include <linux/user_namespace.h>
static __cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock);
-static struct rb_root ns_unified_tree = RB_ROOT; /* protected by ns_tree_lock */
-static LIST_HEAD(ns_unified_list); /* protected by ns_tree_lock */
-/**
- * struct ns_tree - Namespace tree
- * @ns_tree: Rbtree of namespaces of a particular type
- * @ns_list: Sequentially walkable list of all namespaces of this type
- * @type: type of namespaces in this tree
- */
-struct ns_tree {
- struct rb_root ns_tree;
- struct list_head ns_list;
- int type;
+DEFINE_LOCK_GUARD_0(ns_tree_writer,
+ write_seqlock(&ns_tree_lock),
+ write_sequnlock(&ns_tree_lock))
+
+DEFINE_LOCK_GUARD_0(ns_tree_locked_reader,
+ read_seqlock_excl(&ns_tree_lock),
+ read_sequnlock_excl(&ns_tree_lock))
+
+static struct ns_tree_root ns_unified_root = { /* protected by ns_tree_lock */
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(ns_unified_root.ns_list_head),
};
-struct ns_tree mnt_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(mnt_ns_tree.ns_list),
- .type = CLONE_NEWNS,
+struct ns_tree_root mnt_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(mnt_ns_tree.ns_list_head),
};
-struct ns_tree net_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(net_ns_tree.ns_list),
- .type = CLONE_NEWNET,
+struct ns_tree_root net_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(net_ns_tree.ns_list_head),
};
EXPORT_SYMBOL_GPL(net_ns_tree);
-struct ns_tree uts_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(uts_ns_tree.ns_list),
- .type = CLONE_NEWUTS,
+struct ns_tree_root uts_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(uts_ns_tree.ns_list_head),
};
-struct ns_tree user_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(user_ns_tree.ns_list),
- .type = CLONE_NEWUSER,
+struct ns_tree_root user_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(user_ns_tree.ns_list_head),
};
-struct ns_tree ipc_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(ipc_ns_tree.ns_list),
- .type = CLONE_NEWIPC,
+struct ns_tree_root ipc_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(ipc_ns_tree.ns_list_head),
};
-struct ns_tree pid_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(pid_ns_tree.ns_list),
- .type = CLONE_NEWPID,
+struct ns_tree_root pid_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(pid_ns_tree.ns_list_head),
};
-struct ns_tree cgroup_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(cgroup_ns_tree.ns_list),
- .type = CLONE_NEWCGROUP,
+struct ns_tree_root cgroup_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(cgroup_ns_tree.ns_list_head),
};
-struct ns_tree time_ns_tree = {
- .ns_tree = RB_ROOT,
- .ns_list = LIST_HEAD_INIT(time_ns_tree.ns_list),
- .type = CLONE_NEWTIME,
+struct ns_tree_root time_ns_tree = {
+ .ns_rb = RB_ROOT,
+ .ns_list_head = LIST_HEAD_INIT(time_ns_tree.ns_list_head),
};
+/**
+ * ns_tree_node_init - Initialize a namespace tree node
+ * @node: The node to initialize
+ *
+ * Initializes both the rbtree node and list entry.
+ */
+void ns_tree_node_init(struct ns_tree_node *node)
+{
+ RB_CLEAR_NODE(&node->ns_node);
+ INIT_LIST_HEAD(&node->ns_list_entry);
+}
+
+/**
+ * ns_tree_root_init - Initialize a namespace tree root
+ * @root: The root to initialize
+ *
+ * Initializes both the rbtree root and list head.
+ */
+void ns_tree_root_init(struct ns_tree_root *root)
+{
+ root->ns_rb = RB_ROOT;
+ INIT_LIST_HEAD(&root->ns_list_head);
+}
+
+/**
+ * ns_tree_node_empty - Check if a namespace tree node is empty
+ * @node: The node to check
+ *
+ * Returns true if the node is not in any tree.
+ */
+bool ns_tree_node_empty(const struct ns_tree_node *node)
+{
+ return RB_EMPTY_NODE(&node->ns_node);
+}
+
+/**
+ * ns_tree_node_add - Add a node to a namespace tree
+ * @node: The node to add
+ * @root: The tree root to add to
+ * @cmp: Comparison function for rbtree insertion
+ *
+ * Adds the node to both the rbtree and the list, maintaining sorted order.
+ * The list is maintained in the same order as the rbtree to enable efficient
+ * iteration.
+ *
+ * Returns: NULL if insertion succeeded, existing node if duplicate found
+ */
+struct rb_node *ns_tree_node_add(struct ns_tree_node *node,
+ struct ns_tree_root *root,
+ int (*cmp)(struct rb_node *, const struct rb_node *))
+{
+ struct rb_node *ret, *prev;
+
+ /* Add to rbtree */
+ ret = rb_find_add_rcu(&node->ns_node, &root->ns_rb, cmp);
+
+ /* Add to list in sorted order */
+ prev = rb_prev(&node->ns_node);
+ if (!prev) {
+ /* No previous node, add at head */
+ list_add_rcu(&node->ns_list_entry, &root->ns_list_head);
+ } else {
+ /* Add after previous node */
+ struct ns_tree_node *prev_node;
+ prev_node = rb_entry(prev, struct ns_tree_node, ns_node);
+ list_add_rcu(&node->ns_list_entry, &prev_node->ns_list_entry);
+ }
+
+ return ret;
+}
+
+/**
+ * ns_tree_node_del - Remove a node from a namespace tree
+ * @node: The node to remove
+ * @root: The tree root to remove from
+ *
+ * Removes the node from both the rbtree and the list atomically.
+ */
+void ns_tree_node_del(struct ns_tree_node *node, struct ns_tree_root *root)
+{
+ rb_erase(&node->ns_node, &root->ns_rb);
+ RB_CLEAR_NODE(&node->ns_node);
+ list_bidir_del_rcu(&node->ns_list_entry);
+}
+
static inline struct ns_common *node_to_ns(const struct rb_node *node)
{
if (!node)
return NULL;
- return rb_entry(node, struct ns_common, ns_tree_node);
+ return rb_entry(node, struct ns_common, ns_tree_node.ns_node);
}
static inline struct ns_common *node_to_ns_unified(const struct rb_node *node)
{
if (!node)
return NULL;
- return rb_entry(node, struct ns_common, ns_unified_tree_node);
+ return rb_entry(node, struct ns_common, ns_unified_node.ns_node);
}
static inline struct ns_common *node_to_ns_owner(const struct rb_node *node)
{
if (!node)
return NULL;
- return rb_entry(node, struct ns_common, ns_owner_tree_node);
+ return rb_entry(node, struct ns_common, ns_owner_node.ns_node);
}
static int ns_id_cmp(u64 id_a, u64 id_b)
@@ -118,35 +194,22 @@ static int ns_cmp_owner(struct rb_node *a, const struct rb_node *b)
return ns_id_cmp(node_to_ns_owner(a)->ns_id, node_to_ns_owner(b)->ns_id);
}
-void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
+void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree_root *ns_tree)
{
- struct rb_node *node, *prev;
+ struct rb_node *node;
const struct proc_ns_operations *ops = ns->ops;
VFS_WARN_ON_ONCE(!ns->ns_id);
- VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
- write_seqlock(&ns_tree_lock);
+ guard(ns_tree_writer)();
- node = rb_find_add_rcu(&ns->ns_tree_node, &ns_tree->ns_tree, ns_cmp);
- /*
- * If there's no previous entry simply add it after the
- * head and if there is add it after the previous entry.
- */
- prev = rb_prev(&ns->ns_tree_node);
- if (!prev)
- list_add_rcu(&ns->ns_list_node, &ns_tree->ns_list);
- else
- list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node);
+ /* Add to per-type tree and list */
+ node = ns_tree_node_add(&ns->ns_tree_node, ns_tree, ns_cmp);
/* Add to unified tree and list */
- rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unified);
- prev = rb_prev(&ns->ns_unified_tree_node);
- if (!prev)
- list_add_rcu(&ns->ns_unified_list_node, &ns_unified_list);
- else
- list_add_rcu(&ns->ns_unified_list_node, &node_to_ns_unified(prev)->ns_unified_list_node);
+ ns_tree_node_add(&ns->ns_unified_node, &ns_unified_root, ns_cmp_unified);
+ /* Add to owner's tree if applicable */
if (ops) {
struct user_namespace *user_ns;
@@ -156,55 +219,40 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
struct ns_common *owner = &user_ns->ns;
VFS_WARN_ON_ONCE(owner->ns_type != CLONE_NEWUSER);
- /* Insert into owner's rbtree */
- rb_find_add_rcu(&ns->ns_owner_tree_node, &owner->ns_owner_tree, ns_cmp_owner);
-
- /* Insert into owner's list in sorted order */
- prev = rb_prev(&ns->ns_owner_tree_node);
- if (!prev)
- list_add_rcu(&ns->ns_owner_entry, &owner->ns_owner);
- else
- list_add_rcu(&ns->ns_owner_entry, &node_to_ns_owner(prev)->ns_owner_entry);
+ /* Insert into owner's tree and list */
+ ns_tree_node_add(&ns->ns_owner_node, &owner->ns_owner_root, ns_cmp_owner);
} else {
/* Only the initial user namespace doesn't have an owner. */
VFS_WARN_ON_ONCE(ns != to_ns_common(&init_user_ns));
}
}
- write_sequnlock(&ns_tree_lock);
VFS_WARN_ON_ONCE(node);
}
-void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
+void __ns_tree_remove(struct ns_common *ns, struct ns_tree_root *ns_tree)
{
const struct proc_ns_operations *ops = ns->ops;
struct user_namespace *user_ns;
- VFS_WARN_ON_ONCE(RB_EMPTY_NODE(&ns->ns_tree_node));
- VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node));
- VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
+ VFS_WARN_ON_ONCE(ns_tree_node_empty(&ns->ns_tree_node));
+ VFS_WARN_ON_ONCE(list_empty(&ns->ns_tree_node.ns_list_entry));
write_seqlock(&ns_tree_lock);
- rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree);
- RB_CLEAR_NODE(&ns->ns_tree_node);
-
- list_bidir_del_rcu(&ns->ns_list_node);
- rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree);
- RB_CLEAR_NODE(&ns->ns_unified_tree_node);
+ /* Remove from per-type tree and list */
+ ns_tree_node_del(&ns->ns_tree_node, ns_tree);
- list_bidir_del_rcu(&ns->ns_unified_list_node);
+ /* Remove from unified tree and list */
+ ns_tree_node_del(&ns->ns_unified_node, &ns_unified_root);
- /* Remove from owner's rbtree if this namespace has an owner */
+ /* Remove from owner's tree if applicable */
if (ops) {
user_ns = ops->owner(ns);
if (user_ns) {
struct ns_common *owner = &user_ns->ns;
- rb_erase(&ns->ns_owner_tree_node, &owner->ns_owner_tree);
- RB_CLEAR_NODE(&ns->ns_owner_tree_node);
+ ns_tree_node_del(&ns->ns_owner_node, &owner->ns_owner_root);
}
-
- list_bidir_del_rcu(&ns->ns_owner_entry);
}
write_sequnlock(&ns_tree_lock);
@@ -235,7 +283,7 @@ static int ns_find_unified(const void *key, const struct rb_node *node)
return 0;
}
-static struct ns_tree *ns_tree_from_type(int ns_type)
+static struct ns_tree_root *ns_tree_from_type(int ns_type)
{
switch (ns_type) {
case CLONE_NEWCGROUP:
@@ -266,7 +314,7 @@ static struct ns_common *__ns_unified_tree_lookup_rcu(u64 ns_id)
do {
seq = read_seqbegin(&ns_tree_lock);
- node = rb_find_rcu(&ns_id, &ns_unified_tree, ns_find_unified);
+ node = rb_find_rcu(&ns_id, &ns_unified_root.ns_rb, ns_find_unified);
if (node)
break;
} while (read_seqretry(&ns_tree_lock, seq));
@@ -276,7 +324,7 @@ static struct ns_common *__ns_unified_tree_lookup_rcu(u64 ns_id)
static struct ns_common *__ns_tree_lookup_rcu(u64 ns_id, int ns_type)
{
- struct ns_tree *ns_tree;
+ struct ns_tree_root *ns_tree;
struct rb_node *node;
unsigned int seq;
@@ -286,7 +334,7 @@ static struct ns_common *__ns_tree_lookup_rcu(u64 ns_id, int ns_type)
do {
seq = read_seqbegin(&ns_tree_lock);
- node = rb_find_rcu(&ns_id, &ns_tree->ns_tree, ns_find);
+ node = rb_find_rcu(&ns_id, &ns_tree->ns_rb, ns_find);
if (node)
break;
} while (read_seqretry(&ns_tree_lock, seq));
@@ -314,22 +362,20 @@ struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type)
* there is no next/previous namespace, -ENOENT is returned.
*/
struct ns_common *__ns_tree_adjoined_rcu(struct ns_common *ns,
- struct ns_tree *ns_tree, bool previous)
+ struct ns_tree_root *ns_tree, bool previous)
{
struct list_head *list;
RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_adjoined_rcu() usage");
if (previous)
- list = rcu_dereference(list_bidir_prev_rcu(&ns->ns_list_node));
+ list = rcu_dereference(list_bidir_prev_rcu(&ns->ns_tree_node.ns_list_entry));
else
- list = rcu_dereference(list_next_rcu(&ns->ns_list_node));
- if (list_is_head(list, &ns_tree->ns_list))
+ list = rcu_dereference(list_next_rcu(&ns->ns_tree_node.ns_list_entry));
+ if (list_is_head(list, &ns_tree->ns_list_head))
return ERR_PTR(-ENOENT);
- VFS_WARN_ON_ONCE(list_entry_rcu(list, struct ns_common, ns_list_node)->ns_type != ns_tree->type);
-
- return list_entry_rcu(list, struct ns_common, ns_list_node);
+ return list_entry_rcu(list, struct ns_common, ns_tree_node.ns_list_entry);
}
/**
@@ -422,9 +468,9 @@ static struct ns_common *lookup_ns_owner_at(u64 ns_id, struct ns_common *owner)
VFS_WARN_ON_ONCE(owner->ns_type != CLONE_NEWUSER);
- read_seqlock_excl(&ns_tree_lock);
- node = owner->ns_owner_tree.rb_node;
+ guard(ns_tree_locked_reader)();
+ node = owner->ns_owner_root.ns_rb.rb_node;
while (node) {
struct ns_common *ns;
@@ -441,7 +487,6 @@ static struct ns_common *lookup_ns_owner_at(u64 ns_id, struct ns_common *owner)
if (ret)
ret = ns_get_unless_inactive(ret);
- read_sequnlock_excl(&ns_tree_lock);
return ret;
}
@@ -553,18 +598,21 @@ static ssize_t do_listns_userns(struct klistns *kls)
}
ret = 0;
- head = &to_ns_common(kls->user_ns)->ns_owner;
+ head = &to_ns_common(kls->user_ns)->ns_owner_root.ns_list_head;
kls->userns_capable = ns_capable_noaudit(kls->user_ns, CAP_SYS_ADMIN);
rcu_read_lock();
if (!first_ns)
- first_ns = list_entry_rcu(head->next, typeof(*ns), ns_owner_entry);
+ first_ns = list_entry_rcu(head->next, typeof(*first_ns), ns_owner_node.ns_list_entry);
- for (ns = first_ns; &ns->ns_owner_entry != head && nr_ns_ids;
- ns = list_entry_rcu(ns->ns_owner_entry.next, typeof(*ns), ns_owner_entry)) {
+ ns = first_ns;
+ list_for_each_entry_from_rcu(ns, head, ns_owner_node.ns_list_entry) {
struct ns_common *valid;
+ if (!nr_ns_ids)
+ break;
+
valid = legitimize_ns(kls, ns);
if (!valid)
continue;
@@ -597,7 +645,7 @@ static ssize_t do_listns_userns(struct klistns *kls)
static struct ns_common *lookup_ns_id_at(u64 ns_id, int ns_type)
{
struct ns_common *ret = NULL;
- struct ns_tree *ns_tree = NULL;
+ struct ns_tree_root *ns_tree = NULL;
struct rb_node *node;
if (ns_type) {
@@ -606,11 +654,12 @@ static struct ns_common *lookup_ns_id_at(u64 ns_id, int ns_type)
return NULL;
}
- read_seqlock_excl(&ns_tree_lock);
+ guard(ns_tree_locked_reader)();
+
if (ns_tree)
- node = ns_tree->ns_tree.rb_node;
+ node = ns_tree->ns_rb.rb_node;
else
- node = ns_unified_tree.rb_node;
+ node = ns_unified_root.ns_rb.rb_node;
while (node) {
struct ns_common *ns;
@@ -635,33 +684,32 @@ static struct ns_common *lookup_ns_id_at(u64 ns_id, int ns_type)
if (ret)
ret = ns_get_unless_inactive(ret);
- read_sequnlock_excl(&ns_tree_lock);
return ret;
}
static inline struct ns_common *first_ns_common(const struct list_head *head,
- struct ns_tree *ns_tree)
+ struct ns_tree_root *ns_tree)
{
if (ns_tree)
- return list_entry_rcu(head->next, struct ns_common, ns_list_node);
- return list_entry_rcu(head->next, struct ns_common, ns_unified_list_node);
+ return list_entry_rcu(head->next, struct ns_common, ns_tree_node.ns_list_entry);
+ return list_entry_rcu(head->next, struct ns_common, ns_unified_node.ns_list_entry);
}
static inline struct ns_common *next_ns_common(struct ns_common *ns,
- struct ns_tree *ns_tree)
+ struct ns_tree_root *ns_tree)
{
if (ns_tree)
- return list_entry_rcu(ns->ns_list_node.next, struct ns_common, ns_list_node);
- return list_entry_rcu(ns->ns_unified_list_node.next, struct ns_common, ns_unified_list_node);
+ return list_entry_rcu(ns->ns_tree_node.ns_list_entry.next, struct ns_common, ns_tree_node.ns_list_entry);
+ return list_entry_rcu(ns->ns_unified_node.ns_list_entry.next, struct ns_common, ns_unified_node.ns_list_entry);
}
static inline bool ns_common_is_head(struct ns_common *ns,
const struct list_head *head,
- struct ns_tree *ns_tree)
+ struct ns_tree_root *ns_tree)
{
if (ns_tree)
- return &ns->ns_list_node == head;
- return &ns->ns_unified_list_node == head;
+ return &ns->ns_tree_node.ns_list_entry == head;
+ return &ns->ns_unified_node.ns_list_entry == head;
}
static ssize_t do_listns(struct klistns *kls)
@@ -669,7 +717,7 @@ static ssize_t do_listns(struct klistns *kls)
u64 __user *ns_ids = kls->uns_ids;
size_t nr_ns_ids = kls->nr_ns_ids;
struct ns_common *ns, *first_ns = NULL, *prev = NULL;
- struct ns_tree *ns_tree = NULL;
+ struct ns_tree_root *ns_tree = NULL;
const struct list_head *head;
u32 ns_type;
ssize_t ret;
@@ -694,9 +742,9 @@ static ssize_t do_listns(struct klistns *kls)
ret = 0;
if (ns_tree)
- head = &ns_tree->ns_list;
+ head = &ns_tree->ns_list_head;
else
- head = &ns_unified_list;
+ head = &ns_unified_root.ns_list_head;
rcu_read_lock();
diff --git a/kernel/pid.c b/kernel/pid.c
index a5a63dc0a491..a31771bc89c1 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -71,7 +71,7 @@ static int pid_max_max = PID_MAX_LIMIT;
* the scheme scales to up to 4 million PIDs, runtime.
*/
struct pid_namespace init_pid_ns = {
- .ns = NS_COMMON_INIT(init_pid_ns, 2),
+ .ns = NS_COMMON_INIT(init_pid_ns),
.idr = IDR_INIT(init_pid_ns.idr),
.pid_allocated = PIDNS_ADDING,
.level = 0,
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 650be58d8d18..e48f5de41361 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -184,7 +184,7 @@ struct pid_namespace *copy_pid_ns(u64 flags,
void put_pid_ns(struct pid_namespace *ns)
{
- if (ns && ns != &init_pid_ns && ns_ref_put(ns))
+ if (ns && ns_ref_put(ns))
schedule_work(&ns->work);
}
EXPORT_SYMBOL_GPL(put_pid_ns);
diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c
index 19911f88e2b8..e76be24b132c 100644
--- a/kernel/time/namespace.c
+++ b/kernel/time/namespace.c
@@ -478,7 +478,7 @@ const struct proc_ns_operations timens_for_children_operations = {
};
struct time_namespace init_time_ns = {
- .ns = NS_COMMON_INIT(init_time_ns, 3),
+ .ns = NS_COMMON_INIT(init_time_ns),
.user_ns = &init_user_ns,
.frozen_offsets = true,
};
diff --git a/kernel/user.c b/kernel/user.c
index 4b3132e786d9..7aef4e679a6a 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL_GPL(init_binfmt_misc);
* and 1 for... ?
*/
struct user_namespace init_user_ns = {
- .ns = NS_COMMON_INIT(init_user_ns, 3),
+ .ns = NS_COMMON_INIT(init_user_ns),
.uid_map = {
{
.extent[0] = {