Branch data Line data Source code
1 : : /*
2 : : * fs/sysfs/sysfs.h - sysfs internal header file
3 : : *
4 : : * Copyright (c) 2001-3 Patrick Mochel
5 : : * Copyright (c) 2007 SUSE Linux Products GmbH
6 : : * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
7 : : *
8 : : * This file is released under the GPLv2.
9 : : */
10 : :
11 : : #include <linux/lockdep.h>
12 : : #include <linux/kobject_ns.h>
13 : : #include <linux/fs.h>
14 : : #include <linux/rbtree.h>
15 : :
16 : : struct sysfs_open_dirent;
17 : :
18 : : /* type-specific structures for sysfs_dirent->s_* union members */
19 : : struct sysfs_elem_dir {
20 : : struct kobject *kobj;
21 : :
22 : : unsigned long subdirs;
23 : : /* children rbtree starts here and goes through sd->s_rb */
24 : : struct rb_root children;
25 : : };
26 : :
27 : : struct sysfs_elem_symlink {
28 : : struct sysfs_dirent *target_sd;
29 : : };
30 : :
31 : : struct sysfs_elem_attr {
32 : : union {
33 : : struct attribute *attr;
34 : : struct bin_attribute *bin_attr;
35 : : };
36 : : struct sysfs_open_dirent *open;
37 : : };
38 : :
39 : : struct sysfs_inode_attrs {
40 : : struct iattr ia_iattr;
41 : : void *ia_secdata;
42 : : u32 ia_secdata_len;
43 : : };
44 : :
45 : : /*
46 : : * sysfs_dirent - the building block of sysfs hierarchy. Each and
47 : : * every sysfs node is represented by single sysfs_dirent.
48 : : *
49 : : * As long as s_count reference is held, the sysfs_dirent itself is
50 : : * accessible. Dereferencing s_elem or any other outer entity
51 : : * requires s_active reference.
52 : : */
53 : : struct sysfs_dirent {
54 : : atomic_t s_count;
55 : : atomic_t s_active;
56 : : #ifdef CONFIG_DEBUG_LOCK_ALLOC
57 : : struct lockdep_map dep_map;
58 : : #endif
59 : : struct sysfs_dirent *s_parent;
60 : : const char *s_name;
61 : :
62 : : struct rb_node s_rb;
63 : :
64 : : union {
65 : : struct completion *completion;
66 : : struct sysfs_dirent *removed_list;
67 : : } u;
68 : :
69 : : const void *s_ns; /* namespace tag */
70 : : unsigned int s_hash; /* ns + name hash */
71 : : union {
72 : : struct sysfs_elem_dir s_dir;
73 : : struct sysfs_elem_symlink s_symlink;
74 : : struct sysfs_elem_attr s_attr;
75 : : };
76 : :
77 : : unsigned short s_flags;
78 : : umode_t s_mode;
79 : : unsigned int s_ino;
80 : : struct sysfs_inode_attrs *s_iattr;
81 : : };
82 : :
83 : : #define SD_DEACTIVATED_BIAS INT_MIN
84 : :
85 : : #define SYSFS_TYPE_MASK 0x00ff
86 : : #define SYSFS_DIR 0x0001
87 : : #define SYSFS_KOBJ_ATTR 0x0002
88 : : #define SYSFS_KOBJ_BIN_ATTR 0x0004
89 : : #define SYSFS_KOBJ_LINK 0x0008
90 : : #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
91 : : #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
92 : :
93 : : /* identify any namespace tag on sysfs_dirents */
94 : : #define SYSFS_NS_TYPE_MASK 0xf00
95 : : #define SYSFS_NS_TYPE_SHIFT 8
96 : :
97 : : #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK)
98 : : #define SYSFS_FLAG_REMOVED 0x02000
99 : :
100 : : static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
101 : : {
102 : 148408 : return sd->s_flags & SYSFS_TYPE_MASK;
103 : : }
104 : :
105 : : /*
106 : : * Return any namespace tags on this dirent.
107 : : * enum kobj_ns_type is defined in linux/kobject.h
108 : : */
109 : : static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd)
110 : : {
111 : 145644 : return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT;
112 : : }
113 : :
114 : : #ifdef CONFIG_DEBUG_LOCK_ALLOC
115 : :
116 : : #define sysfs_dirent_init_lockdep(sd) \
117 : : do { \
118 : : struct attribute *attr = sd->s_attr.attr; \
119 : : struct lock_class_key *key = attr->key; \
120 : : if (!key) \
121 : : key = &attr->skey; \
122 : : \
123 : : lockdep_init_map(&sd->dep_map, "s_active", key, 0); \
124 : : } while (0)
125 : :
126 : : /* Test for attributes that want to ignore lockdep for read-locking */
127 : : static inline bool sysfs_ignore_lockdep(struct sysfs_dirent *sd)
128 : : {
129 : : int type = sysfs_type(sd);
130 : :
131 : : return (type == SYSFS_KOBJ_ATTR || type == SYSFS_KOBJ_BIN_ATTR) &&
132 : : sd->s_attr.attr->ignore_lockdep;
133 : : }
134 : :
135 : : #else
136 : :
137 : : #define sysfs_dirent_init_lockdep(sd) do {} while (0)
138 : :
139 : : static inline bool sysfs_ignore_lockdep(struct sysfs_dirent *sd)
140 : : {
141 : : return true;
142 : : }
143 : :
144 : : #endif
145 : :
146 : : /*
147 : : * Context structure to be used while adding/removing nodes.
148 : : */
149 : : struct sysfs_addrm_cxt {
150 : : struct sysfs_dirent *removed;
151 : : };
152 : :
153 : : /*
154 : : * mount.c
155 : : */
156 : :
157 : : /*
158 : : * Each sb is associated with a set of namespace tags (i.e.
159 : : * the network namespace of the task which mounted this sysfs
160 : : * instance).
161 : : */
162 : : struct sysfs_super_info {
163 : : void *ns[KOBJ_NS_TYPES];
164 : : };
165 : : #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info))
166 : : extern struct sysfs_dirent sysfs_root;
167 : : extern struct kmem_cache *sysfs_dir_cachep;
168 : :
169 : : /*
170 : : * dir.c
171 : : */
172 : : extern struct mutex sysfs_mutex;
173 : : extern spinlock_t sysfs_symlink_target_lock;
174 : : extern const struct dentry_operations sysfs_dentry_ops;
175 : :
176 : : extern const struct file_operations sysfs_dir_operations;
177 : : extern const struct inode_operations sysfs_dir_inode_operations;
178 : :
179 : : struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
180 : : void sysfs_put_active(struct sysfs_dirent *sd);
181 : : void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt);
182 : : void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name);
183 : : int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
184 : : struct sysfs_dirent *parent_sd);
185 : : int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
186 : : struct sysfs_dirent *parent_sd);
187 : : void sysfs_remove(struct sysfs_dirent *sd);
188 : : int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
189 : : const void *ns);
190 : : void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
191 : :
192 : : struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
193 : : const unsigned char *name,
194 : : const void *ns);
195 : : struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
196 : :
197 : : void release_sysfs_dirent(struct sysfs_dirent *sd);
198 : :
199 : : int sysfs_create_subdir(struct kobject *kobj, const char *name,
200 : : struct sysfs_dirent **p_sd);
201 : :
202 : : int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
203 : : const char *new_name, const void *new_ns);
204 : :
205 : : static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
206 : : {
207 [ + - ][ + - ]: 6233 : if (sd) {
[ # # ][ + -
+ - + - ]
208 [ - + ][ - + ]: 6233 : WARN_ON(!atomic_read(&sd->s_count));
[ - + ][ - + ]
[ - + ]
209 : 6233 : atomic_inc(&sd->s_count);
210 : : }
211 : : return sd;
212 : : }
213 : : #define sysfs_get(sd) __sysfs_get(sd)
214 : :
215 : : static inline void __sysfs_put(struct sysfs_dirent *sd)
216 : : {
217 [ + - + + ]: 38974 : if (sd && atomic_dec_and_test(&sd->s_count))
[ - + # # ]
[ # # # # ]
[ + - - +
+ - - + ]
[ + - - + ]
[ + - - + ]
[ + - + + ]
[ + - - +
# # # # -
+ ][ + + ]
[ + + + + ]
[ + - - + ]
218 : 7776 : release_sysfs_dirent(sd);
219 : : }
220 : : #define sysfs_put(sd) __sysfs_put(sd)
221 : :
222 : : /*
223 : : * inode.c
224 : : */
225 : : struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
226 : : void sysfs_evict_inode(struct inode *inode);
227 : : int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
228 : : int sysfs_permission(struct inode *inode, int mask);
229 : : int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
230 : : int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
231 : : struct kstat *stat);
232 : : int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
233 : : size_t size, int flags);
234 : : int sysfs_inode_init(void);
235 : :
236 : : /*
237 : : * file.c
238 : : */
239 : : extern const struct file_operations sysfs_file_operations;
240 : : extern const struct file_operations sysfs_bin_operations;
241 : :
242 : : int sysfs_add_file(struct sysfs_dirent *dir_sd,
243 : : const struct attribute *attr, int type);
244 : :
245 : : int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
246 : : const struct attribute *attr, int type,
247 : : umode_t amode, const void *ns);
248 : : void sysfs_unmap_bin_file(struct sysfs_dirent *sd);
249 : :
250 : : /*
251 : : * symlink.c
252 : : */
253 : : extern const struct inode_operations sysfs_symlink_inode_operations;
254 : : int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target,
255 : : const char *name);
|