]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - include/linux/kernfs.h
sysfs, kernfs: make sysfs_dirent definition public
[karo-tx-linux.git] / 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 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 struct sysfs_dirent *kernfs_find_and_get_ns(struct sysfs_dirent *parent,
194                                             const char *name, const void *ns);
195 void kernfs_get(struct sysfs_dirent *sd);
196 void kernfs_put(struct sysfs_dirent *sd);
197
198 struct kernfs_root *kernfs_create_root(void *priv);
199 void kernfs_destroy_root(struct kernfs_root *root);
200
201 struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
202                                           const char *name, void *priv,
203                                           const void *ns);
204 struct sysfs_dirent *kernfs_create_file_ns_key(struct sysfs_dirent *parent,
205                                                const char *name,
206                                                umode_t mode, loff_t size,
207                                                const struct kernfs_ops *ops,
208                                                void *priv, const void *ns,
209                                                struct lock_class_key *key);
210 struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
211                                         const char *name,
212                                         struct sysfs_dirent *target);
213 void kernfs_remove(struct sysfs_dirent *sd);
214 int kernfs_remove_by_name_ns(struct sysfs_dirent *parent, const char *name,
215                              const void *ns);
216 int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
217                      const char *new_name, const void *new_ns);
218 int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr);
219 void kernfs_notify(struct sysfs_dirent *sd);
220
221 const void *kernfs_super_ns(struct super_block *sb);
222 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
223                                struct kernfs_root *root, const void *ns);
224 void kernfs_kill_sb(struct super_block *sb);
225
226 void kernfs_init(void);
227
228 #else   /* CONFIG_SYSFS */
229
230 static inline enum kernfs_node_type sysfs_type(struct sysfs_dirent *sd)
231 { return 0; }   /* whatever */
232
233 static inline void kernfs_enable_ns(struct sysfs_dirent *sd) { }
234
235 static inline struct sysfs_dirent *
236 kernfs_find_and_get_ns(struct sysfs_dirent *parent, const char *name,
237                        const void *ns)
238 { return NULL; }
239
240 static inline void kernfs_get(struct sysfs_dirent *sd) { }
241 static inline void kernfs_put(struct sysfs_dirent *sd) { }
242
243 static inline struct kernfs_root *kernfs_create_root(void *priv)
244 { return ERR_PTR(-ENOSYS); }
245
246 static inline void kernfs_destroy_root(struct kernfs_root *root) { }
247
248 static inline struct sysfs_dirent *
249 kernfs_create_dir_ns(struct sysfs_dirent *parent, const char *name, void *priv,
250                      const void *ns)
251 { return ERR_PTR(-ENOSYS); }
252
253 static inline struct sysfs_dirent *
254 kernfs_create_file_ns_key(struct sysfs_dirent *parent, const char *name,
255                           umode_t mode, loff_t size,
256                           const struct kernfs_ops *ops, void *priv,
257                           const void *ns, struct lock_class_key *key)
258 { return ERR_PTR(-ENOSYS); }
259
260 static inline struct sysfs_dirent *
261 kernfs_create_link(struct sysfs_dirent *parent, const char *name,
262                    struct sysfs_dirent *target)
263 { return ERR_PTR(-ENOSYS); }
264
265 static inline void kernfs_remove(struct sysfs_dirent *sd) { }
266
267 static inline int kernfs_remove_by_name_ns(struct sysfs_dirent *parent,
268                                            const char *name, const void *ns)
269 { return -ENOSYS; }
270
271 static inline int kernfs_rename_ns(struct sysfs_dirent *sd,
272                                    struct sysfs_dirent *new_parent,
273                                    const char *new_name, const void *new_ns)
274 { return -ENOSYS; }
275
276 static inline int kernfs_setattr(struct sysfs_dirent *sd,
277                                  const struct iattr *iattr)
278 { return -ENOSYS; }
279
280 static inline void kernfs_notify(struct sysfs_dirent *sd) { }
281
282 static inline const void *kernfs_super_ns(struct super_block *sb)
283 { return NULL; }
284
285 static inline struct dentry *
286 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
287                 struct kernfs_root *root, const void *ns)
288 { return ERR_PTR(-ENOSYS); }
289
290 static inline void kernfs_kill_sb(struct super_block *sb) { }
291
292 static inline void kernfs_init(void) { }
293
294 #endif  /* CONFIG_SYSFS */
295
296 static inline struct sysfs_dirent *
297 kernfs_find_and_get(struct sysfs_dirent *sd, const char *name)
298 {
299         return kernfs_find_and_get_ns(sd, name, NULL);
300 }
301
302 static inline struct sysfs_dirent *
303 kernfs_create_dir(struct sysfs_dirent *parent, const char *name, void *priv)
304 {
305         return kernfs_create_dir_ns(parent, name, priv, NULL);
306 }
307
308 static inline struct sysfs_dirent *
309 kernfs_create_file_ns(struct sysfs_dirent *parent, const char *name,
310                       umode_t mode, loff_t size, const struct kernfs_ops *ops,
311                       void *priv, const void *ns)
312 {
313         struct lock_class_key *key = NULL;
314
315 #ifdef CONFIG_DEBUG_LOCK_ALLOC
316         key = (struct lock_class_key *)&ops->lockdep_key;
317 #endif
318         return kernfs_create_file_ns_key(parent, name, mode, size, ops, priv,
319                                          ns, key);
320 }
321
322 static inline struct sysfs_dirent *
323 kernfs_create_file(struct sysfs_dirent *parent, const char *name, umode_t mode,
324                    loff_t size, const struct kernfs_ops *ops, void *priv)
325 {
326         return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL);
327 }
328
329 static inline int kernfs_remove_by_name(struct sysfs_dirent *parent,
330                                         const char *name)
331 {
332         return kernfs_remove_by_name_ns(parent, name, NULL);
333 }
334
335 static inline struct dentry *
336 kernfs_mount(struct file_system_type *fs_type, int flags,
337              struct kernfs_root *root)
338 {
339         return kernfs_mount_ns(fs_type, flags, root, NULL);
340 }
341
342 #endif  /* __LINUX_KERNFS_H */