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/wait.h>
23 struct vm_area_struct
;
25 struct file_system_type
;
27 struct kernfs_open_node
;
30 enum kernfs_node_type
{
36 #define KERNFS_TYPE_MASK 0x000f
37 #define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK
39 enum kernfs_node_flag
{
40 KERNFS_JUST_DEACTIVATED
= 0x0010, /* used to aid lockdep annotation */
42 KERNFS_HAS_SEQ_SHOW
= 0x0040,
43 KERNFS_HAS_MMAP
= 0x0080,
44 KERNFS_LOCKDEP
= 0x0100,
45 KERNFS_STATIC_NAME
= 0x0200,
48 /* type-specific structures for kernfs_node union members */
49 struct kernfs_elem_dir
{
50 unsigned long subdirs
;
51 /* children rbtree starts here and goes through kn->rb */
52 struct rb_root children
;
55 * The kernfs hierarchy this directory belongs to. This fits
56 * better directly in kernfs_node but is here to save space.
58 struct kernfs_root
*root
;
61 struct kernfs_elem_symlink
{
62 struct kernfs_node
*target_kn
;
65 struct kernfs_elem_attr
{
66 const struct kernfs_ops
*ops
;
67 struct kernfs_open_node
*open
;
72 * kernfs_node - the building block of kernfs hierarchy. Each and every
73 * kernfs node is represented by single kernfs_node. Most fields are
74 * private to kernfs and shouldn't be accessed directly by kernfs users.
76 * As long as s_count reference is held, the kernfs_node itself is
77 * accessible. Dereferencing elem or any other outer entity requires
83 #ifdef CONFIG_DEBUG_LOCK_ALLOC
84 struct lockdep_map dep_map
;
86 /* the following two fields are published */
87 struct kernfs_node
*parent
;
93 struct kernfs_node
*removed_list
;
96 const void *ns
; /* namespace tag */
97 unsigned int hash
; /* ns + name hash */
99 struct kernfs_elem_dir dir
;
100 struct kernfs_elem_symlink symlink
;
101 struct kernfs_elem_attr attr
;
106 unsigned short flags
;
109 struct kernfs_iattrs
*iattr
;
113 * kernfs_dir_ops may be specified on kernfs_create_root() to support
114 * directory manipulation syscalls. These optional callbacks are invoked
115 * on the matching syscalls and can perform any kernfs operations which
116 * don't necessarily have to be the exact operation requested.
118 struct kernfs_dir_ops
{
119 int (*mkdir
)(struct kernfs_node
*parent
, const char *name
,
121 int (*rmdir
)(struct kernfs_node
*kn
);
122 int (*rename
)(struct kernfs_node
*kn
, struct kernfs_node
*new_parent
,
123 const char *new_name
);
127 /* published fields */
128 struct kernfs_node
*kn
;
130 /* private fields, do not use outside kernfs proper */
132 struct kernfs_dir_ops
*dir_ops
;
133 wait_queue_head_t deactivate_waitq
;
136 struct kernfs_open_file
{
137 /* published fields */
138 struct kernfs_node
*kn
;
141 /* private fields, do not use outside kernfs proper */
144 struct list_head list
;
147 const struct vm_operations_struct
*vm_ops
;
152 * Read is handled by either seq_file or raw_read().
154 * If seq_show() is present, seq_file path is active. Other seq
155 * operations are optional and if not implemented, the behavior is
156 * equivalent to single_open(). @sf->private points to the
157 * associated kernfs_open_file.
159 * read() is bounced through kernel buffer and a read larger than
160 * PAGE_SIZE results in partial operation of PAGE_SIZE.
162 int (*seq_show
)(struct seq_file
*sf
, void *v
);
164 void *(*seq_start
)(struct seq_file
*sf
, loff_t
*ppos
);
165 void *(*seq_next
)(struct seq_file
*sf
, void *v
, loff_t
*ppos
);
166 void (*seq_stop
)(struct seq_file
*sf
, void *v
);
168 ssize_t (*read
)(struct kernfs_open_file
*of
, char *buf
, size_t bytes
,
172 * write() is bounced through kernel buffer and a write larger than
173 * PAGE_SIZE results in partial operation of PAGE_SIZE.
175 ssize_t (*write
)(struct kernfs_open_file
*of
, char *buf
, size_t bytes
,
178 int (*mmap
)(struct kernfs_open_file
*of
, struct vm_area_struct
*vma
);
180 #ifdef CONFIG_DEBUG_LOCK_ALLOC
181 struct lock_class_key lockdep_key
;
187 static inline enum kernfs_node_type
kernfs_type(struct kernfs_node
*kn
)
189 return kn
->flags
& KERNFS_TYPE_MASK
;
193 * kernfs_enable_ns - enable namespace under a directory
194 * @kn: directory of interest, should be empty
196 * This is to be called right after @kn is created to enable namespace
197 * under it. All children of @kn must have non-NULL namespace tags and
198 * only the ones which match the super_block's tag will be visible.
200 static inline void kernfs_enable_ns(struct kernfs_node
*kn
)
202 WARN_ON_ONCE(kernfs_type(kn
) != KERNFS_DIR
);
203 WARN_ON_ONCE(!RB_EMPTY_ROOT(&kn
->dir
.children
));
204 kn
->flags
|= KERNFS_NS
;
208 * kernfs_ns_enabled - test whether namespace is enabled
209 * @kn: the node to test
211 * Test whether namespace filtering is enabled for the children of @ns.
213 static inline bool kernfs_ns_enabled(struct kernfs_node
*kn
)
215 return kn
->flags
& KERNFS_NS
;
218 struct kernfs_node
*kernfs_find_and_get_ns(struct kernfs_node
*parent
,
219 const char *name
, const void *ns
);
220 void kernfs_get(struct kernfs_node
*kn
);
221 void kernfs_put(struct kernfs_node
*kn
);
223 struct kernfs_root
*kernfs_create_root(struct kernfs_dir_ops
*kdops
,
225 void kernfs_destroy_root(struct kernfs_root
*root
);
227 struct kernfs_node
*kernfs_create_dir_ns(struct kernfs_node
*parent
,
228 const char *name
, umode_t mode
,
229 void *priv
, const void *ns
);
230 struct kernfs_node
*__kernfs_create_file(struct kernfs_node
*parent
,
232 umode_t mode
, loff_t size
,
233 const struct kernfs_ops
*ops
,
234 void *priv
, const void *ns
,
236 struct lock_class_key
*key
);
237 struct kernfs_node
*kernfs_create_link(struct kernfs_node
*parent
,
239 struct kernfs_node
*target
);
240 void kernfs_remove(struct kernfs_node
*kn
);
241 int kernfs_remove_by_name_ns(struct kernfs_node
*parent
, const char *name
,
243 int kernfs_rename_ns(struct kernfs_node
*kn
, struct kernfs_node
*new_parent
,
244 const char *new_name
, const void *new_ns
);
245 int kernfs_setattr(struct kernfs_node
*kn
, const struct iattr
*iattr
);
246 void kernfs_notify(struct kernfs_node
*kn
);
248 const void *kernfs_super_ns(struct super_block
*sb
);
249 struct dentry
*kernfs_mount_ns(struct file_system_type
*fs_type
, int flags
,
250 struct kernfs_root
*root
, const void *ns
);
251 void kernfs_kill_sb(struct super_block
*sb
);
253 void kernfs_init(void);
255 #else /* CONFIG_SYSFS */
257 static inline enum kernfs_node_type
kernfs_type(struct kernfs_node
*kn
)
258 { return 0; } /* whatever */
260 static inline void kernfs_enable_ns(struct kernfs_node
*kn
) { }
262 static inline bool kernfs_ns_enabled(struct kernfs_node
*kn
)
265 static inline struct kernfs_node
*
266 kernfs_find_and_get_ns(struct kernfs_node
*parent
, const char *name
,
270 static inline void kernfs_get(struct kernfs_node
*kn
) { }
271 static inline void kernfs_put(struct kernfs_node
*kn
) { }
273 static inline struct kernfs_root
*
274 kernfs_create_root(struct kernfs_dir_ops
*kdops
, void *priv
)
275 { return ERR_PTR(-ENOSYS
); }
277 static inline void kernfs_destroy_root(struct kernfs_root
*root
) { }
279 static inline struct kernfs_node
*
280 kernfs_create_dir_ns(struct kernfs_node
*parent
, const char *name
,
281 umode_t mode
, void *priv
, const void *ns
)
282 { return ERR_PTR(-ENOSYS
); }
284 static inline struct kernfs_node
*
285 __kernfs_create_file(struct kernfs_node
*parent
, const char *name
,
286 umode_t mode
, loff_t size
, const struct kernfs_ops
*ops
,
287 void *priv
, const void *ns
, bool name_is_static
,
288 struct lock_class_key
*key
)
289 { return ERR_PTR(-ENOSYS
); }
291 static inline struct kernfs_node
*
292 kernfs_create_link(struct kernfs_node
*parent
, const char *name
,
293 struct kernfs_node
*target
)
294 { return ERR_PTR(-ENOSYS
); }
296 static inline void kernfs_remove(struct kernfs_node
*kn
) { }
298 static inline int kernfs_remove_by_name_ns(struct kernfs_node
*kn
,
299 const char *name
, const void *ns
)
302 static inline int kernfs_rename_ns(struct kernfs_node
*kn
,
303 struct kernfs_node
*new_parent
,
304 const char *new_name
, const void *new_ns
)
307 static inline int kernfs_setattr(struct kernfs_node
*kn
,
308 const struct iattr
*iattr
)
311 static inline void kernfs_notify(struct kernfs_node
*kn
) { }
313 static inline const void *kernfs_super_ns(struct super_block
*sb
)
316 static inline struct dentry
*
317 kernfs_mount_ns(struct file_system_type
*fs_type
, int flags
,
318 struct kernfs_root
*root
, const void *ns
)
319 { return ERR_PTR(-ENOSYS
); }
321 static inline void kernfs_kill_sb(struct super_block
*sb
) { }
323 static inline void kernfs_init(void) { }
325 #endif /* CONFIG_SYSFS */
327 static inline struct kernfs_node
*
328 kernfs_find_and_get(struct kernfs_node
*kn
, const char *name
)
330 return kernfs_find_and_get_ns(kn
, name
, NULL
);
333 static inline struct kernfs_node
*
334 kernfs_create_dir(struct kernfs_node
*parent
, const char *name
, umode_t mode
,
337 return kernfs_create_dir_ns(parent
, name
, mode
, priv
, NULL
);
340 static inline struct kernfs_node
*
341 kernfs_create_file_ns(struct kernfs_node
*parent
, const char *name
,
342 umode_t mode
, loff_t size
, const struct kernfs_ops
*ops
,
343 void *priv
, const void *ns
)
345 struct lock_class_key
*key
= NULL
;
347 #ifdef CONFIG_DEBUG_LOCK_ALLOC
348 key
= (struct lock_class_key
*)&ops
->lockdep_key
;
350 return __kernfs_create_file(parent
, name
, mode
, size
, ops
, priv
, ns
,
354 static inline struct kernfs_node
*
355 kernfs_create_file(struct kernfs_node
*parent
, const char *name
, umode_t mode
,
356 loff_t size
, const struct kernfs_ops
*ops
, void *priv
)
358 return kernfs_create_file_ns(parent
, name
, mode
, size
, ops
, priv
, NULL
);
361 static inline int kernfs_remove_by_name(struct kernfs_node
*parent
,
364 return kernfs_remove_by_name_ns(parent
, name
, NULL
);
367 static inline struct dentry
*
368 kernfs_mount(struct file_system_type
*fs_type
, int flags
,
369 struct kernfs_root
*root
)
371 return kernfs_mount_ns(fs_type
, flags
, root
, NULL
);
374 #endif /* __LINUX_KERNFS_H */