File Index
Files and directories
Sign in
FILE

ns_common.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/ns_common.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _LINUX_NS_COMMON_H
  3#define _LINUX_NS_COMMON_H
  4
  5#include <linux/ns/ns_common_types.h>
  6#include <linux/refcount.h>
  7#include <linux/vfsdebug.h>
  8#include <uapi/linux/sched.h>
  9#include <uapi/linux/nsfs.h>
 10
 11bool is_current_namespace(struct ns_common *ns);
 12int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_ns_operations *ops, int inum);
 13void __ns_common_free(struct ns_common *ns);
 14struct ns_common *__must_check ns_owner(struct ns_common *ns);
 15
 16static __always_inline bool is_ns_init_inum(const struct ns_common *ns)
 17{
 18	VFS_WARN_ON_ONCE(ns->inum == 0);
 19	return unlikely(in_range(ns->inum, MNT_NS_INIT_INO,
 20				 IPC_NS_INIT_INO - MNT_NS_INIT_INO + 1));
 21}
 22
 23static __always_inline bool is_ns_init_id(const struct ns_common *ns)
 24{
 25	VFS_WARN_ON_ONCE(ns->ns_id == 0);
 26	return ns->ns_id <= NS_LAST_INIT_ID;
 27}
 28
 29#define NS_COMMON_INIT(nsname)										\
 30{													\
 31	.ns_type			= ns_common_type(&nsname),					\
 32	.ns_id				= ns_init_id(&nsname),						\
 33	.inum				= ns_init_inum(&nsname),					\
 34	.ops				= to_ns_operations(&nsname),					\
 35	.stashed			= NULL,								\
 36	.__ns_ref			= REFCOUNT_INIT(1),						\
 37	.__ns_ref_active		= ATOMIC_INIT(1),						\
 38	.ns_unified_node.ns_list_entry	= LIST_HEAD_INIT(nsname.ns.ns_unified_node.ns_list_entry),	\
 39	.ns_tree_node.ns_list_entry	= LIST_HEAD_INIT(nsname.ns.ns_tree_node.ns_list_entry),		\
 40	.ns_owner_node.ns_list_entry	= LIST_HEAD_INIT(nsname.ns.ns_owner_node.ns_list_entry),	\
 41	.ns_owner_root.ns_list_head	= LIST_HEAD_INIT(nsname.ns.ns_owner_root.ns_list_head),		\
 42}
 43
 44#define ns_common_init(__ns)                     \
 45	__ns_common_init(to_ns_common(__ns),     \
 46			 ns_common_type(__ns),   \
 47			 to_ns_operations(__ns), \
 48			 (((__ns) == ns_init_ns(__ns)) ? ns_init_inum(__ns) : 0))
 49
 50#define ns_common_init_inum(__ns, __inum)        \
 51	__ns_common_init(to_ns_common(__ns),     \
 52			 ns_common_type(__ns),   \
 53			 to_ns_operations(__ns), \
 54			 __inum)
 55
 56#define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns)))
 57
 58bool may_see_all_namespaces(void);
 59
 60static __always_inline __must_check int __ns_ref_active_read(const struct ns_common *ns)
 61{
 62	return atomic_read(&ns->__ns_ref_active);
 63}
 64
 65static __always_inline __must_check int __ns_ref_read(const struct ns_common *ns)
 66{
 67	return refcount_read(&ns->__ns_ref);
 68}
 69
 70static __always_inline __must_check bool __ns_ref_put(struct ns_common *ns)
 71{
 72	if (is_ns_init_id(ns)) {
 73		VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
 74		VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
 75		return false;
 76	}
 77	if (refcount_dec_and_test(&ns->__ns_ref)) {
 78		VFS_WARN_ON_ONCE(__ns_ref_active_read(ns));
 79		return true;
 80	}
 81	return false;
 82}
 83
 84static __always_inline __must_check bool __ns_ref_get(struct ns_common *ns)
 85{
 86	if (is_ns_init_id(ns)) {
 87		VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
 88		VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
 89		return true;
 90	}
 91	if (refcount_inc_not_zero(&ns->__ns_ref))
 92		return true;
 93	VFS_WARN_ON_ONCE(__ns_ref_active_read(ns));
 94	return false;
 95}
 96
 97static __always_inline void __ns_ref_inc(struct ns_common *ns)
 98{
 99	if (is_ns_init_id(ns)) {
100		VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
101		VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
102		return;
103	}
104	refcount_inc(&ns->__ns_ref);
105}
106
107static __always_inline __must_check bool __ns_ref_dec_and_lock(struct ns_common *ns,
108							       spinlock_t *ns_lock)
109{
110	if (is_ns_init_id(ns)) {
111		VFS_WARN_ON_ONCE(__ns_ref_read(ns) != 1);
112		VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) != 1);
113		return false;
114	}
115	return refcount_dec_and_lock(&ns->__ns_ref, ns_lock);
116}
117
118#define ns_ref_read(__ns) __ns_ref_read(to_ns_common((__ns)))
119#define ns_ref_inc(__ns) \
120	do { if (__ns) __ns_ref_inc(to_ns_common((__ns))); } while (0)
121#define ns_ref_get(__ns) \
122	((__ns) ? __ns_ref_get(to_ns_common((__ns))) : false)
123#define ns_ref_put(__ns) \
124	((__ns) ? __ns_ref_put(to_ns_common((__ns))) : false)
125#define ns_ref_put_and_lock(__ns, __ns_lock) \
126	((__ns) ? __ns_ref_dec_and_lock(to_ns_common((__ns)), __ns_lock) : false)
127
128#define ns_ref_active_read(__ns) \
129	((__ns) ? __ns_ref_active_read(to_ns_common(__ns)) : 0)
130
131void __ns_ref_active_put(struct ns_common *ns);
132
133#define ns_ref_active_put(__ns) \
134	do { if (__ns) __ns_ref_active_put(to_ns_common(__ns)); } while (0)
135
136static __always_inline struct ns_common *__must_check ns_get_unless_inactive(struct ns_common *ns)
137{
138	if (!__ns_ref_active_read(ns)) {
139		VFS_WARN_ON_ONCE(is_ns_init_id(ns));
140		return NULL;
141	}
142	if (!__ns_ref_get(ns))
143		return NULL;
144	return ns;
145}
146
147void __ns_ref_active_get(struct ns_common *ns);
148
149#define ns_ref_active_get(__ns) \
150	do { if (__ns) __ns_ref_active_get(to_ns_common(__ns)); } while (0)
151
152#endif
~/ Read-only file preview.