[PATCH v4 13/72] nstree: introduce a unified tree

Christian Brauner posted 72 patches 3 months, 1 week ago
[PATCH v4 13/72] nstree: introduce a unified tree
Posted by Christian Brauner 3 months, 1 week ago
This will allow userspace to lookup and stat a namespace simply by its
identifier without having to know what type of namespace it is.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/ns_common.h |   4 ++
 kernel/nscommon.c         |   1 +
 kernel/nstree.c           | 114 ++++++++++++++++++++++++++++++++++++----------
 3 files changed, 95 insertions(+), 24 deletions(-)

diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
index adc3542042af..88f27b678b4e 100644
--- a/include/linux/ns_common.h
+++ b/include/linux/ns_common.h
@@ -109,6 +109,10 @@ struct ns_common {
 	union {
 		struct {
 			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;
 				struct list_head ns_list_node;
diff --git a/kernel/nscommon.c b/kernel/nscommon.c
index 1935f640f05a..98a237be64bc 100644
--- a/kernel/nscommon.c
+++ b/kernel/nscommon.c
@@ -61,6 +61,7 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_ope
 	ns->ns_id = 0;
 	ns->ns_type = ns_type;
 	RB_CLEAR_NODE(&ns->ns_tree_node);
+	RB_CLEAR_NODE(&ns->ns_unified_tree_node);
 	INIT_LIST_HEAD(&ns->ns_list_node);
 
 #ifdef CONFIG_DEBUG_VFS
diff --git a/kernel/nstree.c b/kernel/nstree.c
index a231cd2e9368..dbe4fb18f021 100644
--- a/kernel/nstree.c
+++ b/kernel/nstree.c
@@ -4,75 +4,86 @@
 #include <linux/proc_ns.h>
 #include <linux/vfsdebug.h>
 
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock);
+static struct rb_root ns_unified_tree = RB_ROOT; /* 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
- * @ns_tree_lock: Seqlock to protect the tree and list
  * @type: type of namespaces in this tree
  */
 struct ns_tree {
-       struct rb_root ns_tree;
-       struct list_head ns_list;
-       seqlock_t ns_tree_lock;
-       int type;
+	struct rb_root ns_tree;
+	struct list_head ns_list;
+#ifdef CONFIG_DEBUG_VFS
+	int type;
+#endif
 };
 
 struct ns_tree mnt_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(mnt_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(mnt_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWNS,
+#endif
 };
 
 struct ns_tree net_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(net_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(net_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWNET,
+#endif
 };
 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),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(uts_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWUTS,
+#endif
 };
 
 struct ns_tree user_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(user_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(user_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWUSER,
+#endif
 };
 
 struct ns_tree ipc_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(ipc_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(ipc_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWIPC,
+#endif
 };
 
 struct ns_tree pid_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(pid_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(pid_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWPID,
+#endif
 };
 
 struct ns_tree cgroup_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(cgroup_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(cgroup_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWCGROUP,
+#endif
 };
 
 struct ns_tree time_ns_tree = {
 	.ns_tree = RB_ROOT,
 	.ns_list = LIST_HEAD_INIT(time_ns_tree.ns_list),
-	.ns_tree_lock = __SEQLOCK_UNLOCKED(time_ns_tree.ns_tree_lock),
+#ifdef CONFIG_DEBUG_VFS
 	.type = CLONE_NEWTIME,
+#endif
 };
 
 DEFINE_COOKIE(namespace_cookie);
@@ -84,6 +95,13 @@ static inline struct ns_common *node_to_ns(const struct rb_node *node)
 	return rb_entry(node, struct ns_common, ns_tree_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);
+}
+
 static inline int ns_cmp(struct rb_node *a, const struct rb_node *b)
 {
 	struct ns_common *ns_a = node_to_ns(a);
@@ -98,15 +116,27 @@ static inline int ns_cmp(struct rb_node *a, const struct rb_node *b)
 	return 0;
 }
 
+static inline int ns_cmp_unified(struct rb_node *a, const struct rb_node *b)
+{
+	struct ns_common *ns_a = node_to_ns_unified(a);
+	struct ns_common *ns_b = node_to_ns_unified(b);
+	u64 ns_id_a = ns_a->ns_id;
+	u64 ns_id_b = ns_b->ns_id;
+
+	if (ns_id_a < ns_id_b)
+		return -1;
+	if (ns_id_a > ns_id_b)
+		return 1;
+	return 0;
+}
+
 void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
 {
 	struct rb_node *node, *prev;
 
 	VFS_WARN_ON_ONCE(!ns->ns_id);
 
-	write_seqlock(&ns_tree->ns_tree_lock);
-
-	VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
+	write_seqlock(&ns_tree_lock);
 
 	node = rb_find_add_rcu(&ns->ns_tree_node, &ns_tree->ns_tree, ns_cmp);
 	/*
@@ -119,7 +149,8 @@ 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);
 
-	write_sequnlock(&ns_tree->ns_tree_lock);
+	rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unified);
+	write_sequnlock(&ns_tree_lock);
 
 	VFS_WARN_ON_ONCE(node);
 
@@ -138,11 +169,12 @@ void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
 	VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node));
 	VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
 
-	write_seqlock(&ns_tree->ns_tree_lock);
+	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);
 	list_bidir_del_rcu(&ns->ns_list_node);
 	RB_CLEAR_NODE(&ns->ns_tree_node);
-	write_sequnlock(&ns_tree->ns_tree_lock);
+	write_sequnlock(&ns_tree_lock);
 }
 EXPORT_SYMBOL_GPL(__ns_tree_remove);
 
@@ -158,6 +190,17 @@ static int ns_find(const void *key, const struct rb_node *node)
 	return 0;
 }
 
+static int ns_find_unified(const void *key, const struct rb_node *node)
+{
+	const u64 ns_id = *(u64 *)key;
+	const struct ns_common *ns = node_to_ns_unified(node);
+
+	if (ns_id < ns->ns_id)
+		return -1;
+	if (ns_id > ns->ns_id)
+		return 1;
+	return 0;
+}
 
 static struct ns_tree *ns_tree_from_type(int ns_type)
 {
@@ -183,28 +226,51 @@ static struct ns_tree *ns_tree_from_type(int ns_type)
 	return NULL;
 }
 
-struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type)
+static struct ns_common *__ns_unified_tree_lookup_rcu(u64 ns_id)
 {
-	struct ns_tree *ns_tree;
 	struct rb_node *node;
 	unsigned int seq;
 
-	RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_lookup_rcu() usage");
+	do {
+		seq = read_seqbegin(&ns_tree_lock);
+		node = rb_find_rcu(&ns_id, &ns_unified_tree, ns_find_unified);
+		if (node)
+			break;
+	} while (read_seqretry(&ns_tree_lock, seq));
+
+	return node_to_ns_unified(node);
+}
+
+static struct ns_common *__ns_tree_lookup_rcu(u64 ns_id, int ns_type)
+{
+	struct ns_tree *ns_tree;
+	struct rb_node *node;
+	unsigned int seq;
 
 	ns_tree = ns_tree_from_type(ns_type);
 	if (!ns_tree)
 		return NULL;
 
 	do {
-		seq = read_seqbegin(&ns_tree->ns_tree_lock);
+		seq = read_seqbegin(&ns_tree_lock);
 		node = rb_find_rcu(&ns_id, &ns_tree->ns_tree, ns_find);
 		if (node)
 			break;
-	} while (read_seqretry(&ns_tree->ns_tree_lock, seq));
+	} while (read_seqretry(&ns_tree_lock, seq));
 
 	return node_to_ns(node);
 }
 
+struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type)
+{
+	RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_lookup_rcu() usage");
+
+	if (ns_type)
+		return __ns_tree_lookup_rcu(ns_id, ns_type);
+
+	return __ns_unified_tree_lookup_rcu(ns_id);
+}
+
 /**
  * ns_tree_adjoined_rcu - find the next/previous namespace in the same
  * tree

-- 
2.47.3
Re: [PATCH v4 13/72] nstree: introduce a unified tree
Posted by kernel test robot 3 months, 1 week ago
Hi Christian,

kernel test robot noticed the following build errors:

[auto build test ERROR on 3a8660878839faadb4f1a6dd72c3179c1df56787]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Brauner/libfs-allow-to-specify-s_d_flags/20251029-205841
base:   3a8660878839faadb4f1a6dd72c3179c1df56787
patch link:    https://lore.kernel.org/r/20251029-work-namespace-nstree-listns-v4-13-2e6f823ebdc0%40kernel.org
patch subject: [PATCH v4 13/72] nstree: introduce a unified tree
config: m68k-allnoconfig (https://download.01.org/0day-ci/archive/20251029/202510292238.OTyD5CXw-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251029/202510292238.OTyD5CXw-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510292238.OTyD5CXw-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/init.h:5,
                    from include/linux/printk.h:6,
                    from include/asm-generic/bug.h:22,
                    from arch/m68k/include/asm/bug.h:32,
                    from include/linux/bug.h:5,
                    from include/linux/thread_info.h:13,
                    from include/asm-generic/preempt.h:5,
                    from ./arch/m68k/include/generated/asm/preempt.h:1,
                    from include/linux/preempt.h:79,
                    from arch/m68k/include/asm/irqflags.h:6,
                    from include/linux/irqflags.h:18,
                    from arch/m68k/include/asm/atomic.h:6,
                    from include/linux/atomic.h:7,
                    from include/linux/refcount.h:104,
                    from include/linux/ns_common.h:5,
                    from include/linux/nstree.h:5,
                    from kernel/nstree.c:3:
   kernel/nstree.c: In function '__ns_tree_remove':
>> kernel/nstree.c:170:48: error: 'struct ns_tree' has no member named 'type'
     170 |         VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
         |                                                ^~
   include/linux/build_bug.h:30:63: note: in definition of macro 'BUILD_BUG_ON_INVALID'
      30 | #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
         |                                                               ^
   kernel/nstree.c:170:9: note: in expansion of macro 'VFS_WARN_ON_ONCE'
     170 |         VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
         |         ^~~~~~~~~~~~~~~~
   kernel/nstree.c: In function '__ns_tree_adjoined_rcu':
   kernel/nstree.c:297:98: error: 'struct ns_tree' has no member named 'type'
     297 |         VFS_WARN_ON_ONCE(list_entry_rcu(list, struct ns_common, ns_list_node)->ns_type != ns_tree->type);
         |                                                                                                  ^~
   include/linux/build_bug.h:30:63: note: in definition of macro 'BUILD_BUG_ON_INVALID'
      30 | #define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
         |                                                               ^
   kernel/nstree.c:297:9: note: in expansion of macro 'VFS_WARN_ON_ONCE'
     297 |         VFS_WARN_ON_ONCE(list_entry_rcu(list, struct ns_common, ns_list_node)->ns_type != ns_tree->type);
         |         ^~~~~~~~~~~~~~~~


vim +170 kernel/nstree.c

885fc8ac0a4dc7 Christian Brauner 2025-09-12    2  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   @3  #include <linux/nstree.h>
885fc8ac0a4dc7 Christian Brauner 2025-09-12    4  #include <linux/proc_ns.h>
885fc8ac0a4dc7 Christian Brauner 2025-09-12    5  #include <linux/vfsdebug.h>
885fc8ac0a4dc7 Christian Brauner 2025-09-12    6  
01da9c6ec4269b Christian Brauner 2025-10-29    7  __cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock);
01da9c6ec4269b Christian Brauner 2025-10-29    8  static struct rb_root ns_unified_tree = RB_ROOT; /* protected by ns_tree_lock */
01da9c6ec4269b Christian Brauner 2025-10-29    9  
10cdfcd37ade7c Christian Brauner 2025-09-24   10  /**
10cdfcd37ade7c Christian Brauner 2025-09-24   11   * struct ns_tree - Namespace tree
10cdfcd37ade7c Christian Brauner 2025-09-24   12   * @ns_tree: Rbtree of namespaces of a particular type
10cdfcd37ade7c Christian Brauner 2025-09-24   13   * @ns_list: Sequentially walkable list of all namespaces of this type
10cdfcd37ade7c Christian Brauner 2025-09-24   14   * @type: type of namespaces in this tree
10cdfcd37ade7c Christian Brauner 2025-09-24   15   */
10cdfcd37ade7c Christian Brauner 2025-09-24   16  struct ns_tree {
10cdfcd37ade7c Christian Brauner 2025-09-24   17  	struct rb_root ns_tree;
10cdfcd37ade7c Christian Brauner 2025-09-24   18  	struct list_head ns_list;
01da9c6ec4269b Christian Brauner 2025-10-29   19  #ifdef CONFIG_DEBUG_VFS
10cdfcd37ade7c Christian Brauner 2025-09-24   20  	int type;
01da9c6ec4269b Christian Brauner 2025-10-29   21  #endif
10cdfcd37ade7c Christian Brauner 2025-09-24   22  };
10cdfcd37ade7c Christian Brauner 2025-09-24   23  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   24  struct ns_tree mnt_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   25  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   26  	.ns_list = LIST_HEAD_INIT(mnt_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   27  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   28  	.type = CLONE_NEWNS,
01da9c6ec4269b Christian Brauner 2025-10-29   29  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   30  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   31  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   32  struct ns_tree net_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   33  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   34  	.ns_list = LIST_HEAD_INIT(net_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   35  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   36  	.type = CLONE_NEWNET,
01da9c6ec4269b Christian Brauner 2025-10-29   37  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   38  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   39  EXPORT_SYMBOL_GPL(net_ns_tree);
885fc8ac0a4dc7 Christian Brauner 2025-09-12   40  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   41  struct ns_tree uts_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   42  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   43  	.ns_list = LIST_HEAD_INIT(uts_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   44  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   45  	.type = CLONE_NEWUTS,
01da9c6ec4269b Christian Brauner 2025-10-29   46  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   47  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   48  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   49  struct ns_tree user_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   50  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   51  	.ns_list = LIST_HEAD_INIT(user_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   52  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   53  	.type = CLONE_NEWUSER,
01da9c6ec4269b Christian Brauner 2025-10-29   54  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   55  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   56  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   57  struct ns_tree ipc_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   58  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   59  	.ns_list = LIST_HEAD_INIT(ipc_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   60  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   61  	.type = CLONE_NEWIPC,
01da9c6ec4269b Christian Brauner 2025-10-29   62  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   63  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   64  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   65  struct ns_tree pid_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   66  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   67  	.ns_list = LIST_HEAD_INIT(pid_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   68  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   69  	.type = CLONE_NEWPID,
01da9c6ec4269b Christian Brauner 2025-10-29   70  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   71  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   72  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   73  struct ns_tree cgroup_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   74  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   75  	.ns_list = LIST_HEAD_INIT(cgroup_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   76  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   77  	.type = CLONE_NEWCGROUP,
01da9c6ec4269b Christian Brauner 2025-10-29   78  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   79  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   80  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   81  struct ns_tree time_ns_tree = {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   82  	.ns_tree = RB_ROOT,
885fc8ac0a4dc7 Christian Brauner 2025-09-12   83  	.ns_list = LIST_HEAD_INIT(time_ns_tree.ns_list),
01da9c6ec4269b Christian Brauner 2025-10-29   84  #ifdef CONFIG_DEBUG_VFS
885fc8ac0a4dc7 Christian Brauner 2025-09-12   85  	.type = CLONE_NEWTIME,
01da9c6ec4269b Christian Brauner 2025-10-29   86  #endif
885fc8ac0a4dc7 Christian Brauner 2025-09-12   87  };
885fc8ac0a4dc7 Christian Brauner 2025-09-12   88  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   89  DEFINE_COOKIE(namespace_cookie);
885fc8ac0a4dc7 Christian Brauner 2025-09-12   90  
885fc8ac0a4dc7 Christian Brauner 2025-09-12   91  static inline struct ns_common *node_to_ns(const struct rb_node *node)
885fc8ac0a4dc7 Christian Brauner 2025-09-12   92  {
885fc8ac0a4dc7 Christian Brauner 2025-09-12   93  	if (!node)
885fc8ac0a4dc7 Christian Brauner 2025-09-12   94  		return NULL;
885fc8ac0a4dc7 Christian Brauner 2025-09-12   95  	return rb_entry(node, struct ns_common, ns_tree_node);
885fc8ac0a4dc7 Christian Brauner 2025-09-12   96  }
885fc8ac0a4dc7 Christian Brauner 2025-09-12   97  
01da9c6ec4269b Christian Brauner 2025-10-29   98  static inline struct ns_common *node_to_ns_unified(const struct rb_node *node)
01da9c6ec4269b Christian Brauner 2025-10-29   99  {
01da9c6ec4269b Christian Brauner 2025-10-29  100  	if (!node)
01da9c6ec4269b Christian Brauner 2025-10-29  101  		return NULL;
01da9c6ec4269b Christian Brauner 2025-10-29  102  	return rb_entry(node, struct ns_common, ns_unified_tree_node);
01da9c6ec4269b Christian Brauner 2025-10-29  103  }
01da9c6ec4269b Christian Brauner 2025-10-29  104  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  105  static inline int ns_cmp(struct rb_node *a, const struct rb_node *b)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  106  {
885fc8ac0a4dc7 Christian Brauner 2025-09-12  107  	struct ns_common *ns_a = node_to_ns(a);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  108  	struct ns_common *ns_b = node_to_ns(b);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  109  	u64 ns_id_a = ns_a->ns_id;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  110  	u64 ns_id_b = ns_b->ns_id;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  111  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  112  	if (ns_id_a < ns_id_b)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  113  		return -1;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  114  	if (ns_id_a > ns_id_b)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  115  		return 1;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  116  	return 0;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  117  }
885fc8ac0a4dc7 Christian Brauner 2025-09-12  118  
01da9c6ec4269b Christian Brauner 2025-10-29  119  static inline int ns_cmp_unified(struct rb_node *a, const struct rb_node *b)
01da9c6ec4269b Christian Brauner 2025-10-29  120  {
01da9c6ec4269b Christian Brauner 2025-10-29  121  	struct ns_common *ns_a = node_to_ns_unified(a);
01da9c6ec4269b Christian Brauner 2025-10-29  122  	struct ns_common *ns_b = node_to_ns_unified(b);
01da9c6ec4269b Christian Brauner 2025-10-29  123  	u64 ns_id_a = ns_a->ns_id;
01da9c6ec4269b Christian Brauner 2025-10-29  124  	u64 ns_id_b = ns_b->ns_id;
01da9c6ec4269b Christian Brauner 2025-10-29  125  
01da9c6ec4269b Christian Brauner 2025-10-29  126  	if (ns_id_a < ns_id_b)
01da9c6ec4269b Christian Brauner 2025-10-29  127  		return -1;
01da9c6ec4269b Christian Brauner 2025-10-29  128  	if (ns_id_a > ns_id_b)
01da9c6ec4269b Christian Brauner 2025-10-29  129  		return 1;
01da9c6ec4269b Christian Brauner 2025-10-29  130  	return 0;
01da9c6ec4269b Christian Brauner 2025-10-29  131  }
01da9c6ec4269b Christian Brauner 2025-10-29  132  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  133  void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  134  {
885fc8ac0a4dc7 Christian Brauner 2025-09-12  135  	struct rb_node *node, *prev;
885fc8ac0a4dc7 Christian Brauner 2025-09-12  136  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  137  	VFS_WARN_ON_ONCE(!ns->ns_id);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  138  
01da9c6ec4269b Christian Brauner 2025-10-29  139  	write_seqlock(&ns_tree_lock);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  140  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  141  	node = rb_find_add_rcu(&ns->ns_tree_node, &ns_tree->ns_tree, ns_cmp);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  142  	/*
885fc8ac0a4dc7 Christian Brauner 2025-09-12  143  	 * If there's no previous entry simply add it after the
885fc8ac0a4dc7 Christian Brauner 2025-09-12  144  	 * head and if there is add it after the previous entry.
885fc8ac0a4dc7 Christian Brauner 2025-09-12  145  	 */
885fc8ac0a4dc7 Christian Brauner 2025-09-12  146  	prev = rb_prev(&ns->ns_tree_node);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  147  	if (!prev)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  148  		list_add_rcu(&ns->ns_list_node, &ns_tree->ns_list);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  149  	else
885fc8ac0a4dc7 Christian Brauner 2025-09-12  150  		list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  151  
01da9c6ec4269b Christian Brauner 2025-10-29  152  	rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unified);
01da9c6ec4269b Christian Brauner 2025-10-29  153  	write_sequnlock(&ns_tree_lock);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  154  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  155  	VFS_WARN_ON_ONCE(node);
cb9044bf715ece Christian Brauner 2025-10-29  156  
cb9044bf715ece Christian Brauner 2025-10-29  157  	/*
cb9044bf715ece Christian Brauner 2025-10-29  158  	 * Take an active reference on the owner namespace. This ensures
cb9044bf715ece Christian Brauner 2025-10-29  159  	 * that the owner remains visible while any of its child namespaces
cb9044bf715ece Christian Brauner 2025-10-29  160  	 * are active. For init namespaces this is a no-op as ns_owner()
cb9044bf715ece Christian Brauner 2025-10-29  161  	 * returns NULL for namespaces owned by init_user_ns.
cb9044bf715ece Christian Brauner 2025-10-29  162  	 */
cb9044bf715ece Christian Brauner 2025-10-29  163  	__ns_ref_active_get_owner(ns);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  164  }
885fc8ac0a4dc7 Christian Brauner 2025-09-12  165  
885fc8ac0a4dc7 Christian Brauner 2025-09-12  166  void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
885fc8ac0a4dc7 Christian Brauner 2025-09-12  167  {
885fc8ac0a4dc7 Christian Brauner 2025-09-12  168  	VFS_WARN_ON_ONCE(RB_EMPTY_NODE(&ns->ns_tree_node));
885fc8ac0a4dc7 Christian Brauner 2025-09-12  169  	VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node));
4055526d35746c Christian Brauner 2025-09-24 @170  	VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  171  
01da9c6ec4269b Christian Brauner 2025-10-29  172  	write_seqlock(&ns_tree_lock);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  173  	rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree);
01da9c6ec4269b Christian Brauner 2025-10-29  174  	rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  175  	list_bidir_del_rcu(&ns->ns_list_node);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  176  	RB_CLEAR_NODE(&ns->ns_tree_node);
01da9c6ec4269b Christian Brauner 2025-10-29  177  	write_sequnlock(&ns_tree_lock);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  178  }
885fc8ac0a4dc7 Christian Brauner 2025-09-12  179  EXPORT_SYMBOL_GPL(__ns_tree_remove);
885fc8ac0a4dc7 Christian Brauner 2025-09-12  180  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v4 13/72] nstree: introduce a unified tree
Posted by kernel test robot 3 months, 1 week ago
Hi Christian,

kernel test robot noticed the following build errors:

[auto build test ERROR on 3a8660878839faadb4f1a6dd72c3179c1df56787]

url:    https://github.com/intel-lab-lkp/linux/commits/Christian-Brauner/libfs-allow-to-specify-s_d_flags/20251029-205841
base:   3a8660878839faadb4f1a6dd72c3179c1df56787
patch link:    https://lore.kernel.org/r/20251029-work-namespace-nstree-listns-v4-13-2e6f823ebdc0%40kernel.org
patch subject: [PATCH v4 13/72] nstree: introduce a unified tree
config: loongarch-allnoconfig (https://download.01.org/0day-ci/archive/20251029/202510292247.swX8RW4u-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project d1c086e82af239b245fe8d7832f2753436634990)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251029/202510292247.swX8RW4u-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510292247.swX8RW4u-lkp@intel.com/

All errors (new ones prefixed by >>):

>> kernel/nstree.c:170:43: error: no member named 'type' in 'struct ns_tree'
     170 |         VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
         |                                         ~~~~~~~  ^
   kernel/nstree.c:297:93: error: no member named 'type' in 'struct ns_tree'
     297 |         VFS_WARN_ON_ONCE(list_entry_rcu(list, struct ns_common, ns_list_node)->ns_type != ns_tree->type);
         |                                                                                           ~~~~~~~  ^
   2 errors generated.


vim +170 kernel/nstree.c

885fc8ac0a4dc70 Christian Brauner 2025-09-12  165  
885fc8ac0a4dc70 Christian Brauner 2025-09-12  166  void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
885fc8ac0a4dc70 Christian Brauner 2025-09-12  167  {
885fc8ac0a4dc70 Christian Brauner 2025-09-12  168  	VFS_WARN_ON_ONCE(RB_EMPTY_NODE(&ns->ns_tree_node));
885fc8ac0a4dc70 Christian Brauner 2025-09-12  169  	VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node));
4055526d35746ce Christian Brauner 2025-09-24 @170  	VFS_WARN_ON_ONCE(ns->ns_type != ns_tree->type);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  171  
01da9c6ec4269ba Christian Brauner 2025-10-29  172  	write_seqlock(&ns_tree_lock);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  173  	rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree);
01da9c6ec4269ba Christian Brauner 2025-10-29  174  	rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  175  	list_bidir_del_rcu(&ns->ns_list_node);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  176  	RB_CLEAR_NODE(&ns->ns_tree_node);
01da9c6ec4269ba Christian Brauner 2025-10-29  177  	write_sequnlock(&ns_tree_lock);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  178  }
885fc8ac0a4dc70 Christian Brauner 2025-09-12  179  EXPORT_SYMBOL_GPL(__ns_tree_remove);
885fc8ac0a4dc70 Christian Brauner 2025-09-12  180  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki