summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/ns_common.h2
-rw-r--r--kernel/nscommon.c1
-rw-r--r--kernel/nstree.c13
3 files changed, 15 insertions, 1 deletions
diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
index 698aa2f7f486..3f05dd7d40c7 100644
--- a/include/linux/ns_common.h
+++ b/include/linux/ns_common.h
@@ -111,6 +111,7 @@ struct ns_common {
u64 ns_id;
struct /* global namespace rbtree and list */ {
struct rb_node ns_unified_tree_node;
+ struct list_head ns_unified_list_node;
};
struct /* per type rbtree and list */ {
struct rb_node ns_tree_node;
@@ -224,6 +225,7 @@ static __always_inline bool is_initial_namespace(struct ns_common *ns)
.ns_list_node = LIST_HEAD_INIT(nsname.ns.ns_list_node), \
.ns_owner_entry = LIST_HEAD_INIT(nsname.ns.ns_owner_entry), \
.ns_owner = LIST_HEAD_INIT(nsname.ns.ns_owner), \
+ .ns_unified_list_node = LIST_HEAD_INIT(nsname.ns.ns_unified_list_node), \
}
#define ns_common_init(__ns) \
diff --git a/kernel/nscommon.c b/kernel/nscommon.c
index f0b7971392d2..4cbe1ecc8df0 100644
--- a/kernel/nscommon.c
+++ b/kernel/nscommon.c
@@ -65,6 +65,7 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
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);
diff --git a/kernel/nstree.c b/kernel/nstree.c
index 419d500d09df..dcad6a308547 100644
--- a/kernel/nstree.c
+++ b/kernel/nstree.c
@@ -9,6 +9,7 @@
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
@@ -137,7 +138,13 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
else
list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node);
+ /* 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);
if (ops) {
struct user_namespace *user_ns;
@@ -186,11 +193,15 @@ void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
write_seqlock(&ns_tree_lock);
rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree);
- rb_erase(&ns->ns_unified_tree_node, &ns_unified_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);
+
+ list_bidir_del_rcu(&ns->ns_unified_list_node);
+
/* Remove from owner's rbtree if this namespace has an owner */
if (ops) {
user_ns = ops->owner(ns);