aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/kernfs.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 18:49:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 18:49:44 -0500
commitd3bad75a6d57416cf7478ca2a1e42f699bc17ec5 (patch)
treed79e9403e17aef5fee028fc550eec583dda38e0c /include/linux/kernfs.h
parent9f67627a0fea99b080a190d2d24cc1e2634aa2f7 (diff)
parentdb4aad209bc9aefd91f0a9aeb9e37364088b39ad (diff)
Merge tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core / sysfs patches from Greg KH: "Here's the big driver core and sysfs patch set for 3.14-rc1. There's a lot of work here moving sysfs logic out into a "kernfs" to allow other subsystems to also have a virtual filesystem with the same attributes of sysfs (handle device disconnect, dynamic creation / removal as needed / unneeded, etc) This is primarily being done for the cgroups filesystem, but the goal is to also move debugfs to it when it is ready, solving all of the known issues in that filesystem as well. The code isn't completed yet, but all should be stable now (there is a big section that was reverted due to problems found when testing) There's also some other smaller fixes, and a driver core addition that allows for a "collection" of objects, that the DRM people will be using soon (it's in this tree to make merges after -rc1 easier) All of this has been in linux-next with no reported issues" * tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (113 commits) kernfs: associate a new kernfs_node with its parent on creation kernfs: add struct dentry declaration in kernfs.h kernfs: fix get_active failure handling in kernfs_seq_*() Revert "kernfs: fix get_active failure handling in kernfs_seq_*()" Revert "kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq" Revert "kernfs: remove KERNFS_ACTIVE_REF and add kernfs_lockdep()" Revert "kernfs: remove KERNFS_REMOVED" Revert "kernfs: restructure removal path to fix possible premature return" Revert "kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove()" Revert "kernfs: remove kernfs_addrm_cxt" Revert "kernfs: make kernfs_get_active() block if the node is deactivated but not removed" Revert "kernfs: implement kernfs_{de|re}activate[_self]()" Revert "kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers" Revert "pci: use device_remove_file_self() instead of device_schedule_callback()" Revert "scsi: use device_remove_file_self() instead of device_schedule_callback()" Revert "s390: use device_remove_file_self() instead of device_schedule_callback()" Revert "sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner()" Revert "kernfs: remove unnecessary NULL check in __kernfs_remove()" kernfs: remove unnecessary NULL check in __kernfs_remove() drivers/base: provide an infrastructure for componentised subsystems ...
Diffstat (limited to 'include/linux/kernfs.h')
-rw-r--r--include/linux/kernfs.h376
1 files changed, 376 insertions, 0 deletions
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
new file mode 100644
index 000000000000..5be9f0228a3b
--- /dev/null
+++ b/include/linux/kernfs.h
@@ -0,0 +1,376 @@
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
20struct file;
21struct dentry;
22struct iattr;
23struct seq_file;
24struct vm_area_struct;
25struct super_block;
26struct file_system_type;
27
28struct kernfs_open_node;
29struct kernfs_iattrs;
30
31enum kernfs_node_type {
32 KERNFS_DIR = 0x0001,
33 KERNFS_FILE = 0x0002,
34 KERNFS_LINK = 0x0004,
35};
36
37#define KERNFS_TYPE_MASK 0x000f
38#define KERNFS_ACTIVE_REF KERNFS_FILE
39#define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK
40
41enum kernfs_node_flag {
42 KERNFS_REMOVED = 0x0010,
43 KERNFS_NS = 0x0020,
44 KERNFS_HAS_SEQ_SHOW = 0x0040,
45 KERNFS_HAS_MMAP = 0x0080,
46 KERNFS_LOCKDEP = 0x0100,
47 KERNFS_STATIC_NAME = 0x0200,
48};
49
50/* type-specific structures for kernfs_node union members */
51struct kernfs_elem_dir {
52 unsigned long subdirs;
53 /* children rbtree starts here and goes through kn->rb */
54 struct rb_root children;
55
56 /*
57 * The kernfs hierarchy this directory belongs to. This fits
58 * better directly in kernfs_node but is here to save space.
59 */
60 struct kernfs_root *root;
61};
62
63struct kernfs_elem_symlink {
64 struct kernfs_node *target_kn;
65};
66
67struct kernfs_elem_attr {
68 const struct kernfs_ops *ops;
69 struct kernfs_open_node *open;
70 loff_t size;
71};
72
73/*
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.
77 *
78 * As long as s_count reference is held, the kernfs_node itself is
79 * accessible. Dereferencing elem or any other outer entity requires
80 * active reference.
81 */
82struct kernfs_node {
83 atomic_t count;
84 atomic_t active;
85#ifdef CONFIG_DEBUG_LOCK_ALLOC
86 struct lockdep_map dep_map;
87#endif
88 /* the following two fields are published */
89 struct kernfs_node *parent;
90 const char *name;
91
92 struct rb_node rb;
93
94 union {
95 struct completion *completion;
96 struct kernfs_node *removed_list;
97 } u;
98
99 const void *ns; /* namespace tag */
100 unsigned int hash; /* ns + name hash */
101 union {
102 struct kernfs_elem_dir dir;
103 struct kernfs_elem_symlink symlink;
104 struct kernfs_elem_attr attr;
105 };
106
107 void *priv;
108
109 unsigned short flags;
110 umode_t mode;
111 unsigned int ino;
112 struct kernfs_iattrs *iattr;
113};
114
115/*
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.
120 */
121struct kernfs_dir_ops {
122 int (*mkdir)(struct kernfs_node *parent, const char *name,
123 umode_t mode);
124 int (*rmdir)(struct kernfs_node *kn);
125 int (*rename)(struct kernfs_node *kn, struct kernfs_node *new_parent,
126 const char *new_name);
127};
128
129struct kernfs_root {
130 /* published fields */
131 struct kernfs_node *kn;
132
133 /* private fields, do not use outside kernfs proper */
134 struct ida ino_ida;
135 struct kernfs_dir_ops *dir_ops;
136};
137
138struct kernfs_open_file {
139 /* published fields */
140 struct kernfs_node *kn;
141 struct file *file;
142
143 /* private fields, do not use outside kernfs proper */
144 struct mutex mutex;
145 int event;
146 struct list_head list;
147
148 bool mmapped;
149 const struct vm_operations_struct *vm_ops;
150};
151
152struct kernfs_ops {
153 /*
154 * Read is handled by either seq_file or raw_read().
155 *
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.
160 *
161 * read() is bounced through kernel buffer and a read larger than
162 * PAGE_SIZE results in partial operation of PAGE_SIZE.
163 */
164 int (*seq_show)(struct seq_file *sf, void *v);
165
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);
169
170 ssize_t (*read)(struct kernfs_open_file *of, char *buf, size_t bytes,
171 loff_t off);
172
173 /*
174 * write() is bounced through kernel buffer and a write larger than
175 * PAGE_SIZE results in partial operation of PAGE_SIZE.
176 */
177 ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes,
178 loff_t off);
179
180 int (*mmap)(struct kernfs_open_file *of, struct vm_area_struct *vma);
181
182#ifdef CONFIG_DEBUG_LOCK_ALLOC
183 struct lock_class_key lockdep_key;
184#endif
185};
186
187#ifdef CONFIG_SYSFS
188
189static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
190{
191 return kn->flags & KERNFS_TYPE_MASK;
192}
193
194/**
195 * kernfs_enable_ns - enable namespace under a directory
196 * @kn: directory of interest, should be empty
197 *
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.
201 */
202static inline void kernfs_enable_ns(struct kernfs_node *kn)
203{
204 WARN_ON_ONCE(kernfs_type(kn) != KERNFS_DIR);
205 WARN_ON_ONCE(!RB_EMPTY_ROOT(&kn->dir.children));
206 kn->flags |= KERNFS_NS;
207}
208
209/**
210 * kernfs_ns_enabled - test whether namespace is enabled
211 * @kn: the node to test
212 *
213 * Test whether namespace filtering is enabled for the children of @ns.
214 */
215static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
216{
217 return kn->flags & KERNFS_NS;
218}
219
220struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
221 const char *name, const void *ns);
222void kernfs_get(struct kernfs_node *kn);
223void kernfs_put(struct kernfs_node *kn);
224
225struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops,
226 void *priv);
227void kernfs_destroy_root(struct kernfs_root *root);
228
229struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
230 const char *name, umode_t mode,
231 void *priv, const void *ns);
232struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
233 const char *name,
234 umode_t mode, loff_t size,
235 const struct kernfs_ops *ops,
236 void *priv, const void *ns,
237 bool name_is_static,
238 struct lock_class_key *key);
239struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
240 const char *name,
241 struct kernfs_node *target);
242void kernfs_remove(struct kernfs_node *kn);
243int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
244 const void *ns);
245int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
246 const char *new_name, const void *new_ns);
247int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr);
248void kernfs_notify(struct kernfs_node *kn);
249
250const void *kernfs_super_ns(struct super_block *sb);
251struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
252 struct kernfs_root *root, const void *ns);
253void kernfs_kill_sb(struct super_block *sb);
254
255void kernfs_init(void);
256
257#else /* CONFIG_SYSFS */
258
259static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
260{ return 0; } /* whatever */
261
262static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
263
264static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
265{ return false; }
266
267static inline struct kernfs_node *
268kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
269 const void *ns)
270{ return NULL; }
271
272static inline void kernfs_get(struct kernfs_node *kn) { }
273static inline void kernfs_put(struct kernfs_node *kn) { }
274
275static inline struct kernfs_root *
276kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
277{ return ERR_PTR(-ENOSYS); }
278
279static inline void kernfs_destroy_root(struct kernfs_root *root) { }
280
281static inline struct kernfs_node *
282kernfs_create_dir_ns(struct kernfs_node *parent, const char *name,
283 umode_t mode, void *priv, const void *ns)
284{ return ERR_PTR(-ENOSYS); }
285
286static 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); }
292
293static inline struct kernfs_node *
294kernfs_create_link(struct kernfs_node *parent, const char *name,
295 struct kernfs_node *target)
296{ return ERR_PTR(-ENOSYS); }
297
298static inline void kernfs_remove(struct kernfs_node *kn) { }
299
300static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn,
301 const char *name, const void *ns)
302{ return -ENOSYS; }
303
304static inline int kernfs_rename_ns(struct kernfs_node *kn,
305 struct kernfs_node *new_parent,
306 const char *new_name, const void *new_ns)
307{ return -ENOSYS; }
308
309static inline int kernfs_setattr(struct kernfs_node *kn,
310 const struct iattr *iattr)
311{ return -ENOSYS; }
312
313static inline void kernfs_notify(struct kernfs_node *kn) { }
314
315static inline const void *kernfs_super_ns(struct super_block *sb)
316{ return NULL; }
317
318static inline struct dentry *
319kernfs_mount_ns(struct file_system_type *fs_type, int flags,
320 struct kernfs_root *root, const void *ns)
321{ return ERR_PTR(-ENOSYS); }
322
323static inline void kernfs_kill_sb(struct super_block *sb) { }
324
325static inline void kernfs_init(void) { }
326
327#endif /* CONFIG_SYSFS */
328
329static inline struct kernfs_node *
330kernfs_find_and_get(struct kernfs_node *kn, const char *name)
331{
332 return kernfs_find_and_get_ns(kn, name, NULL);
333}
334
335static inline struct kernfs_node *
336kernfs_create_dir(struct kernfs_node *parent, const char *name, umode_t mode,
337 void *priv)
338{
339 return kernfs_create_dir_ns(parent, name, mode, priv, NULL);
340}
341
342static inline struct kernfs_node *
343kernfs_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)
346{
347 struct lock_class_key *key = NULL;
348
349#ifdef CONFIG_DEBUG_LOCK_ALLOC
350 key = (struct lock_class_key *)&ops->lockdep_key;
351#endif
352 return __kernfs_create_file(parent, name, mode, size, ops, priv, ns,
353 false, key);
354}
355
356static inline struct kernfs_node *
357kernfs_create_file(struct kernfs_node *parent, const char *name, umode_t mode,
358 loff_t size, const struct kernfs_ops *ops, void *priv)
359{
360 return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL);
361}
362
363static inline int kernfs_remove_by_name(struct kernfs_node *parent,
364 const char *name)
365{
366 return kernfs_remove_by_name_ns(parent, name, NULL);
367}
368
369static inline struct dentry *
370kernfs_mount(struct file_system_type *fs_type, int flags,
371 struct kernfs_root *root)
372{
373 return kernfs_mount_ns(fs_type, flags, root, NULL);
374}
375
376#endif /* __LINUX_KERNFS_H */