2 * kernfs.h - pseudo filesystem decoupled from vfs locking
4 * This file is released under the GPLv2.
7 #ifndef __LINUX_KERNFS_H
8 #define __LINUX_KERNFS_H
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>
24 struct vm_area_struct
;
26 struct file_system_type
;
28 struct kernfs_open_node
;
31 enum kernfs_node_type
{
37 #define KERNFS_TYPE_MASK 0x000f
38 #define KERNFS_ACTIVE_REF KERNFS_FILE
39 #define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK
41 enum kernfs_node_flag
{
42 KERNFS_REMOVED
= 0x0010,
44 KERNFS_HAS_SEQ_SHOW
= 0x0040,
45 KERNFS_HAS_MMAP
= 0x0080,
46 KERNFS_LOCKDEP
= 0x0100,
47 KERNFS_STATIC_NAME
= 0x0200,
50 /* type-specific structures for kernfs_node union members */
51 struct kernfs_elem_dir
{
52 unsigned long subdirs
;
53 /* children rbtree starts here and goes through kn->rb */
54 struct rb_root children
;
57 * The kernfs hierarchy this directory belongs to. This fits
58 * better directly in kernfs_node but is here to save space.
60 struct kernfs_root
*root
;
63 struct kernfs_elem_symlink
{
64 struct kernfs_node
*target_kn
;
67 struct kernfs_elem_attr
{
68 const struct kernfs_ops
*ops
;
69 struct kernfs_open_node
*open
;
74 * kernfs_node - the building block of kernfs hierarchy. Each and every
75 * kernfs node is represented by single kernfs_node. Most fields are
76 * private to kernfs and shouldn't be accessed directly by kernfs users.
78 * As long as s_count reference is held, the kernfs_node itself is
79 * accessible. Dereferencing elem or any other outer entity requires
85 #ifdef CONFIG_DEBUG_LOCK_ALLOC
86 struct lockdep_map dep_map
;
88 /* the following two fields are published */
89 struct kernfs_node
*parent
;
95 struct completion
*completion
;
96 struct kernfs_node
*removed_list
;
99 const void *ns
; /* namespace tag */
100 unsigned int hash
; /* ns + name hash */
102 struct kernfs_elem_dir dir
;
103 struct kernfs_elem_symlink symlink
;
104 struct kernfs_elem_attr attr
;
109 unsigned short flags
;
112 struct kernfs_iattrs
*iattr
;
116 * kernfs_dir_ops may be specified on kernfs_create_root() to support
117 * directory manipulation syscalls. These optional callbacks are invoked
118 * on the matching syscalls and can perform any kernfs operations which
119 * don't necessarily have to be the exact operation requested.
121 struct kernfs_dir_ops
{
122 int (*mkdir
)(struct kernfs_node
*parent
, const char *name
,
124 int (*rmdir
)(struct kernfs_node
*kn
);
125 int (*rename
)(struct kernfs_node
*kn
, struct kernfs_node
*new_parent
,
126 const char *new_name
);
130 /* published fields */
131 struct kernfs_node
*kn
;
133 /* private fields, do not use outside kernfs proper */
135 struct kernfs_dir_ops
*dir_ops
;
138 struct kernfs_open_file
{
139 /* published fields */
140 struct kernfs_node
*kn
;
143 /* private fields, do not use outside kernfs proper */
146 struct list_head list
;
149 const struct vm_operations_struct
*vm_ops
;
154 * Read is handled by either seq_file or raw_read().
156 * If seq_show() is present, seq_file path is active. Other seq
157 * operations are optional and if not implemented, the behavior is
158 * equivalent to single_open(). @sf->private points to the
159 * associated kernfs_open_file.
161 * read() is bounced through kernel buffer and a read larger than
162 * PAGE_SIZE results in partial operation of PAGE_SIZE.
164 int (*seq_show
)(struct seq_file
*sf
, void *v
);
166 void *(*seq_start
)(struct seq_file
*sf
, loff_t
*ppos
);
167 void *(*seq_next
)(struct seq_file
*sf
, void *v
, loff_t
*ppos
);
168 void (*seq_stop
)(struct seq_file
*sf
, void *v
);
170 ssize_t (*read
)(struct kernfs_open_file
*of
, char *buf
, size_t bytes
,
174 * write() is bounced through kernel buffer and a write larger than
175 * PAGE_SIZE results in partial operation of PAGE_SIZE.
177 ssize_t (*write
)(struct kernfs_open_file
*of
, char *buf
, size_t bytes
,
180 int (*mmap
)(struct kernfs_open_file
*of
, struct vm_area_struct
*vma
);
182 #ifdef CONFIG_DEBUG_LOCK_ALLOC
183 struct lock_class_key lockdep_key
;
189 static inline enum kernfs_node_type
kernfs_type(struct kernfs_node
*kn
)
191 return kn
->flags
& KERNFS_TYPE_MASK
;
195 * kernfs_enable_ns - enable namespace under a directory
196 * @kn: directory of interest, should be empty
198 * This is to be called right after @kn is created to enable namespace
199 * under it. All children of @kn must have non-NULL namespace tags and
200 * only the ones which match the super_block's tag will be visible.
202 static inline void kernfs_enable_ns(struct kernfs_node
*kn
)
204 WARN_ON_ONCE(kernfs_type(kn
) != KERNFS_DIR
);
205 WARN_ON_ONCE(!RB_EMPTY_ROOT(&kn
->dir
.children
));
206 kn
->flags
|= KERNFS_NS
;
210 * kernfs_ns_enabled - test whether namespace is enabled
211 * @kn: the node to test
213 * Test whether namespace filtering is enabled for the children of @ns.
215 static inline bool kernfs_ns_enabled(struct kernfs_node
*kn
)
217 return kn
->flags
& KERNFS_NS
;
220 struct kernfs_node
*kernfs_find_and_get_ns(struct kernfs_node
*parent
,
221 const char *name
, const void *ns
);
222 void kernfs_get(struct kernfs_node
*kn
);
223 void kernfs_put(struct kernfs_node
*kn
);
225 struct kernfs_root
*kernfs_create_root(struct kernfs_dir_ops
*kdops
,
227 void kernfs_destroy_root(struct kernfs_root
*root
);
229 struct kernfs_node
*kernfs_create_dir_ns(struct kernfs_node
*parent
,
230 const char *name
, umode_t mode
,
231 void *priv
, const void *ns
);
232 struct kernfs_node
*__kernfs_create_file(struct kernfs_node
*parent
,
234 umode_t mode
, loff_t size
,
235 const struct kernfs_ops
*ops
,
236 void *priv
, const void *ns
,
238 struct lock_class_key
*key
);
239 struct kernfs_node
*kernfs_create_link(struct kernfs_node
*parent
,
241 struct kernfs_node
*target
);
242 void kernfs_remove(struct kernfs_node
*kn
);
243 int kernfs_remove_by_name_ns(struct kernfs_node
*parent
, const char *name
,
245 int kernfs_rename_ns(struct kernfs_node
*kn
, struct kernfs_node
*new_parent
,
246 const char *new_name
, const void *new_ns
);
247 int kernfs_setattr(struct kernfs_node
*kn
, const struct iattr
*iattr
);
248 void kernfs_notify(struct kernfs_node
*kn
);
250 const void *kernfs_super_ns(struct super_block
*sb
);
251 struct dentry
*kernfs_mount_ns(struct file_system_type
*fs_type
, int flags
,
252 struct kernfs_root
*root
, const void *ns
);
253 void kernfs_kill_sb(struct super_block
*sb
);
255 void kernfs_init(void);
257 #else /* CONFIG_SYSFS */
259 static inline enum kernfs_node_type
kernfs_type(struct kernfs_node
*kn
)
260 { return 0; } /* whatever */
262 static inline void kernfs_enable_ns(struct kernfs_node
*kn
) { }
264 static inline bool kernfs_ns_enabled(struct kernfs_node
*kn
)
267 static inline struct kernfs_node
*
268 kernfs_find_and_get_ns(struct kernfs_node
*parent
, const char *name
,
272 static inline void kernfs_get(struct kernfs_node
*kn
) { }
273 static inline void kernfs_put(struct kernfs_node
*kn
) { }
275 static inline struct kernfs_root
*
276 kernfs_create_root(struct kernfs_dir_ops
*kdops
, void *priv
)
277 { return ERR_PTR(-ENOSYS
); }
279 static inline void kernfs_destroy_root(struct kernfs_root
*root
) { }
281 static inline struct kernfs_node
*
282 kernfs_create_dir_ns(struct kernfs_node
*parent
, const char *name
,
283 umode_t mode
, void *priv
, const void *ns
)
284 { return ERR_PTR(-ENOSYS
); }
286 static inline struct kernfs_node
*
287 __kernfs_create_file(struct kernfs_node
*parent
, const char *name
,
288 umode_t mode
, loff_t size
, const struct kernfs_ops
*ops
,
289 void *priv
, const void *ns
, bool name_is_static
,
290 struct lock_class_key
*key
)
291 { return ERR_PTR(-ENOSYS
); }
293 static inline struct kernfs_node
*
294 kernfs_create_link(struct kernfs_node
*parent
, const char *name
,
295 struct kernfs_node
*target
)
296 { return ERR_PTR(-ENOSYS
); }
298 static inline void kernfs_remove(struct kernfs_node
*kn
) { }
300 static inline int kernfs_remove_by_name_ns(struct kernfs_node
*kn
,
301 const char *name
, const void *ns
)
304 static inline int kernfs_rename_ns(struct kernfs_node
*kn
,
305 struct kernfs_node
*new_parent
,
306 const char *new_name
, const void *new_ns
)
309 static inline int kernfs_setattr(struct kernfs_node
*kn
,
310 const struct iattr
*iattr
)
313 static inline void kernfs_notify(struct kernfs_node
*kn
) { }
315 static inline const void *kernfs_super_ns(struct super_block
*sb
)
318 static inline struct dentry
*
319 kernfs_mount_ns(struct file_system_type
*fs_type
, int flags
,
320 struct kernfs_root
*root
, const void *ns
)
321 { return ERR_PTR(-ENOSYS
); }
323 static inline void kernfs_kill_sb(struct super_block
*sb
) { }
325 static inline void kernfs_init(void) { }
327 #endif /* CONFIG_SYSFS */
329 static inline struct kernfs_node
*
330 kernfs_find_and_get(struct kernfs_node
*kn
, const char *name
)
332 return kernfs_find_and_get_ns(kn
, name
, NULL
);
335 static inline struct kernfs_node
*
336 kernfs_create_dir(struct kernfs_node
*parent
, const char *name
, umode_t mode
,
339 return kernfs_create_dir_ns(parent
, name
, mode
, priv
, NULL
);
342 static inline struct kernfs_node
*
343 kernfs_create_file_ns(struct kernfs_node
*parent
, const char *name
,
344 umode_t mode
, loff_t size
, const struct kernfs_ops
*ops
,
345 void *priv
, const void *ns
)
347 struct lock_class_key
*key
= NULL
;
349 #ifdef CONFIG_DEBUG_LOCK_ALLOC
350 key
= (struct lock_class_key
*)&ops
->lockdep_key
;
352 return __kernfs_create_file(parent
, name
, mode
, size
, ops
, priv
, ns
,
356 static inline struct kernfs_node
*
357 kernfs_create_file(struct kernfs_node
*parent
, const char *name
, umode_t mode
,
358 loff_t size
, const struct kernfs_ops
*ops
, void *priv
)
360 return kernfs_create_file_ns(parent
, name
, mode
, size
, ops
, priv
, NULL
);
363 static inline int kernfs_remove_by_name(struct kernfs_node
*parent
,
366 return kernfs_remove_by_name_ns(parent
, name
, NULL
);
369 static inline struct dentry
*
370 kernfs_mount(struct file_system_type
*fs_type
, int flags
,
371 struct kernfs_root
*root
)
373 return kernfs_mount_ns(fs_type
, flags
, root
, NULL
);
376 #endif /* __LINUX_KERNFS_H */