]> Pileus Git - ~andy/linux/blob - include/linux/kernfs.h
Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[~andy/linux] / include / linux / kernfs.h
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 dentry;
22 struct iattr;
23 struct seq_file;
24 struct vm_area_struct;
25 struct super_block;
26 struct file_system_type;
27
28 struct kernfs_open_node;
29 struct kernfs_iattrs;
30
31 enum 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
41 enum 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 */
51 struct 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
63 struct kernfs_elem_symlink {
64         struct kernfs_node      *target_kn;
65 };
66
67 struct 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  */
82 struct 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  */
121 struct 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
129 struct 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
138 struct 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
152 struct 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
189 static 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  */
202 static 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  */
215 static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
216 {
217         return kn->flags & KERNFS_NS;
218 }
219
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);
224
225 struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops,
226                                        void *priv);
227 void kernfs_destroy_root(struct kernfs_root *root);
228
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,
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);
239 struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
240                                        const char *name,
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,
244                              const void *ns);
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);
249
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, bool *new_sb_created,
253                                const void *ns);
254 void kernfs_kill_sb(struct super_block *sb);
255
256 void kernfs_init(void);
257
258 #else   /* CONFIG_SYSFS */
259
260 static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
261 { return 0; }   /* whatever */
262
263 static inline void kernfs_enable_ns(struct kernfs_node *kn) { }
264
265 static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
266 { return false; }
267
268 static inline struct kernfs_node *
269 kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
270                        const void *ns)
271 { return NULL; }
272
273 static inline void kernfs_get(struct kernfs_node *kn) { }
274 static inline void kernfs_put(struct kernfs_node *kn) { }
275
276 static inline struct kernfs_root *
277 kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv)
278 { return ERR_PTR(-ENOSYS); }
279
280 static inline void kernfs_destroy_root(struct kernfs_root *root) { }
281
282 static inline struct kernfs_node *
283 kernfs_create_dir_ns(struct kernfs_node *parent, const char *name,
284                      umode_t mode, void *priv, const void *ns)
285 { return ERR_PTR(-ENOSYS); }
286
287 static inline struct kernfs_node *
288 __kernfs_create_file(struct kernfs_node *parent, const char *name,
289                      umode_t mode, loff_t size, const struct kernfs_ops *ops,
290                      void *priv, const void *ns, bool name_is_static,
291                      struct lock_class_key *key)
292 { return ERR_PTR(-ENOSYS); }
293
294 static inline struct kernfs_node *
295 kernfs_create_link(struct kernfs_node *parent, const char *name,
296                    struct kernfs_node *target)
297 { return ERR_PTR(-ENOSYS); }
298
299 static inline void kernfs_remove(struct kernfs_node *kn) { }
300
301 static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn,
302                                            const char *name, const void *ns)
303 { return -ENOSYS; }
304
305 static inline int kernfs_rename_ns(struct kernfs_node *kn,
306                                    struct kernfs_node *new_parent,
307                                    const char *new_name, const void *new_ns)
308 { return -ENOSYS; }
309
310 static inline int kernfs_setattr(struct kernfs_node *kn,
311                                  const struct iattr *iattr)
312 { return -ENOSYS; }
313
314 static inline void kernfs_notify(struct kernfs_node *kn) { }
315
316 static inline const void *kernfs_super_ns(struct super_block *sb)
317 { return NULL; }
318
319 static inline struct dentry *
320 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
321                 struct kernfs_root *root, bool *new_sb_created, const void *ns)
322 { return ERR_PTR(-ENOSYS); }
323
324 static inline void kernfs_kill_sb(struct super_block *sb) { }
325
326 static inline void kernfs_init(void) { }
327
328 #endif  /* CONFIG_SYSFS */
329
330 static inline struct kernfs_node *
331 kernfs_find_and_get(struct kernfs_node *kn, const char *name)
332 {
333         return kernfs_find_and_get_ns(kn, name, NULL);
334 }
335
336 static inline struct kernfs_node *
337 kernfs_create_dir(struct kernfs_node *parent, const char *name, umode_t mode,
338                   void *priv)
339 {
340         return kernfs_create_dir_ns(parent, name, mode, priv, NULL);
341 }
342
343 static inline struct kernfs_node *
344 kernfs_create_file_ns(struct kernfs_node *parent, const char *name,
345                       umode_t mode, loff_t size, const struct kernfs_ops *ops,
346                       void *priv, const void *ns)
347 {
348         struct lock_class_key *key = NULL;
349
350 #ifdef CONFIG_DEBUG_LOCK_ALLOC
351         key = (struct lock_class_key *)&ops->lockdep_key;
352 #endif
353         return __kernfs_create_file(parent, name, mode, size, ops, priv, ns,
354                                     false, key);
355 }
356
357 static inline struct kernfs_node *
358 kernfs_create_file(struct kernfs_node *parent, const char *name, umode_t mode,
359                    loff_t size, const struct kernfs_ops *ops, void *priv)
360 {
361         return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL);
362 }
363
364 static inline int kernfs_remove_by_name(struct kernfs_node *parent,
365                                         const char *name)
366 {
367         return kernfs_remove_by_name_ns(parent, name, NULL);
368 }
369
370 static inline struct dentry *
371 kernfs_mount(struct file_system_type *fs_type, int flags,
372              struct kernfs_root *root, bool *new_sb_created)
373 {
374         return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
375 }
376
377 #endif  /* __LINUX_KERNFS_H */