xref: /linux-6.15/include/linux/kernfs.h (revision e756bc56)
1 /*
2  * kernfs.h - pseudo filesystem decoupled from vfs locking
3  *
4  * This file is released under the GPLv2.
5  */
6 
7 #ifndef __LINUX_KERNFS_H
8 #define __LINUX_KERNFS_H
9 
10 #include <linux/kernel.h>
11 #include <linux/err.h>
12 #include <linux/list.h>
13 #include <linux/mutex.h>
14 #include <linux/idr.h>
15 #include <linux/lockdep.h>
16 #include <linux/rbtree.h>
17 #include <linux/atomic.h>
18 #include <linux/completion.h>
19 
20 struct file;
21 struct iattr;
22 struct seq_file;
23 struct vm_area_struct;
24 struct super_block;
25 struct file_system_type;
26 
27 struct sysfs_open_dirent;
28 struct sysfs_inode_attrs;
29 
30 enum kernfs_node_type {
31 	SYSFS_DIR		= 0x0001,
32 	SYSFS_KOBJ_ATTR		= 0x0002,
33 	SYSFS_KOBJ_LINK		= 0x0004,
34 };
35 
36 #define SYSFS_TYPE_MASK		0x000f
37 #define SYSFS_COPY_NAME		(SYSFS_DIR | SYSFS_KOBJ_LINK)
38 #define SYSFS_ACTIVE_REF	SYSFS_KOBJ_ATTR
39 #define SYSFS_FLAG_MASK		~SYSFS_TYPE_MASK
40 
41 enum kernfs_node_flag {
42 	SYSFS_FLAG_REMOVED	= 0x0010,
43 	SYSFS_FLAG_NS		= 0x0020,
44 	SYSFS_FLAG_HAS_SEQ_SHOW	= 0x0040,
45 	SYSFS_FLAG_HAS_MMAP	= 0x0080,
46 	SYSFS_FLAG_LOCKDEP	= 0x0100,
47 };
48 
49 /* type-specific structures for sysfs_dirent->s_* union members */
50 struct sysfs_elem_dir {
51 	unsigned long		subdirs;
52 	/* children rbtree starts here and goes through sd->s_rb */
53 	struct rb_root		children;
54 
55 	/*
56 	 * The kernfs hierarchy this directory belongs to.  This fits
57 	 * better directly in sysfs_dirent but is here to save space.
58 	 */
59 	struct kernfs_root	*root;
60 };
61 
62 struct sysfs_elem_symlink {
63 	struct sysfs_dirent	*target_sd;
64 };
65 
66 struct sysfs_elem_attr {
67 	const struct kernfs_ops	*ops;
68 	struct sysfs_open_dirent *open;
69 	loff_t			size;
70 };
71 
72 /*
73  * sysfs_dirent - the building block of sysfs hierarchy.  Each and every
74  * sysfs node is represented by single sysfs_dirent.  Most fields are
75  * private to kernfs and shouldn't be accessed directly by kernfs users.
76  *
77  * As long as s_count reference is held, the sysfs_dirent itself is
78  * accessible.  Dereferencing s_elem or any other outer entity
79  * requires s_active reference.
80  */
81 struct sysfs_dirent {
82 	atomic_t		s_count;
83 	atomic_t		s_active;
84 #ifdef CONFIG_DEBUG_LOCK_ALLOC
85 	struct lockdep_map	dep_map;
86 #endif
87 	/* the following two fields are published */
88 	struct sysfs_dirent	*s_parent;
89 	const char		*s_name;
90 
91 	struct rb_node		s_rb;
92 
93 	union {
94 		struct completion	*completion;
95 		struct sysfs_dirent	*removed_list;
96 	} u;
97 
98 	const void		*s_ns; /* namespace tag */
99 	unsigned int		s_hash; /* ns + name hash */
100 	union {
101 		struct sysfs_elem_dir		s_dir;
102 		struct sysfs_elem_symlink	s_symlink;
103 		struct sysfs_elem_attr		s_attr;
104 	};
105 
106 	void			*priv;
107 
108 	unsigned short		s_flags;
109 	umode_t			s_mode;
110 	unsigned int		s_ino;
111 	struct sysfs_inode_attrs *s_iattr;
112 };
113 
114 struct kernfs_root {
115 	/* published fields */
116 	struct sysfs_dirent	*sd;
117 
118 	/* private fields, do not use outside kernfs proper */
119 	struct ida		ino_ida;
120 };
121 
122 struct sysfs_open_file {
123 	/* published fields */
124 	struct sysfs_dirent	*sd;
125 	struct file		*file;
126 
127 	/* private fields, do not use outside kernfs proper */
128 	struct mutex		mutex;
129 	int			event;
130 	struct list_head	list;
131 
132 	bool			mmapped;
133 	const struct vm_operations_struct *vm_ops;
134 };
135 
136 struct kernfs_ops {
137 	/*
138 	 * Read is handled by either seq_file or raw_read().
139 	 *
140 	 * If seq_show() is present, seq_file path is active.  Other seq
141 	 * operations are optional and if not implemented, the behavior is
142 	 * equivalent to single_open().  @sf->private points to the
143 	 * associated sysfs_open_file.
144 	 *
145 	 * read() is bounced through kernel buffer and a read larger than
146 	 * PAGE_SIZE results in partial operation of PAGE_SIZE.
147 	 */
148 	int (*seq_show)(struct seq_file *sf, void *v);
149 
150 	void *(*seq_start)(struct seq_file *sf, loff_t *ppos);
151 	void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos);
152 	void (*seq_stop)(struct seq_file *sf, void *v);
153 
154 	ssize_t (*read)(struct sysfs_open_file *of, char *buf, size_t bytes,
155 			loff_t off);
156 
157 	/*
158 	 * write() is bounced through kernel buffer and a write larger than
159 	 * PAGE_SIZE results in partial operation of PAGE_SIZE.
160 	 */
161 	ssize_t (*write)(struct sysfs_open_file *of, char *buf, size_t bytes,
162 			 loff_t off);
163 
164 	int (*mmap)(struct sysfs_open_file *of, struct vm_area_struct *vma);
165 
166 #ifdef CONFIG_DEBUG_LOCK_ALLOC
167 	struct lock_class_key	lockdep_key;
168 #endif
169 };
170 
171 #ifdef CONFIG_SYSFS
172 
173 static inline enum kernfs_node_type sysfs_type(struct sysfs_dirent *sd)
174 {
175 	return sd->s_flags & SYSFS_TYPE_MASK;
176 }
177 
178 /**
179  * kernfs_enable_ns - enable namespace under a directory
180  * @sd: directory of interest, should be empty
181  *
182  * This is to be called right after @sd is created to enable namespace
183  * under it.  All children of @sd must have non-NULL namespace tags and
184  * only the ones which match the super_block's tag will be visible.
185  */
186 static inline void kernfs_enable_ns(struct sysfs_dirent *sd)
187 {
188 	WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR);
189 	WARN_ON_ONCE(!RB_EMPTY_ROOT(&sd->s_dir.children));
190 	sd->s_flags |= SYSFS_FLAG_NS;
191 }
192 
193 /**
194  * kernfs_ns_enabled - test whether namespace is enabled
195  * @sd: the node to test
196  *
197  * Test whether namespace filtering is enabled for the children of @ns.
198  */
199 static inline bool kernfs_ns_enabled(struct sysfs_dirent *sd)
200 {
201 	return sd->s_flags & SYSFS_FLAG_NS;
202 }
203 
204 struct sysfs_dirent *kernfs_find_and_get_ns(struct sysfs_dirent *parent,
205 					    const char *name, const void *ns);
206 void kernfs_get(struct sysfs_dirent *sd);
207 void kernfs_put(struct sysfs_dirent *sd);
208 
209 struct kernfs_root *kernfs_create_root(void *priv);
210 void kernfs_destroy_root(struct kernfs_root *root);
211 
212 struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
213 					  const char *name, void *priv,
214 					  const void *ns);
215 struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
216 					       const char *name,
217 					       umode_t mode, loff_t size,
218 					       const struct kernfs_ops *ops,
219 					       void *priv, const void *ns,
220 					       struct lock_class_key *key);
221 struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
222 					const char *name,
223 					struct sysfs_dirent *target);
224 void kernfs_remove(struct sysfs_dirent *sd);
225 int kernfs_remove_by_name_ns(struct sysfs_dirent *parent, const char *name,
226 			     const void *ns);
227 int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
228 		     const char *new_name, const void *new_ns);
229 int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr);
230 void kernfs_notify(struct sysfs_dirent *sd);
231 
232 const void *kernfs_super_ns(struct super_block *sb);
233 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
234 			       struct kernfs_root *root, const void *ns);
235 void kernfs_kill_sb(struct super_block *sb);
236 
237 void kernfs_init(void);
238 
239 #else	/* CONFIG_SYSFS */
240 
241 static inline enum kernfs_node_type sysfs_type(struct sysfs_dirent *sd)
242 { return 0; }	/* whatever */
243 
244 static inline void kernfs_enable_ns(struct sysfs_dirent *sd) { }
245 
246 static inline bool kernfs_ns_enabled(struct sysfs_dirent *sd)
247 { return false; }
248 
249 static inline struct sysfs_dirent *
250 kernfs_find_and_get_ns(struct sysfs_dirent *parent, const char *name,
251 		       const void *ns)
252 { return NULL; }
253 
254 static inline void kernfs_get(struct sysfs_dirent *sd) { }
255 static inline void kernfs_put(struct sysfs_dirent *sd) { }
256 
257 static inline struct kernfs_root *kernfs_create_root(void *priv)
258 { return ERR_PTR(-ENOSYS); }
259 
260 static inline void kernfs_destroy_root(struct kernfs_root *root) { }
261 
262 static inline struct sysfs_dirent *
263 kernfs_create_dir_ns(struct sysfs_dirent *parent, const char *name, void *priv,
264 		     const void *ns)
265 { return ERR_PTR(-ENOSYS); }
266 
267 static inline struct sysfs_dirent *
268 kernfs_create_file_ns_key(struct sysfs_dirent *parent, const char *name,
269 			  umode_t mode, loff_t size,
270 			  const struct kernfs_ops *ops, void *priv,
271 			  const void *ns, struct lock_class_key *key)
272 { return ERR_PTR(-ENOSYS); }
273 
274 static inline struct sysfs_dirent *
275 kernfs_create_link(struct sysfs_dirent *parent, const char *name,
276 		   struct sysfs_dirent *target)
277 { return ERR_PTR(-ENOSYS); }
278 
279 static inline void kernfs_remove(struct sysfs_dirent *sd) { }
280 
281 static inline int kernfs_remove_by_name_ns(struct sysfs_dirent *parent,
282 					   const char *name, const void *ns)
283 { return -ENOSYS; }
284 
285 static inline int kernfs_rename_ns(struct sysfs_dirent *sd,
286 				   struct sysfs_dirent *new_parent,
287 				   const char *new_name, const void *new_ns)
288 { return -ENOSYS; }
289 
290 static inline int kernfs_setattr(struct sysfs_dirent *sd,
291 				 const struct iattr *iattr)
292 { return -ENOSYS; }
293 
294 static inline void kernfs_notify(struct sysfs_dirent *sd) { }
295 
296 static inline const void *kernfs_super_ns(struct super_block *sb)
297 { return NULL; }
298 
299 static inline struct dentry *
300 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
301 		struct kernfs_root *root, const void *ns)
302 { return ERR_PTR(-ENOSYS); }
303 
304 static inline void kernfs_kill_sb(struct super_block *sb) { }
305 
306 static inline void kernfs_init(void) { }
307 
308 #endif	/* CONFIG_SYSFS */
309 
310 static inline struct sysfs_dirent *
311 kernfs_find_and_get(struct sysfs_dirent *sd, const char *name)
312 {
313 	return kernfs_find_and_get_ns(sd, name, NULL);
314 }
315 
316 static inline struct sysfs_dirent *
317 kernfs_create_dir(struct sysfs_dirent *parent, const char *name, void *priv)
318 {
319 	return kernfs_create_dir_ns(parent, name, priv, NULL);
320 }
321 
322 static inline struct sysfs_dirent *
323 kernfs_create_file_ns(struct sysfs_dirent *parent, const char *name,
324 		      umode_t mode, loff_t size, const struct kernfs_ops *ops,
325 		      void *priv, const void *ns)
326 {
327 	struct lock_class_key *key = NULL;
328 
329 #ifdef CONFIG_DEBUG_LOCK_ALLOC
330 	key = (struct lock_class_key *)&ops->lockdep_key;
331 #endif
332 	return kernfs_create_file_ns_key(parent, name, mode, size, ops, priv,
333 					 ns, key);
334 }
335 
336 static inline struct sysfs_dirent *
337 kernfs_create_file(struct sysfs_dirent *parent, const char *name, umode_t mode,
338 		   loff_t size, const struct kernfs_ops *ops, void *priv)
339 {
340 	return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL);
341 }
342 
343 static inline int kernfs_remove_by_name(struct sysfs_dirent *parent,
344 					const char *name)
345 {
346 	return kernfs_remove_by_name_ns(parent, name, NULL);
347 }
348 
349 static inline struct dentry *
350 kernfs_mount(struct file_system_type *fs_type, int flags,
351 	     struct kernfs_root *root)
352 {
353 	return kernfs_mount_ns(fs_type, flags, root, NULL);
354 }
355 
356 #endif	/* __LINUX_KERNFS_H */
357