Commit faef2b6c9960b5ae288899f461a2218ec6bb7928
1 parent
5b91aca0bd
Exists in
master
and in
6 other branches
sysfs: propagate umode_t
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 4 changed files with 5 additions and 5 deletions Inline Diff
Documentation/filesystems/sysfs.txt
1 | 1 | ||
2 | sysfs - _The_ filesystem for exporting kernel objects. | 2 | sysfs - _The_ filesystem for exporting kernel objects. |
3 | 3 | ||
4 | Patrick Mochel <mochel@osdl.org> | 4 | Patrick Mochel <mochel@osdl.org> |
5 | Mike Murphy <mamurph@cs.clemson.edu> | 5 | Mike Murphy <mamurph@cs.clemson.edu> |
6 | 6 | ||
7 | Revised: 16 August 2011 | 7 | Revised: 16 August 2011 |
8 | Original: 10 January 2003 | 8 | Original: 10 January 2003 |
9 | 9 | ||
10 | 10 | ||
11 | What it is: | 11 | What it is: |
12 | ~~~~~~~~~~~ | 12 | ~~~~~~~~~~~ |
13 | 13 | ||
14 | sysfs is a ram-based filesystem initially based on ramfs. It provides | 14 | sysfs is a ram-based filesystem initially based on ramfs. It provides |
15 | a means to export kernel data structures, their attributes, and the | 15 | a means to export kernel data structures, their attributes, and the |
16 | linkages between them to userspace. | 16 | linkages between them to userspace. |
17 | 17 | ||
18 | sysfs is tied inherently to the kobject infrastructure. Please read | 18 | sysfs is tied inherently to the kobject infrastructure. Please read |
19 | Documentation/kobject.txt for more information concerning the kobject | 19 | Documentation/kobject.txt for more information concerning the kobject |
20 | interface. | 20 | interface. |
21 | 21 | ||
22 | 22 | ||
23 | Using sysfs | 23 | Using sysfs |
24 | ~~~~~~~~~~~ | 24 | ~~~~~~~~~~~ |
25 | 25 | ||
26 | sysfs is always compiled in if CONFIG_SYSFS is defined. You can access | 26 | sysfs is always compiled in if CONFIG_SYSFS is defined. You can access |
27 | it by doing: | 27 | it by doing: |
28 | 28 | ||
29 | mount -t sysfs sysfs /sys | 29 | mount -t sysfs sysfs /sys |
30 | 30 | ||
31 | 31 | ||
32 | Directory Creation | 32 | Directory Creation |
33 | ~~~~~~~~~~~~~~~~~~ | 33 | ~~~~~~~~~~~~~~~~~~ |
34 | 34 | ||
35 | For every kobject that is registered with the system, a directory is | 35 | For every kobject that is registered with the system, a directory is |
36 | created for it in sysfs. That directory is created as a subdirectory | 36 | created for it in sysfs. That directory is created as a subdirectory |
37 | of the kobject's parent, expressing internal object hierarchies to | 37 | of the kobject's parent, expressing internal object hierarchies to |
38 | userspace. Top-level directories in sysfs represent the common | 38 | userspace. Top-level directories in sysfs represent the common |
39 | ancestors of object hierarchies; i.e. the subsystems the objects | 39 | ancestors of object hierarchies; i.e. the subsystems the objects |
40 | belong to. | 40 | belong to. |
41 | 41 | ||
42 | Sysfs internally stores a pointer to the kobject that implements a | 42 | Sysfs internally stores a pointer to the kobject that implements a |
43 | directory in the sysfs_dirent object associated with the directory. In | 43 | directory in the sysfs_dirent object associated with the directory. In |
44 | the past this kobject pointer has been used by sysfs to do reference | 44 | the past this kobject pointer has been used by sysfs to do reference |
45 | counting directly on the kobject whenever the file is opened or closed. | 45 | counting directly on the kobject whenever the file is opened or closed. |
46 | With the current sysfs implementation the kobject reference count is | 46 | With the current sysfs implementation the kobject reference count is |
47 | only modified directly by the function sysfs_schedule_callback(). | 47 | only modified directly by the function sysfs_schedule_callback(). |
48 | 48 | ||
49 | 49 | ||
50 | Attributes | 50 | Attributes |
51 | ~~~~~~~~~~ | 51 | ~~~~~~~~~~ |
52 | 52 | ||
53 | Attributes can be exported for kobjects in the form of regular files in | 53 | Attributes can be exported for kobjects in the form of regular files in |
54 | the filesystem. Sysfs forwards file I/O operations to methods defined | 54 | the filesystem. Sysfs forwards file I/O operations to methods defined |
55 | for the attributes, providing a means to read and write kernel | 55 | for the attributes, providing a means to read and write kernel |
56 | attributes. | 56 | attributes. |
57 | 57 | ||
58 | Attributes should be ASCII text files, preferably with only one value | 58 | Attributes should be ASCII text files, preferably with only one value |
59 | per file. It is noted that it may not be efficient to contain only one | 59 | per file. It is noted that it may not be efficient to contain only one |
60 | value per file, so it is socially acceptable to express an array of | 60 | value per file, so it is socially acceptable to express an array of |
61 | values of the same type. | 61 | values of the same type. |
62 | 62 | ||
63 | Mixing types, expressing multiple lines of data, and doing fancy | 63 | Mixing types, expressing multiple lines of data, and doing fancy |
64 | formatting of data is heavily frowned upon. Doing these things may get | 64 | formatting of data is heavily frowned upon. Doing these things may get |
65 | you publicly humiliated and your code rewritten without notice. | 65 | you publicly humiliated and your code rewritten without notice. |
66 | 66 | ||
67 | 67 | ||
68 | An attribute definition is simply: | 68 | An attribute definition is simply: |
69 | 69 | ||
70 | struct attribute { | 70 | struct attribute { |
71 | char * name; | 71 | char * name; |
72 | struct module *owner; | 72 | struct module *owner; |
73 | mode_t mode; | 73 | umode_t mode; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | 76 | ||
77 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); | 77 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); |
78 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); | 78 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); |
79 | 79 | ||
80 | 80 | ||
81 | A bare attribute contains no means to read or write the value of the | 81 | A bare attribute contains no means to read or write the value of the |
82 | attribute. Subsystems are encouraged to define their own attribute | 82 | attribute. Subsystems are encouraged to define their own attribute |
83 | structure and wrapper functions for adding and removing attributes for | 83 | structure and wrapper functions for adding and removing attributes for |
84 | a specific object type. | 84 | a specific object type. |
85 | 85 | ||
86 | For example, the driver model defines struct device_attribute like: | 86 | For example, the driver model defines struct device_attribute like: |
87 | 87 | ||
88 | struct device_attribute { | 88 | struct device_attribute { |
89 | struct attribute attr; | 89 | struct attribute attr; |
90 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, | 90 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, |
91 | char *buf); | 91 | char *buf); |
92 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 92 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, |
93 | const char *buf, size_t count); | 93 | const char *buf, size_t count); |
94 | }; | 94 | }; |
95 | 95 | ||
96 | int device_create_file(struct device *, const struct device_attribute *); | 96 | int device_create_file(struct device *, const struct device_attribute *); |
97 | void device_remove_file(struct device *, const struct device_attribute *); | 97 | void device_remove_file(struct device *, const struct device_attribute *); |
98 | 98 | ||
99 | It also defines this helper for defining device attributes: | 99 | It also defines this helper for defining device attributes: |
100 | 100 | ||
101 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ | 101 | #define DEVICE_ATTR(_name, _mode, _show, _store) \ |
102 | struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) | 102 | struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) |
103 | 103 | ||
104 | For example, declaring | 104 | For example, declaring |
105 | 105 | ||
106 | static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); | 106 | static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); |
107 | 107 | ||
108 | is equivalent to doing: | 108 | is equivalent to doing: |
109 | 109 | ||
110 | static struct device_attribute dev_attr_foo = { | 110 | static struct device_attribute dev_attr_foo = { |
111 | .attr = { | 111 | .attr = { |
112 | .name = "foo", | 112 | .name = "foo", |
113 | .mode = S_IWUSR | S_IRUGO, | 113 | .mode = S_IWUSR | S_IRUGO, |
114 | .show = show_foo, | 114 | .show = show_foo, |
115 | .store = store_foo, | 115 | .store = store_foo, |
116 | }, | 116 | }, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | 119 | ||
120 | Subsystem-Specific Callbacks | 120 | Subsystem-Specific Callbacks |
121 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 121 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
122 | 122 | ||
123 | When a subsystem defines a new attribute type, it must implement a | 123 | When a subsystem defines a new attribute type, it must implement a |
124 | set of sysfs operations for forwarding read and write calls to the | 124 | set of sysfs operations for forwarding read and write calls to the |
125 | show and store methods of the attribute owners. | 125 | show and store methods of the attribute owners. |
126 | 126 | ||
127 | struct sysfs_ops { | 127 | struct sysfs_ops { |
128 | ssize_t (*show)(struct kobject *, struct attribute *, char *); | 128 | ssize_t (*show)(struct kobject *, struct attribute *, char *); |
129 | ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); | 129 | ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); |
130 | }; | 130 | }; |
131 | 131 | ||
132 | [ Subsystems should have already defined a struct kobj_type as a | 132 | [ Subsystems should have already defined a struct kobj_type as a |
133 | descriptor for this type, which is where the sysfs_ops pointer is | 133 | descriptor for this type, which is where the sysfs_ops pointer is |
134 | stored. See the kobject documentation for more information. ] | 134 | stored. See the kobject documentation for more information. ] |
135 | 135 | ||
136 | When a file is read or written, sysfs calls the appropriate method | 136 | When a file is read or written, sysfs calls the appropriate method |
137 | for the type. The method then translates the generic struct kobject | 137 | for the type. The method then translates the generic struct kobject |
138 | and struct attribute pointers to the appropriate pointer types, and | 138 | and struct attribute pointers to the appropriate pointer types, and |
139 | calls the associated methods. | 139 | calls the associated methods. |
140 | 140 | ||
141 | 141 | ||
142 | To illustrate: | 142 | To illustrate: |
143 | 143 | ||
144 | #define to_dev(obj) container_of(obj, struct device, kobj) | 144 | #define to_dev(obj) container_of(obj, struct device, kobj) |
145 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 145 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
146 | 146 | ||
147 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, | 147 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, |
148 | char *buf) | 148 | char *buf) |
149 | { | 149 | { |
150 | struct device_attribute *dev_attr = to_dev_attr(attr); | 150 | struct device_attribute *dev_attr = to_dev_attr(attr); |
151 | struct device *dev = to_dev(kobj); | 151 | struct device *dev = to_dev(kobj); |
152 | ssize_t ret = -EIO; | 152 | ssize_t ret = -EIO; |
153 | 153 | ||
154 | if (dev_attr->show) | 154 | if (dev_attr->show) |
155 | ret = dev_attr->show(dev, dev_attr, buf); | 155 | ret = dev_attr->show(dev, dev_attr, buf); |
156 | if (ret >= (ssize_t)PAGE_SIZE) { | 156 | if (ret >= (ssize_t)PAGE_SIZE) { |
157 | print_symbol("dev_attr_show: %s returned bad count\n", | 157 | print_symbol("dev_attr_show: %s returned bad count\n", |
158 | (unsigned long)dev_attr->show); | 158 | (unsigned long)dev_attr->show); |
159 | } | 159 | } |
160 | return ret; | 160 | return ret; |
161 | } | 161 | } |
162 | 162 | ||
163 | 163 | ||
164 | 164 | ||
165 | Reading/Writing Attribute Data | 165 | Reading/Writing Attribute Data |
166 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 166 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
167 | 167 | ||
168 | To read or write attributes, show() or store() methods must be | 168 | To read or write attributes, show() or store() methods must be |
169 | specified when declaring the attribute. The method types should be as | 169 | specified when declaring the attribute. The method types should be as |
170 | simple as those defined for device attributes: | 170 | simple as those defined for device attributes: |
171 | 171 | ||
172 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); | 172 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); |
173 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 173 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, |
174 | const char *buf, size_t count); | 174 | const char *buf, size_t count); |
175 | 175 | ||
176 | IOW, they should take only an object, an attribute, and a buffer as parameters. | 176 | IOW, they should take only an object, an attribute, and a buffer as parameters. |
177 | 177 | ||
178 | 178 | ||
179 | sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the | 179 | sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the |
180 | method. Sysfs will call the method exactly once for each read or | 180 | method. Sysfs will call the method exactly once for each read or |
181 | write. This forces the following behavior on the method | 181 | write. This forces the following behavior on the method |
182 | implementations: | 182 | implementations: |
183 | 183 | ||
184 | - On read(2), the show() method should fill the entire buffer. | 184 | - On read(2), the show() method should fill the entire buffer. |
185 | Recall that an attribute should only be exporting one value, or an | 185 | Recall that an attribute should only be exporting one value, or an |
186 | array of similar values, so this shouldn't be that expensive. | 186 | array of similar values, so this shouldn't be that expensive. |
187 | 187 | ||
188 | This allows userspace to do partial reads and forward seeks | 188 | This allows userspace to do partial reads and forward seeks |
189 | arbitrarily over the entire file at will. If userspace seeks back to | 189 | arbitrarily over the entire file at will. If userspace seeks back to |
190 | zero or does a pread(2) with an offset of '0' the show() method will | 190 | zero or does a pread(2) with an offset of '0' the show() method will |
191 | be called again, rearmed, to fill the buffer. | 191 | be called again, rearmed, to fill the buffer. |
192 | 192 | ||
193 | - On write(2), sysfs expects the entire buffer to be passed during the | 193 | - On write(2), sysfs expects the entire buffer to be passed during the |
194 | first write. Sysfs then passes the entire buffer to the store() | 194 | first write. Sysfs then passes the entire buffer to the store() |
195 | method. | 195 | method. |
196 | 196 | ||
197 | When writing sysfs files, userspace processes should first read the | 197 | When writing sysfs files, userspace processes should first read the |
198 | entire file, modify the values it wishes to change, then write the | 198 | entire file, modify the values it wishes to change, then write the |
199 | entire buffer back. | 199 | entire buffer back. |
200 | 200 | ||
201 | Attribute method implementations should operate on an identical | 201 | Attribute method implementations should operate on an identical |
202 | buffer when reading and writing values. | 202 | buffer when reading and writing values. |
203 | 203 | ||
204 | Other notes: | 204 | Other notes: |
205 | 205 | ||
206 | - Writing causes the show() method to be rearmed regardless of current | 206 | - Writing causes the show() method to be rearmed regardless of current |
207 | file position. | 207 | file position. |
208 | 208 | ||
209 | - The buffer will always be PAGE_SIZE bytes in length. On i386, this | 209 | - The buffer will always be PAGE_SIZE bytes in length. On i386, this |
210 | is 4096. | 210 | is 4096. |
211 | 211 | ||
212 | - show() methods should return the number of bytes printed into the | 212 | - show() methods should return the number of bytes printed into the |
213 | buffer. This is the return value of scnprintf(). | 213 | buffer. This is the return value of scnprintf(). |
214 | 214 | ||
215 | - show() should always use scnprintf(). | 215 | - show() should always use scnprintf(). |
216 | 216 | ||
217 | - store() should return the number of bytes used from the buffer. If the | 217 | - store() should return the number of bytes used from the buffer. If the |
218 | entire buffer has been used, just return the count argument. | 218 | entire buffer has been used, just return the count argument. |
219 | 219 | ||
220 | - show() or store() can always return errors. If a bad value comes | 220 | - show() or store() can always return errors. If a bad value comes |
221 | through, be sure to return an error. | 221 | through, be sure to return an error. |
222 | 222 | ||
223 | - The object passed to the methods will be pinned in memory via sysfs | 223 | - The object passed to the methods will be pinned in memory via sysfs |
224 | referencing counting its embedded object. However, the physical | 224 | referencing counting its embedded object. However, the physical |
225 | entity (e.g. device) the object represents may not be present. Be | 225 | entity (e.g. device) the object represents may not be present. Be |
226 | sure to have a way to check this, if necessary. | 226 | sure to have a way to check this, if necessary. |
227 | 227 | ||
228 | 228 | ||
229 | A very simple (and naive) implementation of a device attribute is: | 229 | A very simple (and naive) implementation of a device attribute is: |
230 | 230 | ||
231 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, | 231 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, |
232 | char *buf) | 232 | char *buf) |
233 | { | 233 | { |
234 | return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); | 234 | return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); |
235 | } | 235 | } |
236 | 236 | ||
237 | static ssize_t store_name(struct device *dev, struct device_attribute *attr, | 237 | static ssize_t store_name(struct device *dev, struct device_attribute *attr, |
238 | const char *buf, size_t count) | 238 | const char *buf, size_t count) |
239 | { | 239 | { |
240 | snprintf(dev->name, sizeof(dev->name), "%.*s", | 240 | snprintf(dev->name, sizeof(dev->name), "%.*s", |
241 | (int)min(count, sizeof(dev->name) - 1), buf); | 241 | (int)min(count, sizeof(dev->name) - 1), buf); |
242 | return count; | 242 | return count; |
243 | } | 243 | } |
244 | 244 | ||
245 | static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); | 245 | static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); |
246 | 246 | ||
247 | 247 | ||
248 | (Note that the real implementation doesn't allow userspace to set the | 248 | (Note that the real implementation doesn't allow userspace to set the |
249 | name for a device.) | 249 | name for a device.) |
250 | 250 | ||
251 | 251 | ||
252 | Top Level Directory Layout | 252 | Top Level Directory Layout |
253 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 253 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
254 | 254 | ||
255 | The sysfs directory arrangement exposes the relationship of kernel | 255 | The sysfs directory arrangement exposes the relationship of kernel |
256 | data structures. | 256 | data structures. |
257 | 257 | ||
258 | The top level sysfs directory looks like: | 258 | The top level sysfs directory looks like: |
259 | 259 | ||
260 | block/ | 260 | block/ |
261 | bus/ | 261 | bus/ |
262 | class/ | 262 | class/ |
263 | dev/ | 263 | dev/ |
264 | devices/ | 264 | devices/ |
265 | firmware/ | 265 | firmware/ |
266 | net/ | 266 | net/ |
267 | fs/ | 267 | fs/ |
268 | 268 | ||
269 | devices/ contains a filesystem representation of the device tree. It maps | 269 | devices/ contains a filesystem representation of the device tree. It maps |
270 | directly to the internal kernel device tree, which is a hierarchy of | 270 | directly to the internal kernel device tree, which is a hierarchy of |
271 | struct device. | 271 | struct device. |
272 | 272 | ||
273 | bus/ contains flat directory layout of the various bus types in the | 273 | bus/ contains flat directory layout of the various bus types in the |
274 | kernel. Each bus's directory contains two subdirectories: | 274 | kernel. Each bus's directory contains two subdirectories: |
275 | 275 | ||
276 | devices/ | 276 | devices/ |
277 | drivers/ | 277 | drivers/ |
278 | 278 | ||
279 | devices/ contains symlinks for each device discovered in the system | 279 | devices/ contains symlinks for each device discovered in the system |
280 | that point to the device's directory under root/. | 280 | that point to the device's directory under root/. |
281 | 281 | ||
282 | drivers/ contains a directory for each device driver that is loaded | 282 | drivers/ contains a directory for each device driver that is loaded |
283 | for devices on that particular bus (this assumes that drivers do not | 283 | for devices on that particular bus (this assumes that drivers do not |
284 | span multiple bus types). | 284 | span multiple bus types). |
285 | 285 | ||
286 | fs/ contains a directory for some filesystems. Currently each | 286 | fs/ contains a directory for some filesystems. Currently each |
287 | filesystem wanting to export attributes must create its own hierarchy | 287 | filesystem wanting to export attributes must create its own hierarchy |
288 | below fs/ (see ./fuse.txt for an example). | 288 | below fs/ (see ./fuse.txt for an example). |
289 | 289 | ||
290 | dev/ contains two directories char/ and block/. Inside these two | 290 | dev/ contains two directories char/ and block/. Inside these two |
291 | directories there are symlinks named <major>:<minor>. These symlinks | 291 | directories there are symlinks named <major>:<minor>. These symlinks |
292 | point to the sysfs directory for the given device. /sys/dev provides a | 292 | point to the sysfs directory for the given device. /sys/dev provides a |
293 | quick way to lookup the sysfs interface for a device from the result of | 293 | quick way to lookup the sysfs interface for a device from the result of |
294 | a stat(2) operation. | 294 | a stat(2) operation. |
295 | 295 | ||
296 | More information can driver-model specific features can be found in | 296 | More information can driver-model specific features can be found in |
297 | Documentation/driver-model/. | 297 | Documentation/driver-model/. |
298 | 298 | ||
299 | 299 | ||
300 | TODO: Finish this section. | 300 | TODO: Finish this section. |
301 | 301 | ||
302 | 302 | ||
303 | Current Interfaces | 303 | Current Interfaces |
304 | ~~~~~~~~~~~~~~~~~~ | 304 | ~~~~~~~~~~~~~~~~~~ |
305 | 305 | ||
306 | The following interface layers currently exist in sysfs: | 306 | The following interface layers currently exist in sysfs: |
307 | 307 | ||
308 | 308 | ||
309 | - devices (include/linux/device.h) | 309 | - devices (include/linux/device.h) |
310 | ---------------------------------- | 310 | ---------------------------------- |
311 | Structure: | 311 | Structure: |
312 | 312 | ||
313 | struct device_attribute { | 313 | struct device_attribute { |
314 | struct attribute attr; | 314 | struct attribute attr; |
315 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, | 315 | ssize_t (*show)(struct device *dev, struct device_attribute *attr, |
316 | char *buf); | 316 | char *buf); |
317 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, | 317 | ssize_t (*store)(struct device *dev, struct device_attribute *attr, |
318 | const char *buf, size_t count); | 318 | const char *buf, size_t count); |
319 | }; | 319 | }; |
320 | 320 | ||
321 | Declaring: | 321 | Declaring: |
322 | 322 | ||
323 | DEVICE_ATTR(_name, _mode, _show, _store); | 323 | DEVICE_ATTR(_name, _mode, _show, _store); |
324 | 324 | ||
325 | Creation/Removal: | 325 | Creation/Removal: |
326 | 326 | ||
327 | int device_create_file(struct device *dev, const struct device_attribute * attr); | 327 | int device_create_file(struct device *dev, const struct device_attribute * attr); |
328 | void device_remove_file(struct device *dev, const struct device_attribute * attr); | 328 | void device_remove_file(struct device *dev, const struct device_attribute * attr); |
329 | 329 | ||
330 | 330 | ||
331 | - bus drivers (include/linux/device.h) | 331 | - bus drivers (include/linux/device.h) |
332 | -------------------------------------- | 332 | -------------------------------------- |
333 | Structure: | 333 | Structure: |
334 | 334 | ||
335 | struct bus_attribute { | 335 | struct bus_attribute { |
336 | struct attribute attr; | 336 | struct attribute attr; |
337 | ssize_t (*show)(struct bus_type *, char * buf); | 337 | ssize_t (*show)(struct bus_type *, char * buf); |
338 | ssize_t (*store)(struct bus_type *, const char * buf, size_t count); | 338 | ssize_t (*store)(struct bus_type *, const char * buf, size_t count); |
339 | }; | 339 | }; |
340 | 340 | ||
341 | Declaring: | 341 | Declaring: |
342 | 342 | ||
343 | BUS_ATTR(_name, _mode, _show, _store) | 343 | BUS_ATTR(_name, _mode, _show, _store) |
344 | 344 | ||
345 | Creation/Removal: | 345 | Creation/Removal: |
346 | 346 | ||
347 | int bus_create_file(struct bus_type *, struct bus_attribute *); | 347 | int bus_create_file(struct bus_type *, struct bus_attribute *); |
348 | void bus_remove_file(struct bus_type *, struct bus_attribute *); | 348 | void bus_remove_file(struct bus_type *, struct bus_attribute *); |
349 | 349 | ||
350 | 350 | ||
351 | - device drivers (include/linux/device.h) | 351 | - device drivers (include/linux/device.h) |
352 | ----------------------------------------- | 352 | ----------------------------------------- |
353 | 353 | ||
354 | Structure: | 354 | Structure: |
355 | 355 | ||
356 | struct driver_attribute { | 356 | struct driver_attribute { |
357 | struct attribute attr; | 357 | struct attribute attr; |
358 | ssize_t (*show)(struct device_driver *, char * buf); | 358 | ssize_t (*show)(struct device_driver *, char * buf); |
359 | ssize_t (*store)(struct device_driver *, const char * buf, | 359 | ssize_t (*store)(struct device_driver *, const char * buf, |
360 | size_t count); | 360 | size_t count); |
361 | }; | 361 | }; |
362 | 362 | ||
363 | Declaring: | 363 | Declaring: |
364 | 364 | ||
365 | DRIVER_ATTR(_name, _mode, _show, _store) | 365 | DRIVER_ATTR(_name, _mode, _show, _store) |
366 | 366 | ||
367 | Creation/Removal: | 367 | Creation/Removal: |
368 | 368 | ||
369 | int driver_create_file(struct device_driver *, const struct driver_attribute *); | 369 | int driver_create_file(struct device_driver *, const struct driver_attribute *); |
370 | void driver_remove_file(struct device_driver *, const struct driver_attribute *); | 370 | void driver_remove_file(struct device_driver *, const struct driver_attribute *); |
371 | 371 | ||
372 | 372 | ||
373 | Documentation | 373 | Documentation |
374 | ~~~~~~~~~~~~~ | 374 | ~~~~~~~~~~~~~ |
375 | 375 | ||
376 | The sysfs directory structure and the attributes in each directory define an | 376 | The sysfs directory structure and the attributes in each directory define an |
377 | ABI between the kernel and user space. As for any ABI, it is important that | 377 | ABI between the kernel and user space. As for any ABI, it is important that |
378 | this ABI is stable and properly documented. All new sysfs attributes must be | 378 | this ABI is stable and properly documented. All new sysfs attributes must be |
379 | documented in Documentation/ABI. See also Documentation/ABI/README for more | 379 | documented in Documentation/ABI. See also Documentation/ABI/README for more |
380 | information. | 380 | information. |
381 | 381 |
fs/sysfs/file.c
1 | /* | 1 | /* |
2 | * fs/sysfs/file.c - sysfs regular (text) file implementation | 2 | * fs/sysfs/file.c - sysfs regular (text) file implementation |
3 | * | 3 | * |
4 | * Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
5 | * Copyright (c) 2007 SUSE Linux Products GmbH | 5 | * Copyright (c) 2007 SUSE Linux Products GmbH |
6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> |
7 | * | 7 | * |
8 | * This file is released under the GPLv2. | 8 | * This file is released under the GPLv2. |
9 | * | 9 | * |
10 | * Please see Documentation/filesystems/sysfs.txt for more information. | 10 | * Please see Documentation/filesystems/sysfs.txt for more information. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
15 | #include <linux/kallsyms.h> | 15 | #include <linux/kallsyms.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/fsnotify.h> | 17 | #include <linux/fsnotify.h> |
18 | #include <linux/namei.h> | 18 | #include <linux/namei.h> |
19 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/limits.h> | 22 | #include <linux/limits.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | 24 | ||
25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * There's one sysfs_buffer for each open file and one | 28 | * There's one sysfs_buffer for each open file and one |
29 | * sysfs_open_dirent for each sysfs_dirent with one or more open | 29 | * sysfs_open_dirent for each sysfs_dirent with one or more open |
30 | * files. | 30 | * files. |
31 | * | 31 | * |
32 | * filp->private_data points to sysfs_buffer and | 32 | * filp->private_data points to sysfs_buffer and |
33 | * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open | 33 | * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open |
34 | * is protected by sysfs_open_dirent_lock. | 34 | * is protected by sysfs_open_dirent_lock. |
35 | */ | 35 | */ |
36 | static DEFINE_SPINLOCK(sysfs_open_dirent_lock); | 36 | static DEFINE_SPINLOCK(sysfs_open_dirent_lock); |
37 | 37 | ||
38 | struct sysfs_open_dirent { | 38 | struct sysfs_open_dirent { |
39 | atomic_t refcnt; | 39 | atomic_t refcnt; |
40 | atomic_t event; | 40 | atomic_t event; |
41 | wait_queue_head_t poll; | 41 | wait_queue_head_t poll; |
42 | struct list_head buffers; /* goes through sysfs_buffer.list */ | 42 | struct list_head buffers; /* goes through sysfs_buffer.list */ |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct sysfs_buffer { | 45 | struct sysfs_buffer { |
46 | size_t count; | 46 | size_t count; |
47 | loff_t pos; | 47 | loff_t pos; |
48 | char * page; | 48 | char * page; |
49 | const struct sysfs_ops * ops; | 49 | const struct sysfs_ops * ops; |
50 | struct mutex mutex; | 50 | struct mutex mutex; |
51 | int needs_read_fill; | 51 | int needs_read_fill; |
52 | int event; | 52 | int event; |
53 | struct list_head list; | 53 | struct list_head list; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * fill_read_buffer - allocate and fill buffer from object. | 57 | * fill_read_buffer - allocate and fill buffer from object. |
58 | * @dentry: dentry pointer. | 58 | * @dentry: dentry pointer. |
59 | * @buffer: data buffer for file. | 59 | * @buffer: data buffer for file. |
60 | * | 60 | * |
61 | * Allocate @buffer->page, if it hasn't been already, then call the | 61 | * Allocate @buffer->page, if it hasn't been already, then call the |
62 | * kobject's show() method to fill the buffer with this attribute's | 62 | * kobject's show() method to fill the buffer with this attribute's |
63 | * data. | 63 | * data. |
64 | * This is called only once, on the file's first read unless an error | 64 | * This is called only once, on the file's first read unless an error |
65 | * is returned. | 65 | * is returned. |
66 | */ | 66 | */ |
67 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) | 67 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) |
68 | { | 68 | { |
69 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 69 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
70 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 70 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
71 | const struct sysfs_ops * ops = buffer->ops; | 71 | const struct sysfs_ops * ops = buffer->ops; |
72 | int ret = 0; | 72 | int ret = 0; |
73 | ssize_t count; | 73 | ssize_t count; |
74 | 74 | ||
75 | if (!buffer->page) | 75 | if (!buffer->page) |
76 | buffer->page = (char *) get_zeroed_page(GFP_KERNEL); | 76 | buffer->page = (char *) get_zeroed_page(GFP_KERNEL); |
77 | if (!buffer->page) | 77 | if (!buffer->page) |
78 | return -ENOMEM; | 78 | return -ENOMEM; |
79 | 79 | ||
80 | /* need attr_sd for attr and ops, its parent for kobj */ | 80 | /* need attr_sd for attr and ops, its parent for kobj */ |
81 | if (!sysfs_get_active(attr_sd)) | 81 | if (!sysfs_get_active(attr_sd)) |
82 | return -ENODEV; | 82 | return -ENODEV; |
83 | 83 | ||
84 | buffer->event = atomic_read(&attr_sd->s_attr.open->event); | 84 | buffer->event = atomic_read(&attr_sd->s_attr.open->event); |
85 | count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); | 85 | count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); |
86 | 86 | ||
87 | sysfs_put_active(attr_sd); | 87 | sysfs_put_active(attr_sd); |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * The code works fine with PAGE_SIZE return but it's likely to | 90 | * The code works fine with PAGE_SIZE return but it's likely to |
91 | * indicate truncated result or overflow in normal use cases. | 91 | * indicate truncated result or overflow in normal use cases. |
92 | */ | 92 | */ |
93 | if (count >= (ssize_t)PAGE_SIZE) { | 93 | if (count >= (ssize_t)PAGE_SIZE) { |
94 | print_symbol("fill_read_buffer: %s returned bad count\n", | 94 | print_symbol("fill_read_buffer: %s returned bad count\n", |
95 | (unsigned long)ops->show); | 95 | (unsigned long)ops->show); |
96 | /* Try to struggle along */ | 96 | /* Try to struggle along */ |
97 | count = PAGE_SIZE - 1; | 97 | count = PAGE_SIZE - 1; |
98 | } | 98 | } |
99 | if (count >= 0) { | 99 | if (count >= 0) { |
100 | buffer->needs_read_fill = 0; | 100 | buffer->needs_read_fill = 0; |
101 | buffer->count = count; | 101 | buffer->count = count; |
102 | } else { | 102 | } else { |
103 | ret = count; | 103 | ret = count; |
104 | } | 104 | } |
105 | return ret; | 105 | return ret; |
106 | } | 106 | } |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * sysfs_read_file - read an attribute. | 109 | * sysfs_read_file - read an attribute. |
110 | * @file: file pointer. | 110 | * @file: file pointer. |
111 | * @buf: buffer to fill. | 111 | * @buf: buffer to fill. |
112 | * @count: number of bytes to read. | 112 | * @count: number of bytes to read. |
113 | * @ppos: starting offset in file. | 113 | * @ppos: starting offset in file. |
114 | * | 114 | * |
115 | * Userspace wants to read an attribute file. The attribute descriptor | 115 | * Userspace wants to read an attribute file. The attribute descriptor |
116 | * is in the file's ->d_fsdata. The target object is in the directory's | 116 | * is in the file's ->d_fsdata. The target object is in the directory's |
117 | * ->d_fsdata. | 117 | * ->d_fsdata. |
118 | * | 118 | * |
119 | * We call fill_read_buffer() to allocate and fill the buffer from the | 119 | * We call fill_read_buffer() to allocate and fill the buffer from the |
120 | * object's show() method exactly once (if the read is happening from | 120 | * object's show() method exactly once (if the read is happening from |
121 | * the beginning of the file). That should fill the entire buffer with | 121 | * the beginning of the file). That should fill the entire buffer with |
122 | * all the data the object has to offer for that attribute. | 122 | * all the data the object has to offer for that attribute. |
123 | * We then call flush_read_buffer() to copy the buffer to userspace | 123 | * We then call flush_read_buffer() to copy the buffer to userspace |
124 | * in the increments specified. | 124 | * in the increments specified. |
125 | */ | 125 | */ |
126 | 126 | ||
127 | static ssize_t | 127 | static ssize_t |
128 | sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 128 | sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
129 | { | 129 | { |
130 | struct sysfs_buffer * buffer = file->private_data; | 130 | struct sysfs_buffer * buffer = file->private_data; |
131 | ssize_t retval = 0; | 131 | ssize_t retval = 0; |
132 | 132 | ||
133 | mutex_lock(&buffer->mutex); | 133 | mutex_lock(&buffer->mutex); |
134 | if (buffer->needs_read_fill || *ppos == 0) { | 134 | if (buffer->needs_read_fill || *ppos == 0) { |
135 | retval = fill_read_buffer(file->f_path.dentry,buffer); | 135 | retval = fill_read_buffer(file->f_path.dentry,buffer); |
136 | if (retval) | 136 | if (retval) |
137 | goto out; | 137 | goto out; |
138 | } | 138 | } |
139 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", | 139 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", |
140 | __func__, count, *ppos, buffer->page); | 140 | __func__, count, *ppos, buffer->page); |
141 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, | 141 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, |
142 | buffer->count); | 142 | buffer->count); |
143 | out: | 143 | out: |
144 | mutex_unlock(&buffer->mutex); | 144 | mutex_unlock(&buffer->mutex); |
145 | return retval; | 145 | return retval; |
146 | } | 146 | } |
147 | 147 | ||
148 | /** | 148 | /** |
149 | * fill_write_buffer - copy buffer from userspace. | 149 | * fill_write_buffer - copy buffer from userspace. |
150 | * @buffer: data buffer for file. | 150 | * @buffer: data buffer for file. |
151 | * @buf: data from user. | 151 | * @buf: data from user. |
152 | * @count: number of bytes in @userbuf. | 152 | * @count: number of bytes in @userbuf. |
153 | * | 153 | * |
154 | * Allocate @buffer->page if it hasn't been already, then | 154 | * Allocate @buffer->page if it hasn't been already, then |
155 | * copy the user-supplied buffer into it. | 155 | * copy the user-supplied buffer into it. |
156 | */ | 156 | */ |
157 | 157 | ||
158 | static int | 158 | static int |
159 | fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count) | 159 | fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count) |
160 | { | 160 | { |
161 | int error; | 161 | int error; |
162 | 162 | ||
163 | if (!buffer->page) | 163 | if (!buffer->page) |
164 | buffer->page = (char *)get_zeroed_page(GFP_KERNEL); | 164 | buffer->page = (char *)get_zeroed_page(GFP_KERNEL); |
165 | if (!buffer->page) | 165 | if (!buffer->page) |
166 | return -ENOMEM; | 166 | return -ENOMEM; |
167 | 167 | ||
168 | if (count >= PAGE_SIZE) | 168 | if (count >= PAGE_SIZE) |
169 | count = PAGE_SIZE - 1; | 169 | count = PAGE_SIZE - 1; |
170 | error = copy_from_user(buffer->page,buf,count); | 170 | error = copy_from_user(buffer->page,buf,count); |
171 | buffer->needs_read_fill = 1; | 171 | buffer->needs_read_fill = 1; |
172 | /* if buf is assumed to contain a string, terminate it by \0, | 172 | /* if buf is assumed to contain a string, terminate it by \0, |
173 | so e.g. sscanf() can scan the string easily */ | 173 | so e.g. sscanf() can scan the string easily */ |
174 | buffer->page[count] = 0; | 174 | buffer->page[count] = 0; |
175 | return error ? -EFAULT : count; | 175 | return error ? -EFAULT : count; |
176 | } | 176 | } |
177 | 177 | ||
178 | 178 | ||
179 | /** | 179 | /** |
180 | * flush_write_buffer - push buffer to kobject. | 180 | * flush_write_buffer - push buffer to kobject. |
181 | * @dentry: dentry to the attribute | 181 | * @dentry: dentry to the attribute |
182 | * @buffer: data buffer for file. | 182 | * @buffer: data buffer for file. |
183 | * @count: number of bytes | 183 | * @count: number of bytes |
184 | * | 184 | * |
185 | * Get the correct pointers for the kobject and the attribute we're | 185 | * Get the correct pointers for the kobject and the attribute we're |
186 | * dealing with, then call the store() method for the attribute, | 186 | * dealing with, then call the store() method for the attribute, |
187 | * passing the buffer that we acquired in fill_write_buffer(). | 187 | * passing the buffer that we acquired in fill_write_buffer(). |
188 | */ | 188 | */ |
189 | 189 | ||
190 | static int | 190 | static int |
191 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) | 191 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) |
192 | { | 192 | { |
193 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 193 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
194 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 194 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
195 | const struct sysfs_ops * ops = buffer->ops; | 195 | const struct sysfs_ops * ops = buffer->ops; |
196 | int rc; | 196 | int rc; |
197 | 197 | ||
198 | /* need attr_sd for attr and ops, its parent for kobj */ | 198 | /* need attr_sd for attr and ops, its parent for kobj */ |
199 | if (!sysfs_get_active(attr_sd)) | 199 | if (!sysfs_get_active(attr_sd)) |
200 | return -ENODEV; | 200 | return -ENODEV; |
201 | 201 | ||
202 | rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); | 202 | rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); |
203 | 203 | ||
204 | sysfs_put_active(attr_sd); | 204 | sysfs_put_active(attr_sd); |
205 | 205 | ||
206 | return rc; | 206 | return rc; |
207 | } | 207 | } |
208 | 208 | ||
209 | 209 | ||
210 | /** | 210 | /** |
211 | * sysfs_write_file - write an attribute. | 211 | * sysfs_write_file - write an attribute. |
212 | * @file: file pointer | 212 | * @file: file pointer |
213 | * @buf: data to write | 213 | * @buf: data to write |
214 | * @count: number of bytes | 214 | * @count: number of bytes |
215 | * @ppos: starting offset | 215 | * @ppos: starting offset |
216 | * | 216 | * |
217 | * Similar to sysfs_read_file(), though working in the opposite direction. | 217 | * Similar to sysfs_read_file(), though working in the opposite direction. |
218 | * We allocate and fill the data from the user in fill_write_buffer(), | 218 | * We allocate and fill the data from the user in fill_write_buffer(), |
219 | * then push it to the kobject in flush_write_buffer(). | 219 | * then push it to the kobject in flush_write_buffer(). |
220 | * There is no easy way for us to know if userspace is only doing a partial | 220 | * There is no easy way for us to know if userspace is only doing a partial |
221 | * write, so we don't support them. We expect the entire buffer to come | 221 | * write, so we don't support them. We expect the entire buffer to come |
222 | * on the first write. | 222 | * on the first write. |
223 | * Hint: if you're writing a value, first read the file, modify only the | 223 | * Hint: if you're writing a value, first read the file, modify only the |
224 | * the value you're changing, then write entire buffer back. | 224 | * the value you're changing, then write entire buffer back. |
225 | */ | 225 | */ |
226 | 226 | ||
227 | static ssize_t | 227 | static ssize_t |
228 | sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 228 | sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) |
229 | { | 229 | { |
230 | struct sysfs_buffer * buffer = file->private_data; | 230 | struct sysfs_buffer * buffer = file->private_data; |
231 | ssize_t len; | 231 | ssize_t len; |
232 | 232 | ||
233 | mutex_lock(&buffer->mutex); | 233 | mutex_lock(&buffer->mutex); |
234 | len = fill_write_buffer(buffer, buf, count); | 234 | len = fill_write_buffer(buffer, buf, count); |
235 | if (len > 0) | 235 | if (len > 0) |
236 | len = flush_write_buffer(file->f_path.dentry, buffer, len); | 236 | len = flush_write_buffer(file->f_path.dentry, buffer, len); |
237 | if (len > 0) | 237 | if (len > 0) |
238 | *ppos += len; | 238 | *ppos += len; |
239 | mutex_unlock(&buffer->mutex); | 239 | mutex_unlock(&buffer->mutex); |
240 | return len; | 240 | return len; |
241 | } | 241 | } |
242 | 242 | ||
243 | /** | 243 | /** |
244 | * sysfs_get_open_dirent - get or create sysfs_open_dirent | 244 | * sysfs_get_open_dirent - get or create sysfs_open_dirent |
245 | * @sd: target sysfs_dirent | 245 | * @sd: target sysfs_dirent |
246 | * @buffer: sysfs_buffer for this instance of open | 246 | * @buffer: sysfs_buffer for this instance of open |
247 | * | 247 | * |
248 | * If @sd->s_attr.open exists, increment its reference count; | 248 | * If @sd->s_attr.open exists, increment its reference count; |
249 | * otherwise, create one. @buffer is chained to the buffers | 249 | * otherwise, create one. @buffer is chained to the buffers |
250 | * list. | 250 | * list. |
251 | * | 251 | * |
252 | * LOCKING: | 252 | * LOCKING: |
253 | * Kernel thread context (may sleep). | 253 | * Kernel thread context (may sleep). |
254 | * | 254 | * |
255 | * RETURNS: | 255 | * RETURNS: |
256 | * 0 on success, -errno on failure. | 256 | * 0 on success, -errno on failure. |
257 | */ | 257 | */ |
258 | static int sysfs_get_open_dirent(struct sysfs_dirent *sd, | 258 | static int sysfs_get_open_dirent(struct sysfs_dirent *sd, |
259 | struct sysfs_buffer *buffer) | 259 | struct sysfs_buffer *buffer) |
260 | { | 260 | { |
261 | struct sysfs_open_dirent *od, *new_od = NULL; | 261 | struct sysfs_open_dirent *od, *new_od = NULL; |
262 | 262 | ||
263 | retry: | 263 | retry: |
264 | spin_lock_irq(&sysfs_open_dirent_lock); | 264 | spin_lock_irq(&sysfs_open_dirent_lock); |
265 | 265 | ||
266 | if (!sd->s_attr.open && new_od) { | 266 | if (!sd->s_attr.open && new_od) { |
267 | sd->s_attr.open = new_od; | 267 | sd->s_attr.open = new_od; |
268 | new_od = NULL; | 268 | new_od = NULL; |
269 | } | 269 | } |
270 | 270 | ||
271 | od = sd->s_attr.open; | 271 | od = sd->s_attr.open; |
272 | if (od) { | 272 | if (od) { |
273 | atomic_inc(&od->refcnt); | 273 | atomic_inc(&od->refcnt); |
274 | list_add_tail(&buffer->list, &od->buffers); | 274 | list_add_tail(&buffer->list, &od->buffers); |
275 | } | 275 | } |
276 | 276 | ||
277 | spin_unlock_irq(&sysfs_open_dirent_lock); | 277 | spin_unlock_irq(&sysfs_open_dirent_lock); |
278 | 278 | ||
279 | if (od) { | 279 | if (od) { |
280 | kfree(new_od); | 280 | kfree(new_od); |
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | /* not there, initialize a new one and retry */ | 284 | /* not there, initialize a new one and retry */ |
285 | new_od = kmalloc(sizeof(*new_od), GFP_KERNEL); | 285 | new_od = kmalloc(sizeof(*new_od), GFP_KERNEL); |
286 | if (!new_od) | 286 | if (!new_od) |
287 | return -ENOMEM; | 287 | return -ENOMEM; |
288 | 288 | ||
289 | atomic_set(&new_od->refcnt, 0); | 289 | atomic_set(&new_od->refcnt, 0); |
290 | atomic_set(&new_od->event, 1); | 290 | atomic_set(&new_od->event, 1); |
291 | init_waitqueue_head(&new_od->poll); | 291 | init_waitqueue_head(&new_od->poll); |
292 | INIT_LIST_HEAD(&new_od->buffers); | 292 | INIT_LIST_HEAD(&new_od->buffers); |
293 | goto retry; | 293 | goto retry; |
294 | } | 294 | } |
295 | 295 | ||
296 | /** | 296 | /** |
297 | * sysfs_put_open_dirent - put sysfs_open_dirent | 297 | * sysfs_put_open_dirent - put sysfs_open_dirent |
298 | * @sd: target sysfs_dirent | 298 | * @sd: target sysfs_dirent |
299 | * @buffer: associated sysfs_buffer | 299 | * @buffer: associated sysfs_buffer |
300 | * | 300 | * |
301 | * Put @sd->s_attr.open and unlink @buffer from the buffers list. | 301 | * Put @sd->s_attr.open and unlink @buffer from the buffers list. |
302 | * If reference count reaches zero, disassociate and free it. | 302 | * If reference count reaches zero, disassociate and free it. |
303 | * | 303 | * |
304 | * LOCKING: | 304 | * LOCKING: |
305 | * None. | 305 | * None. |
306 | */ | 306 | */ |
307 | static void sysfs_put_open_dirent(struct sysfs_dirent *sd, | 307 | static void sysfs_put_open_dirent(struct sysfs_dirent *sd, |
308 | struct sysfs_buffer *buffer) | 308 | struct sysfs_buffer *buffer) |
309 | { | 309 | { |
310 | struct sysfs_open_dirent *od = sd->s_attr.open; | 310 | struct sysfs_open_dirent *od = sd->s_attr.open; |
311 | unsigned long flags; | 311 | unsigned long flags; |
312 | 312 | ||
313 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); | 313 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); |
314 | 314 | ||
315 | list_del(&buffer->list); | 315 | list_del(&buffer->list); |
316 | if (atomic_dec_and_test(&od->refcnt)) | 316 | if (atomic_dec_and_test(&od->refcnt)) |
317 | sd->s_attr.open = NULL; | 317 | sd->s_attr.open = NULL; |
318 | else | 318 | else |
319 | od = NULL; | 319 | od = NULL; |
320 | 320 | ||
321 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); | 321 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); |
322 | 322 | ||
323 | kfree(od); | 323 | kfree(od); |
324 | } | 324 | } |
325 | 325 | ||
326 | static int sysfs_open_file(struct inode *inode, struct file *file) | 326 | static int sysfs_open_file(struct inode *inode, struct file *file) |
327 | { | 327 | { |
328 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 328 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
329 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 329 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
330 | struct sysfs_buffer *buffer; | 330 | struct sysfs_buffer *buffer; |
331 | const struct sysfs_ops *ops; | 331 | const struct sysfs_ops *ops; |
332 | int error = -EACCES; | 332 | int error = -EACCES; |
333 | 333 | ||
334 | /* need attr_sd for attr and ops, its parent for kobj */ | 334 | /* need attr_sd for attr and ops, its parent for kobj */ |
335 | if (!sysfs_get_active(attr_sd)) | 335 | if (!sysfs_get_active(attr_sd)) |
336 | return -ENODEV; | 336 | return -ENODEV; |
337 | 337 | ||
338 | /* every kobject with an attribute needs a ktype assigned */ | 338 | /* every kobject with an attribute needs a ktype assigned */ |
339 | if (kobj->ktype && kobj->ktype->sysfs_ops) | 339 | if (kobj->ktype && kobj->ktype->sysfs_ops) |
340 | ops = kobj->ktype->sysfs_ops; | 340 | ops = kobj->ktype->sysfs_ops; |
341 | else { | 341 | else { |
342 | WARN(1, KERN_ERR "missing sysfs attribute operations for " | 342 | WARN(1, KERN_ERR "missing sysfs attribute operations for " |
343 | "kobject: %s\n", kobject_name(kobj)); | 343 | "kobject: %s\n", kobject_name(kobj)); |
344 | goto err_out; | 344 | goto err_out; |
345 | } | 345 | } |
346 | 346 | ||
347 | /* File needs write support. | 347 | /* File needs write support. |
348 | * The inode's perms must say it's ok, | 348 | * The inode's perms must say it's ok, |
349 | * and we must have a store method. | 349 | * and we must have a store method. |
350 | */ | 350 | */ |
351 | if (file->f_mode & FMODE_WRITE) { | 351 | if (file->f_mode & FMODE_WRITE) { |
352 | if (!(inode->i_mode & S_IWUGO) || !ops->store) | 352 | if (!(inode->i_mode & S_IWUGO) || !ops->store) |
353 | goto err_out; | 353 | goto err_out; |
354 | } | 354 | } |
355 | 355 | ||
356 | /* File needs read support. | 356 | /* File needs read support. |
357 | * The inode's perms must say it's ok, and we there | 357 | * The inode's perms must say it's ok, and we there |
358 | * must be a show method for it. | 358 | * must be a show method for it. |
359 | */ | 359 | */ |
360 | if (file->f_mode & FMODE_READ) { | 360 | if (file->f_mode & FMODE_READ) { |
361 | if (!(inode->i_mode & S_IRUGO) || !ops->show) | 361 | if (!(inode->i_mode & S_IRUGO) || !ops->show) |
362 | goto err_out; | 362 | goto err_out; |
363 | } | 363 | } |
364 | 364 | ||
365 | /* No error? Great, allocate a buffer for the file, and store it | 365 | /* No error? Great, allocate a buffer for the file, and store it |
366 | * it in file->private_data for easy access. | 366 | * it in file->private_data for easy access. |
367 | */ | 367 | */ |
368 | error = -ENOMEM; | 368 | error = -ENOMEM; |
369 | buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); | 369 | buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); |
370 | if (!buffer) | 370 | if (!buffer) |
371 | goto err_out; | 371 | goto err_out; |
372 | 372 | ||
373 | mutex_init(&buffer->mutex); | 373 | mutex_init(&buffer->mutex); |
374 | buffer->needs_read_fill = 1; | 374 | buffer->needs_read_fill = 1; |
375 | buffer->ops = ops; | 375 | buffer->ops = ops; |
376 | file->private_data = buffer; | 376 | file->private_data = buffer; |
377 | 377 | ||
378 | /* make sure we have open dirent struct */ | 378 | /* make sure we have open dirent struct */ |
379 | error = sysfs_get_open_dirent(attr_sd, buffer); | 379 | error = sysfs_get_open_dirent(attr_sd, buffer); |
380 | if (error) | 380 | if (error) |
381 | goto err_free; | 381 | goto err_free; |
382 | 382 | ||
383 | /* open succeeded, put active references */ | 383 | /* open succeeded, put active references */ |
384 | sysfs_put_active(attr_sd); | 384 | sysfs_put_active(attr_sd); |
385 | return 0; | 385 | return 0; |
386 | 386 | ||
387 | err_free: | 387 | err_free: |
388 | kfree(buffer); | 388 | kfree(buffer); |
389 | err_out: | 389 | err_out: |
390 | sysfs_put_active(attr_sd); | 390 | sysfs_put_active(attr_sd); |
391 | return error; | 391 | return error; |
392 | } | 392 | } |
393 | 393 | ||
394 | static int sysfs_release(struct inode *inode, struct file *filp) | 394 | static int sysfs_release(struct inode *inode, struct file *filp) |
395 | { | 395 | { |
396 | struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata; | 396 | struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata; |
397 | struct sysfs_buffer *buffer = filp->private_data; | 397 | struct sysfs_buffer *buffer = filp->private_data; |
398 | 398 | ||
399 | sysfs_put_open_dirent(sd, buffer); | 399 | sysfs_put_open_dirent(sd, buffer); |
400 | 400 | ||
401 | if (buffer->page) | 401 | if (buffer->page) |
402 | free_page((unsigned long)buffer->page); | 402 | free_page((unsigned long)buffer->page); |
403 | kfree(buffer); | 403 | kfree(buffer); |
404 | 404 | ||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | /* Sysfs attribute files are pollable. The idea is that you read | 408 | /* Sysfs attribute files are pollable. The idea is that you read |
409 | * the content and then you use 'poll' or 'select' to wait for | 409 | * the content and then you use 'poll' or 'select' to wait for |
410 | * the content to change. When the content changes (assuming the | 410 | * the content to change. When the content changes (assuming the |
411 | * manager for the kobject supports notification), poll will | 411 | * manager for the kobject supports notification), poll will |
412 | * return POLLERR|POLLPRI, and select will return the fd whether | 412 | * return POLLERR|POLLPRI, and select will return the fd whether |
413 | * it is waiting for read, write, or exceptions. | 413 | * it is waiting for read, write, or exceptions. |
414 | * Once poll/select indicates that the value has changed, you | 414 | * Once poll/select indicates that the value has changed, you |
415 | * need to close and re-open the file, or seek to 0 and read again. | 415 | * need to close and re-open the file, or seek to 0 and read again. |
416 | * Reminder: this only works for attributes which actively support | 416 | * Reminder: this only works for attributes which actively support |
417 | * it, and it is not possible to test an attribute from userspace | 417 | * it, and it is not possible to test an attribute from userspace |
418 | * to see if it supports poll (Neither 'poll' nor 'select' return | 418 | * to see if it supports poll (Neither 'poll' nor 'select' return |
419 | * an appropriate error code). When in doubt, set a suitable timeout value. | 419 | * an appropriate error code). When in doubt, set a suitable timeout value. |
420 | */ | 420 | */ |
421 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | 421 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) |
422 | { | 422 | { |
423 | struct sysfs_buffer * buffer = filp->private_data; | 423 | struct sysfs_buffer * buffer = filp->private_data; |
424 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; | 424 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
425 | struct sysfs_open_dirent *od = attr_sd->s_attr.open; | 425 | struct sysfs_open_dirent *od = attr_sd->s_attr.open; |
426 | 426 | ||
427 | /* need parent for the kobj, grab both */ | 427 | /* need parent for the kobj, grab both */ |
428 | if (!sysfs_get_active(attr_sd)) | 428 | if (!sysfs_get_active(attr_sd)) |
429 | goto trigger; | 429 | goto trigger; |
430 | 430 | ||
431 | poll_wait(filp, &od->poll, wait); | 431 | poll_wait(filp, &od->poll, wait); |
432 | 432 | ||
433 | sysfs_put_active(attr_sd); | 433 | sysfs_put_active(attr_sd); |
434 | 434 | ||
435 | if (buffer->event != atomic_read(&od->event)) | 435 | if (buffer->event != atomic_read(&od->event)) |
436 | goto trigger; | 436 | goto trigger; |
437 | 437 | ||
438 | return DEFAULT_POLLMASK; | 438 | return DEFAULT_POLLMASK; |
439 | 439 | ||
440 | trigger: | 440 | trigger: |
441 | buffer->needs_read_fill = 1; | 441 | buffer->needs_read_fill = 1; |
442 | return DEFAULT_POLLMASK|POLLERR|POLLPRI; | 442 | return DEFAULT_POLLMASK|POLLERR|POLLPRI; |
443 | } | 443 | } |
444 | 444 | ||
445 | void sysfs_notify_dirent(struct sysfs_dirent *sd) | 445 | void sysfs_notify_dirent(struct sysfs_dirent *sd) |
446 | { | 446 | { |
447 | struct sysfs_open_dirent *od; | 447 | struct sysfs_open_dirent *od; |
448 | unsigned long flags; | 448 | unsigned long flags; |
449 | 449 | ||
450 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); | 450 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); |
451 | 451 | ||
452 | od = sd->s_attr.open; | 452 | od = sd->s_attr.open; |
453 | if (od) { | 453 | if (od) { |
454 | atomic_inc(&od->event); | 454 | atomic_inc(&od->event); |
455 | wake_up_interruptible(&od->poll); | 455 | wake_up_interruptible(&od->poll); |
456 | } | 456 | } |
457 | 457 | ||
458 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); | 458 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); |
459 | } | 459 | } |
460 | EXPORT_SYMBOL_GPL(sysfs_notify_dirent); | 460 | EXPORT_SYMBOL_GPL(sysfs_notify_dirent); |
461 | 461 | ||
462 | void sysfs_notify(struct kobject *k, const char *dir, const char *attr) | 462 | void sysfs_notify(struct kobject *k, const char *dir, const char *attr) |
463 | { | 463 | { |
464 | struct sysfs_dirent *sd = k->sd; | 464 | struct sysfs_dirent *sd = k->sd; |
465 | 465 | ||
466 | mutex_lock(&sysfs_mutex); | 466 | mutex_lock(&sysfs_mutex); |
467 | 467 | ||
468 | if (sd && dir) | 468 | if (sd && dir) |
469 | sd = sysfs_find_dirent(sd, NULL, dir); | 469 | sd = sysfs_find_dirent(sd, NULL, dir); |
470 | if (sd && attr) | 470 | if (sd && attr) |
471 | sd = sysfs_find_dirent(sd, NULL, attr); | 471 | sd = sysfs_find_dirent(sd, NULL, attr); |
472 | if (sd) | 472 | if (sd) |
473 | sysfs_notify_dirent(sd); | 473 | sysfs_notify_dirent(sd); |
474 | 474 | ||
475 | mutex_unlock(&sysfs_mutex); | 475 | mutex_unlock(&sysfs_mutex); |
476 | } | 476 | } |
477 | EXPORT_SYMBOL_GPL(sysfs_notify); | 477 | EXPORT_SYMBOL_GPL(sysfs_notify); |
478 | 478 | ||
479 | const struct file_operations sysfs_file_operations = { | 479 | const struct file_operations sysfs_file_operations = { |
480 | .read = sysfs_read_file, | 480 | .read = sysfs_read_file, |
481 | .write = sysfs_write_file, | 481 | .write = sysfs_write_file, |
482 | .llseek = generic_file_llseek, | 482 | .llseek = generic_file_llseek, |
483 | .open = sysfs_open_file, | 483 | .open = sysfs_open_file, |
484 | .release = sysfs_release, | 484 | .release = sysfs_release, |
485 | .poll = sysfs_poll, | 485 | .poll = sysfs_poll, |
486 | }; | 486 | }; |
487 | 487 | ||
488 | int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, | 488 | int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, |
489 | const void **pns) | 489 | const void **pns) |
490 | { | 490 | { |
491 | struct sysfs_dirent *dir_sd = kobj->sd; | 491 | struct sysfs_dirent *dir_sd = kobj->sd; |
492 | const struct sysfs_ops *ops; | 492 | const struct sysfs_ops *ops; |
493 | const void *ns = NULL; | 493 | const void *ns = NULL; |
494 | int err; | 494 | int err; |
495 | 495 | ||
496 | err = 0; | 496 | err = 0; |
497 | if (!sysfs_ns_type(dir_sd)) | 497 | if (!sysfs_ns_type(dir_sd)) |
498 | goto out; | 498 | goto out; |
499 | 499 | ||
500 | err = -EINVAL; | 500 | err = -EINVAL; |
501 | if (!kobj->ktype) | 501 | if (!kobj->ktype) |
502 | goto out; | 502 | goto out; |
503 | ops = kobj->ktype->sysfs_ops; | 503 | ops = kobj->ktype->sysfs_ops; |
504 | if (!ops) | 504 | if (!ops) |
505 | goto out; | 505 | goto out; |
506 | if (!ops->namespace) | 506 | if (!ops->namespace) |
507 | goto out; | 507 | goto out; |
508 | 508 | ||
509 | err = 0; | 509 | err = 0; |
510 | ns = ops->namespace(kobj, attr); | 510 | ns = ops->namespace(kobj, attr); |
511 | out: | 511 | out: |
512 | if (err) { | 512 | if (err) { |
513 | WARN(1, KERN_ERR "missing sysfs namespace attribute operation for " | 513 | WARN(1, KERN_ERR "missing sysfs namespace attribute operation for " |
514 | "kobject: %s\n", kobject_name(kobj)); | 514 | "kobject: %s\n", kobject_name(kobj)); |
515 | } | 515 | } |
516 | *pns = ns; | 516 | *pns = ns; |
517 | return err; | 517 | return err; |
518 | } | 518 | } |
519 | 519 | ||
520 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | 520 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, |
521 | const struct attribute *attr, int type, mode_t amode) | 521 | const struct attribute *attr, int type, umode_t amode) |
522 | { | 522 | { |
523 | umode_t mode = (amode & S_IALLUGO) | S_IFREG; | 523 | umode_t mode = (amode & S_IALLUGO) | S_IFREG; |
524 | struct sysfs_addrm_cxt acxt; | 524 | struct sysfs_addrm_cxt acxt; |
525 | struct sysfs_dirent *sd; | 525 | struct sysfs_dirent *sd; |
526 | const void *ns; | 526 | const void *ns; |
527 | int rc; | 527 | int rc; |
528 | 528 | ||
529 | rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns); | 529 | rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns); |
530 | if (rc) | 530 | if (rc) |
531 | return rc; | 531 | return rc; |
532 | 532 | ||
533 | sd = sysfs_new_dirent(attr->name, mode, type); | 533 | sd = sysfs_new_dirent(attr->name, mode, type); |
534 | if (!sd) | 534 | if (!sd) |
535 | return -ENOMEM; | 535 | return -ENOMEM; |
536 | 536 | ||
537 | sd->s_ns = ns; | 537 | sd->s_ns = ns; |
538 | sd->s_attr.attr = (void *)attr; | 538 | sd->s_attr.attr = (void *)attr; |
539 | sysfs_dirent_init_lockdep(sd); | 539 | sysfs_dirent_init_lockdep(sd); |
540 | 540 | ||
541 | sysfs_addrm_start(&acxt, dir_sd); | 541 | sysfs_addrm_start(&acxt, dir_sd); |
542 | rc = sysfs_add_one(&acxt, sd); | 542 | rc = sysfs_add_one(&acxt, sd); |
543 | sysfs_addrm_finish(&acxt); | 543 | sysfs_addrm_finish(&acxt); |
544 | 544 | ||
545 | if (rc) | 545 | if (rc) |
546 | sysfs_put(sd); | 546 | sysfs_put(sd); |
547 | 547 | ||
548 | return rc; | 548 | return rc; |
549 | } | 549 | } |
550 | 550 | ||
551 | 551 | ||
552 | int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | 552 | int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, |
553 | int type) | 553 | int type) |
554 | { | 554 | { |
555 | return sysfs_add_file_mode(dir_sd, attr, type, attr->mode); | 555 | return sysfs_add_file_mode(dir_sd, attr, type, attr->mode); |
556 | } | 556 | } |
557 | 557 | ||
558 | 558 | ||
559 | /** | 559 | /** |
560 | * sysfs_create_file - create an attribute file for an object. | 560 | * sysfs_create_file - create an attribute file for an object. |
561 | * @kobj: object we're creating for. | 561 | * @kobj: object we're creating for. |
562 | * @attr: attribute descriptor. | 562 | * @attr: attribute descriptor. |
563 | */ | 563 | */ |
564 | 564 | ||
565 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | 565 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) |
566 | { | 566 | { |
567 | BUG_ON(!kobj || !kobj->sd || !attr); | 567 | BUG_ON(!kobj || !kobj->sd || !attr); |
568 | 568 | ||
569 | return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); | 569 | return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); |
570 | 570 | ||
571 | } | 571 | } |
572 | 572 | ||
573 | int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) | 573 | int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) |
574 | { | 574 | { |
575 | int err = 0; | 575 | int err = 0; |
576 | int i; | 576 | int i; |
577 | 577 | ||
578 | for (i = 0; ptr[i] && !err; i++) | 578 | for (i = 0; ptr[i] && !err; i++) |
579 | err = sysfs_create_file(kobj, ptr[i]); | 579 | err = sysfs_create_file(kobj, ptr[i]); |
580 | if (err) | 580 | if (err) |
581 | while (--i >= 0) | 581 | while (--i >= 0) |
582 | sysfs_remove_file(kobj, ptr[i]); | 582 | sysfs_remove_file(kobj, ptr[i]); |
583 | return err; | 583 | return err; |
584 | } | 584 | } |
585 | 585 | ||
586 | /** | 586 | /** |
587 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. | 587 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. |
588 | * @kobj: object we're acting for. | 588 | * @kobj: object we're acting for. |
589 | * @attr: attribute descriptor. | 589 | * @attr: attribute descriptor. |
590 | * @group: group name. | 590 | * @group: group name. |
591 | */ | 591 | */ |
592 | int sysfs_add_file_to_group(struct kobject *kobj, | 592 | int sysfs_add_file_to_group(struct kobject *kobj, |
593 | const struct attribute *attr, const char *group) | 593 | const struct attribute *attr, const char *group) |
594 | { | 594 | { |
595 | struct sysfs_dirent *dir_sd; | 595 | struct sysfs_dirent *dir_sd; |
596 | int error; | 596 | int error; |
597 | 597 | ||
598 | if (group) | 598 | if (group) |
599 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); | 599 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); |
600 | else | 600 | else |
601 | dir_sd = sysfs_get(kobj->sd); | 601 | dir_sd = sysfs_get(kobj->sd); |
602 | 602 | ||
603 | if (!dir_sd) | 603 | if (!dir_sd) |
604 | return -ENOENT; | 604 | return -ENOENT; |
605 | 605 | ||
606 | error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR); | 606 | error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR); |
607 | sysfs_put(dir_sd); | 607 | sysfs_put(dir_sd); |
608 | 608 | ||
609 | return error; | 609 | return error; |
610 | } | 610 | } |
611 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | 611 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); |
612 | 612 | ||
613 | /** | 613 | /** |
614 | * sysfs_chmod_file - update the modified mode value on an object attribute. | 614 | * sysfs_chmod_file - update the modified mode value on an object attribute. |
615 | * @kobj: object we're acting for. | 615 | * @kobj: object we're acting for. |
616 | * @attr: attribute descriptor. | 616 | * @attr: attribute descriptor. |
617 | * @mode: file permissions. | 617 | * @mode: file permissions. |
618 | * | 618 | * |
619 | */ | 619 | */ |
620 | int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, | 620 | int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, |
621 | umode_t mode) | 621 | umode_t mode) |
622 | { | 622 | { |
623 | struct sysfs_dirent *sd; | 623 | struct sysfs_dirent *sd; |
624 | struct iattr newattrs; | 624 | struct iattr newattrs; |
625 | const void *ns; | 625 | const void *ns; |
626 | int rc; | 626 | int rc; |
627 | 627 | ||
628 | rc = sysfs_attr_ns(kobj, attr, &ns); | 628 | rc = sysfs_attr_ns(kobj, attr, &ns); |
629 | if (rc) | 629 | if (rc) |
630 | return rc; | 630 | return rc; |
631 | 631 | ||
632 | mutex_lock(&sysfs_mutex); | 632 | mutex_lock(&sysfs_mutex); |
633 | 633 | ||
634 | rc = -ENOENT; | 634 | rc = -ENOENT; |
635 | sd = sysfs_find_dirent(kobj->sd, ns, attr->name); | 635 | sd = sysfs_find_dirent(kobj->sd, ns, attr->name); |
636 | if (!sd) | 636 | if (!sd) |
637 | goto out; | 637 | goto out; |
638 | 638 | ||
639 | newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO); | 639 | newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO); |
640 | newattrs.ia_valid = ATTR_MODE; | 640 | newattrs.ia_valid = ATTR_MODE; |
641 | rc = sysfs_sd_setattr(sd, &newattrs); | 641 | rc = sysfs_sd_setattr(sd, &newattrs); |
642 | 642 | ||
643 | out: | 643 | out: |
644 | mutex_unlock(&sysfs_mutex); | 644 | mutex_unlock(&sysfs_mutex); |
645 | return rc; | 645 | return rc; |
646 | } | 646 | } |
647 | EXPORT_SYMBOL_GPL(sysfs_chmod_file); | 647 | EXPORT_SYMBOL_GPL(sysfs_chmod_file); |
648 | 648 | ||
649 | 649 | ||
650 | /** | 650 | /** |
651 | * sysfs_remove_file - remove an object attribute. | 651 | * sysfs_remove_file - remove an object attribute. |
652 | * @kobj: object we're acting for. | 652 | * @kobj: object we're acting for. |
653 | * @attr: attribute descriptor. | 653 | * @attr: attribute descriptor. |
654 | * | 654 | * |
655 | * Hash the attribute name and kill the victim. | 655 | * Hash the attribute name and kill the victim. |
656 | */ | 656 | */ |
657 | 657 | ||
658 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | 658 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) |
659 | { | 659 | { |
660 | const void *ns; | 660 | const void *ns; |
661 | 661 | ||
662 | if (sysfs_attr_ns(kobj, attr, &ns)) | 662 | if (sysfs_attr_ns(kobj, attr, &ns)) |
663 | return; | 663 | return; |
664 | 664 | ||
665 | sysfs_hash_and_remove(kobj->sd, ns, attr->name); | 665 | sysfs_hash_and_remove(kobj->sd, ns, attr->name); |
666 | } | 666 | } |
667 | 667 | ||
668 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) | 668 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) |
669 | { | 669 | { |
670 | int i; | 670 | int i; |
671 | for (i = 0; ptr[i]; i++) | 671 | for (i = 0; ptr[i]; i++) |
672 | sysfs_remove_file(kobj, ptr[i]); | 672 | sysfs_remove_file(kobj, ptr[i]); |
673 | } | 673 | } |
674 | 674 | ||
675 | /** | 675 | /** |
676 | * sysfs_remove_file_from_group - remove an attribute file from a group. | 676 | * sysfs_remove_file_from_group - remove an attribute file from a group. |
677 | * @kobj: object we're acting for. | 677 | * @kobj: object we're acting for. |
678 | * @attr: attribute descriptor. | 678 | * @attr: attribute descriptor. |
679 | * @group: group name. | 679 | * @group: group name. |
680 | */ | 680 | */ |
681 | void sysfs_remove_file_from_group(struct kobject *kobj, | 681 | void sysfs_remove_file_from_group(struct kobject *kobj, |
682 | const struct attribute *attr, const char *group) | 682 | const struct attribute *attr, const char *group) |
683 | { | 683 | { |
684 | struct sysfs_dirent *dir_sd; | 684 | struct sysfs_dirent *dir_sd; |
685 | 685 | ||
686 | if (group) | 686 | if (group) |
687 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); | 687 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); |
688 | else | 688 | else |
689 | dir_sd = sysfs_get(kobj->sd); | 689 | dir_sd = sysfs_get(kobj->sd); |
690 | if (dir_sd) { | 690 | if (dir_sd) { |
691 | sysfs_hash_and_remove(dir_sd, NULL, attr->name); | 691 | sysfs_hash_and_remove(dir_sd, NULL, attr->name); |
692 | sysfs_put(dir_sd); | 692 | sysfs_put(dir_sd); |
693 | } | 693 | } |
694 | } | 694 | } |
695 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); | 695 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); |
696 | 696 | ||
697 | struct sysfs_schedule_callback_struct { | 697 | struct sysfs_schedule_callback_struct { |
698 | struct list_head workq_list; | 698 | struct list_head workq_list; |
699 | struct kobject *kobj; | 699 | struct kobject *kobj; |
700 | void (*func)(void *); | 700 | void (*func)(void *); |
701 | void *data; | 701 | void *data; |
702 | struct module *owner; | 702 | struct module *owner; |
703 | struct work_struct work; | 703 | struct work_struct work; |
704 | }; | 704 | }; |
705 | 705 | ||
706 | static struct workqueue_struct *sysfs_workqueue; | 706 | static struct workqueue_struct *sysfs_workqueue; |
707 | static DEFINE_MUTEX(sysfs_workq_mutex); | 707 | static DEFINE_MUTEX(sysfs_workq_mutex); |
708 | static LIST_HEAD(sysfs_workq); | 708 | static LIST_HEAD(sysfs_workq); |
709 | static void sysfs_schedule_callback_work(struct work_struct *work) | 709 | static void sysfs_schedule_callback_work(struct work_struct *work) |
710 | { | 710 | { |
711 | struct sysfs_schedule_callback_struct *ss = container_of(work, | 711 | struct sysfs_schedule_callback_struct *ss = container_of(work, |
712 | struct sysfs_schedule_callback_struct, work); | 712 | struct sysfs_schedule_callback_struct, work); |
713 | 713 | ||
714 | (ss->func)(ss->data); | 714 | (ss->func)(ss->data); |
715 | kobject_put(ss->kobj); | 715 | kobject_put(ss->kobj); |
716 | module_put(ss->owner); | 716 | module_put(ss->owner); |
717 | mutex_lock(&sysfs_workq_mutex); | 717 | mutex_lock(&sysfs_workq_mutex); |
718 | list_del(&ss->workq_list); | 718 | list_del(&ss->workq_list); |
719 | mutex_unlock(&sysfs_workq_mutex); | 719 | mutex_unlock(&sysfs_workq_mutex); |
720 | kfree(ss); | 720 | kfree(ss); |
721 | } | 721 | } |
722 | 722 | ||
723 | /** | 723 | /** |
724 | * sysfs_schedule_callback - helper to schedule a callback for a kobject | 724 | * sysfs_schedule_callback - helper to schedule a callback for a kobject |
725 | * @kobj: object we're acting for. | 725 | * @kobj: object we're acting for. |
726 | * @func: callback function to invoke later. | 726 | * @func: callback function to invoke later. |
727 | * @data: argument to pass to @func. | 727 | * @data: argument to pass to @func. |
728 | * @owner: module owning the callback code | 728 | * @owner: module owning the callback code |
729 | * | 729 | * |
730 | * sysfs attribute methods must not unregister themselves or their parent | 730 | * sysfs attribute methods must not unregister themselves or their parent |
731 | * kobject (which would amount to the same thing). Attempts to do so will | 731 | * kobject (which would amount to the same thing). Attempts to do so will |
732 | * deadlock, since unregistration is mutually exclusive with driver | 732 | * deadlock, since unregistration is mutually exclusive with driver |
733 | * callbacks. | 733 | * callbacks. |
734 | * | 734 | * |
735 | * Instead methods can call this routine, which will attempt to allocate | 735 | * Instead methods can call this routine, which will attempt to allocate |
736 | * and schedule a workqueue request to call back @func with @data as its | 736 | * and schedule a workqueue request to call back @func with @data as its |
737 | * argument in the workqueue's process context. @kobj will be pinned | 737 | * argument in the workqueue's process context. @kobj will be pinned |
738 | * until @func returns. | 738 | * until @func returns. |
739 | * | 739 | * |
740 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | 740 | * Returns 0 if the request was submitted, -ENOMEM if storage could not |
741 | * be allocated, -ENODEV if a reference to @owner isn't available, | 741 | * be allocated, -ENODEV if a reference to @owner isn't available, |
742 | * -EAGAIN if a callback has already been scheduled for @kobj. | 742 | * -EAGAIN if a callback has already been scheduled for @kobj. |
743 | */ | 743 | */ |
744 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | 744 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), |
745 | void *data, struct module *owner) | 745 | void *data, struct module *owner) |
746 | { | 746 | { |
747 | struct sysfs_schedule_callback_struct *ss, *tmp; | 747 | struct sysfs_schedule_callback_struct *ss, *tmp; |
748 | 748 | ||
749 | if (!try_module_get(owner)) | 749 | if (!try_module_get(owner)) |
750 | return -ENODEV; | 750 | return -ENODEV; |
751 | 751 | ||
752 | mutex_lock(&sysfs_workq_mutex); | 752 | mutex_lock(&sysfs_workq_mutex); |
753 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) | 753 | list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) |
754 | if (ss->kobj == kobj) { | 754 | if (ss->kobj == kobj) { |
755 | module_put(owner); | 755 | module_put(owner); |
756 | mutex_unlock(&sysfs_workq_mutex); | 756 | mutex_unlock(&sysfs_workq_mutex); |
757 | return -EAGAIN; | 757 | return -EAGAIN; |
758 | } | 758 | } |
759 | mutex_unlock(&sysfs_workq_mutex); | 759 | mutex_unlock(&sysfs_workq_mutex); |
760 | 760 | ||
761 | if (sysfs_workqueue == NULL) { | 761 | if (sysfs_workqueue == NULL) { |
762 | sysfs_workqueue = create_singlethread_workqueue("sysfsd"); | 762 | sysfs_workqueue = create_singlethread_workqueue("sysfsd"); |
763 | if (sysfs_workqueue == NULL) { | 763 | if (sysfs_workqueue == NULL) { |
764 | module_put(owner); | 764 | module_put(owner); |
765 | return -ENOMEM; | 765 | return -ENOMEM; |
766 | } | 766 | } |
767 | } | 767 | } |
768 | 768 | ||
769 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); | 769 | ss = kmalloc(sizeof(*ss), GFP_KERNEL); |
770 | if (!ss) { | 770 | if (!ss) { |
771 | module_put(owner); | 771 | module_put(owner); |
772 | return -ENOMEM; | 772 | return -ENOMEM; |
773 | } | 773 | } |
774 | kobject_get(kobj); | 774 | kobject_get(kobj); |
775 | ss->kobj = kobj; | 775 | ss->kobj = kobj; |
776 | ss->func = func; | 776 | ss->func = func; |
777 | ss->data = data; | 777 | ss->data = data; |
778 | ss->owner = owner; | 778 | ss->owner = owner; |
779 | INIT_WORK(&ss->work, sysfs_schedule_callback_work); | 779 | INIT_WORK(&ss->work, sysfs_schedule_callback_work); |
780 | INIT_LIST_HEAD(&ss->workq_list); | 780 | INIT_LIST_HEAD(&ss->workq_list); |
781 | mutex_lock(&sysfs_workq_mutex); | 781 | mutex_lock(&sysfs_workq_mutex); |
782 | list_add_tail(&ss->workq_list, &sysfs_workq); | 782 | list_add_tail(&ss->workq_list, &sysfs_workq); |
783 | mutex_unlock(&sysfs_workq_mutex); | 783 | mutex_unlock(&sysfs_workq_mutex); |
784 | queue_work(sysfs_workqueue, &ss->work); | 784 | queue_work(sysfs_workqueue, &ss->work); |
785 | return 0; | 785 | return 0; |
786 | } | 786 | } |
787 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | 787 | EXPORT_SYMBOL_GPL(sysfs_schedule_callback); |
788 | 788 | ||
789 | 789 | ||
790 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 790 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
791 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 791 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
792 | EXPORT_SYMBOL_GPL(sysfs_remove_files); | 792 | EXPORT_SYMBOL_GPL(sysfs_remove_files); |
793 | EXPORT_SYMBOL_GPL(sysfs_create_files); | 793 | EXPORT_SYMBOL_GPL(sysfs_create_files); |
794 | 794 |
fs/sysfs/inode.c
1 | /* | 1 | /* |
2 | * fs/sysfs/inode.c - basic sysfs inode and dentry operations | 2 | * fs/sysfs/inode.c - basic sysfs inode and dentry operations |
3 | * | 3 | * |
4 | * Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
5 | * Copyright (c) 2007 SUSE Linux Products GmbH | 5 | * Copyright (c) 2007 SUSE Linux Products GmbH |
6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> |
7 | * | 7 | * |
8 | * This file is released under the GPLv2. | 8 | * This file is released under the GPLv2. |
9 | * | 9 | * |
10 | * Please see Documentation/filesystems/sysfs.txt for more information. | 10 | * Please see Documentation/filesystems/sysfs.txt for more information. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #undef DEBUG | 13 | #undef DEBUG |
14 | 14 | ||
15 | #include <linux/pagemap.h> | 15 | #include <linux/pagemap.h> |
16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
17 | #include <linux/backing-dev.h> | 17 | #include <linux/backing-dev.h> |
18 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/sysfs.h> | 22 | #include <linux/sysfs.h> |
23 | #include <linux/xattr.h> | 23 | #include <linux/xattr.h> |
24 | #include <linux/security.h> | 24 | #include <linux/security.h> |
25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
26 | 26 | ||
27 | extern struct super_block * sysfs_sb; | 27 | extern struct super_block * sysfs_sb; |
28 | 28 | ||
29 | static const struct address_space_operations sysfs_aops = { | 29 | static const struct address_space_operations sysfs_aops = { |
30 | .readpage = simple_readpage, | 30 | .readpage = simple_readpage, |
31 | .write_begin = simple_write_begin, | 31 | .write_begin = simple_write_begin, |
32 | .write_end = simple_write_end, | 32 | .write_end = simple_write_end, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | static struct backing_dev_info sysfs_backing_dev_info = { | 35 | static struct backing_dev_info sysfs_backing_dev_info = { |
36 | .name = "sysfs", | 36 | .name = "sysfs", |
37 | .ra_pages = 0, /* No readahead */ | 37 | .ra_pages = 0, /* No readahead */ |
38 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, | 38 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static const struct inode_operations sysfs_inode_operations ={ | 41 | static const struct inode_operations sysfs_inode_operations ={ |
42 | .permission = sysfs_permission, | 42 | .permission = sysfs_permission, |
43 | .setattr = sysfs_setattr, | 43 | .setattr = sysfs_setattr, |
44 | .getattr = sysfs_getattr, | 44 | .getattr = sysfs_getattr, |
45 | .setxattr = sysfs_setxattr, | 45 | .setxattr = sysfs_setxattr, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | int __init sysfs_inode_init(void) | 48 | int __init sysfs_inode_init(void) |
49 | { | 49 | { |
50 | return bdi_init(&sysfs_backing_dev_info); | 50 | return bdi_init(&sysfs_backing_dev_info); |
51 | } | 51 | } |
52 | 52 | ||
53 | static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) | 53 | static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) |
54 | { | 54 | { |
55 | struct sysfs_inode_attrs *attrs; | 55 | struct sysfs_inode_attrs *attrs; |
56 | struct iattr *iattrs; | 56 | struct iattr *iattrs; |
57 | 57 | ||
58 | attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL); | 58 | attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL); |
59 | if (!attrs) | 59 | if (!attrs) |
60 | return NULL; | 60 | return NULL; |
61 | iattrs = &attrs->ia_iattr; | 61 | iattrs = &attrs->ia_iattr; |
62 | 62 | ||
63 | /* assign default attributes */ | 63 | /* assign default attributes */ |
64 | iattrs->ia_mode = sd->s_mode; | 64 | iattrs->ia_mode = sd->s_mode; |
65 | iattrs->ia_uid = 0; | 65 | iattrs->ia_uid = 0; |
66 | iattrs->ia_gid = 0; | 66 | iattrs->ia_gid = 0; |
67 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; | 67 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; |
68 | 68 | ||
69 | return attrs; | 69 | return attrs; |
70 | } | 70 | } |
71 | 71 | ||
72 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) | 72 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) |
73 | { | 73 | { |
74 | struct sysfs_inode_attrs *sd_attrs; | 74 | struct sysfs_inode_attrs *sd_attrs; |
75 | struct iattr *iattrs; | 75 | struct iattr *iattrs; |
76 | unsigned int ia_valid = iattr->ia_valid; | 76 | unsigned int ia_valid = iattr->ia_valid; |
77 | 77 | ||
78 | sd_attrs = sd->s_iattr; | 78 | sd_attrs = sd->s_iattr; |
79 | 79 | ||
80 | if (!sd_attrs) { | 80 | if (!sd_attrs) { |
81 | /* setting attributes for the first time, allocate now */ | 81 | /* setting attributes for the first time, allocate now */ |
82 | sd_attrs = sysfs_init_inode_attrs(sd); | 82 | sd_attrs = sysfs_init_inode_attrs(sd); |
83 | if (!sd_attrs) | 83 | if (!sd_attrs) |
84 | return -ENOMEM; | 84 | return -ENOMEM; |
85 | sd->s_iattr = sd_attrs; | 85 | sd->s_iattr = sd_attrs; |
86 | } | 86 | } |
87 | /* attributes were changed at least once in past */ | 87 | /* attributes were changed at least once in past */ |
88 | iattrs = &sd_attrs->ia_iattr; | 88 | iattrs = &sd_attrs->ia_iattr; |
89 | 89 | ||
90 | if (ia_valid & ATTR_UID) | 90 | if (ia_valid & ATTR_UID) |
91 | iattrs->ia_uid = iattr->ia_uid; | 91 | iattrs->ia_uid = iattr->ia_uid; |
92 | if (ia_valid & ATTR_GID) | 92 | if (ia_valid & ATTR_GID) |
93 | iattrs->ia_gid = iattr->ia_gid; | 93 | iattrs->ia_gid = iattr->ia_gid; |
94 | if (ia_valid & ATTR_ATIME) | 94 | if (ia_valid & ATTR_ATIME) |
95 | iattrs->ia_atime = iattr->ia_atime; | 95 | iattrs->ia_atime = iattr->ia_atime; |
96 | if (ia_valid & ATTR_MTIME) | 96 | if (ia_valid & ATTR_MTIME) |
97 | iattrs->ia_mtime = iattr->ia_mtime; | 97 | iattrs->ia_mtime = iattr->ia_mtime; |
98 | if (ia_valid & ATTR_CTIME) | 98 | if (ia_valid & ATTR_CTIME) |
99 | iattrs->ia_ctime = iattr->ia_ctime; | 99 | iattrs->ia_ctime = iattr->ia_ctime; |
100 | if (ia_valid & ATTR_MODE) { | 100 | if (ia_valid & ATTR_MODE) { |
101 | umode_t mode = iattr->ia_mode; | 101 | umode_t mode = iattr->ia_mode; |
102 | iattrs->ia_mode = sd->s_mode = mode; | 102 | iattrs->ia_mode = sd->s_mode = mode; |
103 | } | 103 | } |
104 | return 0; | 104 | return 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) | 107 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) |
108 | { | 108 | { |
109 | struct inode *inode = dentry->d_inode; | 109 | struct inode *inode = dentry->d_inode; |
110 | struct sysfs_dirent *sd = dentry->d_fsdata; | 110 | struct sysfs_dirent *sd = dentry->d_fsdata; |
111 | int error; | 111 | int error; |
112 | 112 | ||
113 | if (!sd) | 113 | if (!sd) |
114 | return -EINVAL; | 114 | return -EINVAL; |
115 | 115 | ||
116 | mutex_lock(&sysfs_mutex); | 116 | mutex_lock(&sysfs_mutex); |
117 | error = inode_change_ok(inode, iattr); | 117 | error = inode_change_ok(inode, iattr); |
118 | if (error) | 118 | if (error) |
119 | goto out; | 119 | goto out; |
120 | 120 | ||
121 | error = sysfs_sd_setattr(sd, iattr); | 121 | error = sysfs_sd_setattr(sd, iattr); |
122 | if (error) | 122 | if (error) |
123 | goto out; | 123 | goto out; |
124 | 124 | ||
125 | /* this ignores size changes */ | 125 | /* this ignores size changes */ |
126 | setattr_copy(inode, iattr); | 126 | setattr_copy(inode, iattr); |
127 | 127 | ||
128 | out: | 128 | out: |
129 | mutex_unlock(&sysfs_mutex); | 129 | mutex_unlock(&sysfs_mutex); |
130 | return error; | 130 | return error; |
131 | } | 131 | } |
132 | 132 | ||
133 | static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len) | 133 | static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len) |
134 | { | 134 | { |
135 | struct sysfs_inode_attrs *iattrs; | 135 | struct sysfs_inode_attrs *iattrs; |
136 | void *old_secdata; | 136 | void *old_secdata; |
137 | size_t old_secdata_len; | 137 | size_t old_secdata_len; |
138 | 138 | ||
139 | iattrs = sd->s_iattr; | 139 | iattrs = sd->s_iattr; |
140 | if (!iattrs) | 140 | if (!iattrs) |
141 | iattrs = sysfs_init_inode_attrs(sd); | 141 | iattrs = sysfs_init_inode_attrs(sd); |
142 | if (!iattrs) | 142 | if (!iattrs) |
143 | return -ENOMEM; | 143 | return -ENOMEM; |
144 | 144 | ||
145 | old_secdata = iattrs->ia_secdata; | 145 | old_secdata = iattrs->ia_secdata; |
146 | old_secdata_len = iattrs->ia_secdata_len; | 146 | old_secdata_len = iattrs->ia_secdata_len; |
147 | 147 | ||
148 | iattrs->ia_secdata = *secdata; | 148 | iattrs->ia_secdata = *secdata; |
149 | iattrs->ia_secdata_len = *secdata_len; | 149 | iattrs->ia_secdata_len = *secdata_len; |
150 | 150 | ||
151 | *secdata = old_secdata; | 151 | *secdata = old_secdata; |
152 | *secdata_len = old_secdata_len; | 152 | *secdata_len = old_secdata_len; |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 156 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
157 | size_t size, int flags) | 157 | size_t size, int flags) |
158 | { | 158 | { |
159 | struct sysfs_dirent *sd = dentry->d_fsdata; | 159 | struct sysfs_dirent *sd = dentry->d_fsdata; |
160 | void *secdata; | 160 | void *secdata; |
161 | int error; | 161 | int error; |
162 | u32 secdata_len = 0; | 162 | u32 secdata_len = 0; |
163 | 163 | ||
164 | if (!sd) | 164 | if (!sd) |
165 | return -EINVAL; | 165 | return -EINVAL; |
166 | 166 | ||
167 | if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { | 167 | if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { |
168 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | 168 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; |
169 | error = security_inode_setsecurity(dentry->d_inode, suffix, | 169 | error = security_inode_setsecurity(dentry->d_inode, suffix, |
170 | value, size, flags); | 170 | value, size, flags); |
171 | if (error) | 171 | if (error) |
172 | goto out; | 172 | goto out; |
173 | error = security_inode_getsecctx(dentry->d_inode, | 173 | error = security_inode_getsecctx(dentry->d_inode, |
174 | &secdata, &secdata_len); | 174 | &secdata, &secdata_len); |
175 | if (error) | 175 | if (error) |
176 | goto out; | 176 | goto out; |
177 | 177 | ||
178 | mutex_lock(&sysfs_mutex); | 178 | mutex_lock(&sysfs_mutex); |
179 | error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); | 179 | error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); |
180 | mutex_unlock(&sysfs_mutex); | 180 | mutex_unlock(&sysfs_mutex); |
181 | 181 | ||
182 | if (secdata) | 182 | if (secdata) |
183 | security_release_secctx(secdata, secdata_len); | 183 | security_release_secctx(secdata, secdata_len); |
184 | } else | 184 | } else |
185 | return -EINVAL; | 185 | return -EINVAL; |
186 | out: | 186 | out: |
187 | return error; | 187 | return error; |
188 | } | 188 | } |
189 | 189 | ||
190 | static inline void set_default_inode_attr(struct inode * inode, mode_t mode) | 190 | static inline void set_default_inode_attr(struct inode * inode, umode_t mode) |
191 | { | 191 | { |
192 | inode->i_mode = mode; | 192 | inode->i_mode = mode; |
193 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 193 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
194 | } | 194 | } |
195 | 195 | ||
196 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | 196 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) |
197 | { | 197 | { |
198 | inode->i_uid = iattr->ia_uid; | 198 | inode->i_uid = iattr->ia_uid; |
199 | inode->i_gid = iattr->ia_gid; | 199 | inode->i_gid = iattr->ia_gid; |
200 | inode->i_atime = iattr->ia_atime; | 200 | inode->i_atime = iattr->ia_atime; |
201 | inode->i_mtime = iattr->ia_mtime; | 201 | inode->i_mtime = iattr->ia_mtime; |
202 | inode->i_ctime = iattr->ia_ctime; | 202 | inode->i_ctime = iattr->ia_ctime; |
203 | } | 203 | } |
204 | 204 | ||
205 | static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) | 205 | static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) |
206 | { | 206 | { |
207 | struct sysfs_inode_attrs *iattrs = sd->s_iattr; | 207 | struct sysfs_inode_attrs *iattrs = sd->s_iattr; |
208 | 208 | ||
209 | inode->i_mode = sd->s_mode; | 209 | inode->i_mode = sd->s_mode; |
210 | if (iattrs) { | 210 | if (iattrs) { |
211 | /* sysfs_dirent has non-default attributes | 211 | /* sysfs_dirent has non-default attributes |
212 | * get them from persistent copy in sysfs_dirent | 212 | * get them from persistent copy in sysfs_dirent |
213 | */ | 213 | */ |
214 | set_inode_attr(inode, &iattrs->ia_iattr); | 214 | set_inode_attr(inode, &iattrs->ia_iattr); |
215 | security_inode_notifysecctx(inode, | 215 | security_inode_notifysecctx(inode, |
216 | iattrs->ia_secdata, | 216 | iattrs->ia_secdata, |
217 | iattrs->ia_secdata_len); | 217 | iattrs->ia_secdata_len); |
218 | } | 218 | } |
219 | 219 | ||
220 | if (sysfs_type(sd) == SYSFS_DIR) | 220 | if (sysfs_type(sd) == SYSFS_DIR) |
221 | set_nlink(inode, sd->s_dir.subdirs + 2); | 221 | set_nlink(inode, sd->s_dir.subdirs + 2); |
222 | } | 222 | } |
223 | 223 | ||
224 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 224 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
225 | { | 225 | { |
226 | struct sysfs_dirent *sd = dentry->d_fsdata; | 226 | struct sysfs_dirent *sd = dentry->d_fsdata; |
227 | struct inode *inode = dentry->d_inode; | 227 | struct inode *inode = dentry->d_inode; |
228 | 228 | ||
229 | mutex_lock(&sysfs_mutex); | 229 | mutex_lock(&sysfs_mutex); |
230 | sysfs_refresh_inode(sd, inode); | 230 | sysfs_refresh_inode(sd, inode); |
231 | mutex_unlock(&sysfs_mutex); | 231 | mutex_unlock(&sysfs_mutex); |
232 | 232 | ||
233 | generic_fillattr(inode, stat); | 233 | generic_fillattr(inode, stat); |
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 237 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
238 | { | 238 | { |
239 | struct bin_attribute *bin_attr; | 239 | struct bin_attribute *bin_attr; |
240 | 240 | ||
241 | inode->i_private = sysfs_get(sd); | 241 | inode->i_private = sysfs_get(sd); |
242 | inode->i_mapping->a_ops = &sysfs_aops; | 242 | inode->i_mapping->a_ops = &sysfs_aops; |
243 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 243 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
244 | inode->i_op = &sysfs_inode_operations; | 244 | inode->i_op = &sysfs_inode_operations; |
245 | 245 | ||
246 | set_default_inode_attr(inode, sd->s_mode); | 246 | set_default_inode_attr(inode, sd->s_mode); |
247 | sysfs_refresh_inode(sd, inode); | 247 | sysfs_refresh_inode(sd, inode); |
248 | 248 | ||
249 | /* initialize inode according to type */ | 249 | /* initialize inode according to type */ |
250 | switch (sysfs_type(sd)) { | 250 | switch (sysfs_type(sd)) { |
251 | case SYSFS_DIR: | 251 | case SYSFS_DIR: |
252 | inode->i_op = &sysfs_dir_inode_operations; | 252 | inode->i_op = &sysfs_dir_inode_operations; |
253 | inode->i_fop = &sysfs_dir_operations; | 253 | inode->i_fop = &sysfs_dir_operations; |
254 | break; | 254 | break; |
255 | case SYSFS_KOBJ_ATTR: | 255 | case SYSFS_KOBJ_ATTR: |
256 | inode->i_size = PAGE_SIZE; | 256 | inode->i_size = PAGE_SIZE; |
257 | inode->i_fop = &sysfs_file_operations; | 257 | inode->i_fop = &sysfs_file_operations; |
258 | break; | 258 | break; |
259 | case SYSFS_KOBJ_BIN_ATTR: | 259 | case SYSFS_KOBJ_BIN_ATTR: |
260 | bin_attr = sd->s_bin_attr.bin_attr; | 260 | bin_attr = sd->s_bin_attr.bin_attr; |
261 | inode->i_size = bin_attr->size; | 261 | inode->i_size = bin_attr->size; |
262 | inode->i_fop = &bin_fops; | 262 | inode->i_fop = &bin_fops; |
263 | break; | 263 | break; |
264 | case SYSFS_KOBJ_LINK: | 264 | case SYSFS_KOBJ_LINK: |
265 | inode->i_op = &sysfs_symlink_inode_operations; | 265 | inode->i_op = &sysfs_symlink_inode_operations; |
266 | break; | 266 | break; |
267 | default: | 267 | default: |
268 | BUG(); | 268 | BUG(); |
269 | } | 269 | } |
270 | 270 | ||
271 | unlock_new_inode(inode); | 271 | unlock_new_inode(inode); |
272 | } | 272 | } |
273 | 273 | ||
274 | /** | 274 | /** |
275 | * sysfs_get_inode - get inode for sysfs_dirent | 275 | * sysfs_get_inode - get inode for sysfs_dirent |
276 | * @sb: super block | 276 | * @sb: super block |
277 | * @sd: sysfs_dirent to allocate inode for | 277 | * @sd: sysfs_dirent to allocate inode for |
278 | * | 278 | * |
279 | * Get inode for @sd. If such inode doesn't exist, a new inode | 279 | * Get inode for @sd. If such inode doesn't exist, a new inode |
280 | * is allocated and basics are initialized. New inode is | 280 | * is allocated and basics are initialized. New inode is |
281 | * returned locked. | 281 | * returned locked. |
282 | * | 282 | * |
283 | * LOCKING: | 283 | * LOCKING: |
284 | * Kernel thread context (may sleep). | 284 | * Kernel thread context (may sleep). |
285 | * | 285 | * |
286 | * RETURNS: | 286 | * RETURNS: |
287 | * Pointer to allocated inode on success, NULL on failure. | 287 | * Pointer to allocated inode on success, NULL on failure. |
288 | */ | 288 | */ |
289 | struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) | 289 | struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) |
290 | { | 290 | { |
291 | struct inode *inode; | 291 | struct inode *inode; |
292 | 292 | ||
293 | inode = iget_locked(sb, sd->s_ino); | 293 | inode = iget_locked(sb, sd->s_ino); |
294 | if (inode && (inode->i_state & I_NEW)) | 294 | if (inode && (inode->i_state & I_NEW)) |
295 | sysfs_init_inode(sd, inode); | 295 | sysfs_init_inode(sd, inode); |
296 | 296 | ||
297 | return inode; | 297 | return inode; |
298 | } | 298 | } |
299 | 299 | ||
300 | /* | 300 | /* |
301 | * The sysfs_dirent serves as both an inode and a directory entry for sysfs. | 301 | * The sysfs_dirent serves as both an inode and a directory entry for sysfs. |
302 | * To prevent the sysfs inode numbers from being freed prematurely we take a | 302 | * To prevent the sysfs inode numbers from being freed prematurely we take a |
303 | * reference to sysfs_dirent from the sysfs inode. A | 303 | * reference to sysfs_dirent from the sysfs inode. A |
304 | * super_operations.evict_inode() implementation is needed to drop that | 304 | * super_operations.evict_inode() implementation is needed to drop that |
305 | * reference upon inode destruction. | 305 | * reference upon inode destruction. |
306 | */ | 306 | */ |
307 | void sysfs_evict_inode(struct inode *inode) | 307 | void sysfs_evict_inode(struct inode *inode) |
308 | { | 308 | { |
309 | struct sysfs_dirent *sd = inode->i_private; | 309 | struct sysfs_dirent *sd = inode->i_private; |
310 | 310 | ||
311 | truncate_inode_pages(&inode->i_data, 0); | 311 | truncate_inode_pages(&inode->i_data, 0); |
312 | end_writeback(inode); | 312 | end_writeback(inode); |
313 | sysfs_put(sd); | 313 | sysfs_put(sd); |
314 | } | 314 | } |
315 | 315 | ||
316 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name) | 316 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name) |
317 | { | 317 | { |
318 | struct sysfs_addrm_cxt acxt; | 318 | struct sysfs_addrm_cxt acxt; |
319 | struct sysfs_dirent *sd; | 319 | struct sysfs_dirent *sd; |
320 | 320 | ||
321 | if (!dir_sd) | 321 | if (!dir_sd) |
322 | return -ENOENT; | 322 | return -ENOENT; |
323 | 323 | ||
324 | sysfs_addrm_start(&acxt, dir_sd); | 324 | sysfs_addrm_start(&acxt, dir_sd); |
325 | 325 | ||
326 | sd = sysfs_find_dirent(dir_sd, ns, name); | 326 | sd = sysfs_find_dirent(dir_sd, ns, name); |
327 | if (sd) | 327 | if (sd) |
328 | sysfs_remove_one(&acxt, sd); | 328 | sysfs_remove_one(&acxt, sd); |
329 | 329 | ||
330 | sysfs_addrm_finish(&acxt); | 330 | sysfs_addrm_finish(&acxt); |
331 | 331 | ||
332 | if (sd) | 332 | if (sd) |
333 | return 0; | 333 | return 0; |
334 | else | 334 | else |
335 | return -ENOENT; | 335 | return -ENOENT; |
336 | } | 336 | } |
337 | 337 | ||
338 | int sysfs_permission(struct inode *inode, int mask) | 338 | int sysfs_permission(struct inode *inode, int mask) |
339 | { | 339 | { |
340 | struct sysfs_dirent *sd; | 340 | struct sysfs_dirent *sd; |
341 | 341 | ||
342 | if (mask & MAY_NOT_BLOCK) | 342 | if (mask & MAY_NOT_BLOCK) |
343 | return -ECHILD; | 343 | return -ECHILD; |
344 | 344 | ||
345 | sd = inode->i_private; | 345 | sd = inode->i_private; |
346 | 346 | ||
347 | mutex_lock(&sysfs_mutex); | 347 | mutex_lock(&sysfs_mutex); |
348 | sysfs_refresh_inode(sd, inode); | 348 | sysfs_refresh_inode(sd, inode); |
349 | mutex_unlock(&sysfs_mutex); | 349 | mutex_unlock(&sysfs_mutex); |
350 | 350 | ||
351 | return generic_permission(inode, mask); | 351 | return generic_permission(inode, mask); |
352 | } | 352 | } |
353 | 353 |
fs/sysfs/sysfs.h
1 | /* | 1 | /* |
2 | * fs/sysfs/sysfs.h - sysfs internal header file | 2 | * fs/sysfs/sysfs.h - sysfs internal header file |
3 | * | 3 | * |
4 | * Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
5 | * Copyright (c) 2007 SUSE Linux Products GmbH | 5 | * Copyright (c) 2007 SUSE Linux Products GmbH |
6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> |
7 | * | 7 | * |
8 | * This file is released under the GPLv2. | 8 | * This file is released under the GPLv2. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/lockdep.h> | 11 | #include <linux/lockdep.h> |
12 | #include <linux/kobject_ns.h> | 12 | #include <linux/kobject_ns.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/rbtree.h> | 14 | #include <linux/rbtree.h> |
15 | 15 | ||
16 | struct sysfs_open_dirent; | 16 | struct sysfs_open_dirent; |
17 | 17 | ||
18 | /* type-specific structures for sysfs_dirent->s_* union members */ | 18 | /* type-specific structures for sysfs_dirent->s_* union members */ |
19 | struct sysfs_elem_dir { | 19 | struct sysfs_elem_dir { |
20 | struct kobject *kobj; | 20 | struct kobject *kobj; |
21 | 21 | ||
22 | unsigned long subdirs; | 22 | unsigned long subdirs; |
23 | 23 | ||
24 | struct rb_root inode_tree; | 24 | struct rb_root inode_tree; |
25 | struct rb_root name_tree; | 25 | struct rb_root name_tree; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct sysfs_elem_symlink { | 28 | struct sysfs_elem_symlink { |
29 | struct sysfs_dirent *target_sd; | 29 | struct sysfs_dirent *target_sd; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct sysfs_elem_attr { | 32 | struct sysfs_elem_attr { |
33 | struct attribute *attr; | 33 | struct attribute *attr; |
34 | struct sysfs_open_dirent *open; | 34 | struct sysfs_open_dirent *open; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | struct sysfs_elem_bin_attr { | 37 | struct sysfs_elem_bin_attr { |
38 | struct bin_attribute *bin_attr; | 38 | struct bin_attribute *bin_attr; |
39 | struct hlist_head buffers; | 39 | struct hlist_head buffers; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct sysfs_inode_attrs { | 42 | struct sysfs_inode_attrs { |
43 | struct iattr ia_iattr; | 43 | struct iattr ia_iattr; |
44 | void *ia_secdata; | 44 | void *ia_secdata; |
45 | u32 ia_secdata_len; | 45 | u32 ia_secdata_len; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * sysfs_dirent - the building block of sysfs hierarchy. Each and | 49 | * sysfs_dirent - the building block of sysfs hierarchy. Each and |
50 | * every sysfs node is represented by single sysfs_dirent. | 50 | * every sysfs node is represented by single sysfs_dirent. |
51 | * | 51 | * |
52 | * As long as s_count reference is held, the sysfs_dirent itself is | 52 | * As long as s_count reference is held, the sysfs_dirent itself is |
53 | * accessible. Dereferencing s_elem or any other outer entity | 53 | * accessible. Dereferencing s_elem or any other outer entity |
54 | * requires s_active reference. | 54 | * requires s_active reference. |
55 | */ | 55 | */ |
56 | struct sysfs_dirent { | 56 | struct sysfs_dirent { |
57 | atomic_t s_count; | 57 | atomic_t s_count; |
58 | atomic_t s_active; | 58 | atomic_t s_active; |
59 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 59 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
60 | struct lockdep_map dep_map; | 60 | struct lockdep_map dep_map; |
61 | #endif | 61 | #endif |
62 | struct sysfs_dirent *s_parent; | 62 | struct sysfs_dirent *s_parent; |
63 | const char *s_name; | 63 | const char *s_name; |
64 | 64 | ||
65 | struct rb_node inode_node; | 65 | struct rb_node inode_node; |
66 | struct rb_node name_node; | 66 | struct rb_node name_node; |
67 | 67 | ||
68 | union { | 68 | union { |
69 | struct completion *completion; | 69 | struct completion *completion; |
70 | struct sysfs_dirent *removed_list; | 70 | struct sysfs_dirent *removed_list; |
71 | } u; | 71 | } u; |
72 | 72 | ||
73 | const void *s_ns; /* namespace tag */ | 73 | const void *s_ns; /* namespace tag */ |
74 | union { | 74 | union { |
75 | struct sysfs_elem_dir s_dir; | 75 | struct sysfs_elem_dir s_dir; |
76 | struct sysfs_elem_symlink s_symlink; | 76 | struct sysfs_elem_symlink s_symlink; |
77 | struct sysfs_elem_attr s_attr; | 77 | struct sysfs_elem_attr s_attr; |
78 | struct sysfs_elem_bin_attr s_bin_attr; | 78 | struct sysfs_elem_bin_attr s_bin_attr; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | unsigned int s_flags; | 81 | unsigned int s_flags; |
82 | unsigned short s_mode; | 82 | umode_t s_mode; |
83 | ino_t s_ino; | 83 | ino_t s_ino; |
84 | struct sysfs_inode_attrs *s_iattr; | 84 | struct sysfs_inode_attrs *s_iattr; |
85 | }; | 85 | }; |
86 | 86 | ||
87 | #define SD_DEACTIVATED_BIAS INT_MIN | 87 | #define SD_DEACTIVATED_BIAS INT_MIN |
88 | 88 | ||
89 | #define SYSFS_TYPE_MASK 0x00ff | 89 | #define SYSFS_TYPE_MASK 0x00ff |
90 | #define SYSFS_DIR 0x0001 | 90 | #define SYSFS_DIR 0x0001 |
91 | #define SYSFS_KOBJ_ATTR 0x0002 | 91 | #define SYSFS_KOBJ_ATTR 0x0002 |
92 | #define SYSFS_KOBJ_BIN_ATTR 0x0004 | 92 | #define SYSFS_KOBJ_BIN_ATTR 0x0004 |
93 | #define SYSFS_KOBJ_LINK 0x0008 | 93 | #define SYSFS_KOBJ_LINK 0x0008 |
94 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | 94 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) |
95 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) | 95 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) |
96 | 96 | ||
97 | /* identify any namespace tag on sysfs_dirents */ | 97 | /* identify any namespace tag on sysfs_dirents */ |
98 | #define SYSFS_NS_TYPE_MASK 0xff00 | 98 | #define SYSFS_NS_TYPE_MASK 0xff00 |
99 | #define SYSFS_NS_TYPE_SHIFT 8 | 99 | #define SYSFS_NS_TYPE_SHIFT 8 |
100 | 100 | ||
101 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) | 101 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) |
102 | #define SYSFS_FLAG_REMOVED 0x020000 | 102 | #define SYSFS_FLAG_REMOVED 0x020000 |
103 | 103 | ||
104 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | 104 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) |
105 | { | 105 | { |
106 | return sd->s_flags & SYSFS_TYPE_MASK; | 106 | return sd->s_flags & SYSFS_TYPE_MASK; |
107 | } | 107 | } |
108 | 108 | ||
109 | /* | 109 | /* |
110 | * Return any namespace tags on this dirent. | 110 | * Return any namespace tags on this dirent. |
111 | * enum kobj_ns_type is defined in linux/kobject.h | 111 | * enum kobj_ns_type is defined in linux/kobject.h |
112 | */ | 112 | */ |
113 | static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd) | 113 | static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd) |
114 | { | 114 | { |
115 | return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT; | 115 | return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT; |
116 | } | 116 | } |
117 | 117 | ||
118 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 118 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
119 | #define sysfs_dirent_init_lockdep(sd) \ | 119 | #define sysfs_dirent_init_lockdep(sd) \ |
120 | do { \ | 120 | do { \ |
121 | struct attribute *attr = sd->s_attr.attr; \ | 121 | struct attribute *attr = sd->s_attr.attr; \ |
122 | struct lock_class_key *key = attr->key; \ | 122 | struct lock_class_key *key = attr->key; \ |
123 | if (!key) \ | 123 | if (!key) \ |
124 | key = &attr->skey; \ | 124 | key = &attr->skey; \ |
125 | \ | 125 | \ |
126 | lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ | 126 | lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ |
127 | } while(0) | 127 | } while(0) |
128 | #else | 128 | #else |
129 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) | 129 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) |
130 | #endif | 130 | #endif |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * Context structure to be used while adding/removing nodes. | 133 | * Context structure to be used while adding/removing nodes. |
134 | */ | 134 | */ |
135 | struct sysfs_addrm_cxt { | 135 | struct sysfs_addrm_cxt { |
136 | struct sysfs_dirent *parent_sd; | 136 | struct sysfs_dirent *parent_sd; |
137 | struct sysfs_dirent *removed; | 137 | struct sysfs_dirent *removed; |
138 | }; | 138 | }; |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * mount.c | 141 | * mount.c |
142 | */ | 142 | */ |
143 | 143 | ||
144 | /* | 144 | /* |
145 | * Each sb is associated with a set of namespace tags (i.e. | 145 | * Each sb is associated with a set of namespace tags (i.e. |
146 | * the network namespace of the task which mounted this sysfs | 146 | * the network namespace of the task which mounted this sysfs |
147 | * instance). | 147 | * instance). |
148 | */ | 148 | */ |
149 | struct sysfs_super_info { | 149 | struct sysfs_super_info { |
150 | void *ns[KOBJ_NS_TYPES]; | 150 | void *ns[KOBJ_NS_TYPES]; |
151 | }; | 151 | }; |
152 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) | 152 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) |
153 | extern struct sysfs_dirent sysfs_root; | 153 | extern struct sysfs_dirent sysfs_root; |
154 | extern struct kmem_cache *sysfs_dir_cachep; | 154 | extern struct kmem_cache *sysfs_dir_cachep; |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * dir.c | 157 | * dir.c |
158 | */ | 158 | */ |
159 | extern struct mutex sysfs_mutex; | 159 | extern struct mutex sysfs_mutex; |
160 | extern spinlock_t sysfs_assoc_lock; | 160 | extern spinlock_t sysfs_assoc_lock; |
161 | 161 | ||
162 | extern const struct file_operations sysfs_dir_operations; | 162 | extern const struct file_operations sysfs_dir_operations; |
163 | extern const struct inode_operations sysfs_dir_inode_operations; | 163 | extern const struct inode_operations sysfs_dir_inode_operations; |
164 | 164 | ||
165 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); | 165 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
166 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | 166 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); |
167 | void sysfs_put_active(struct sysfs_dirent *sd); | 167 | void sysfs_put_active(struct sysfs_dirent *sd); |
168 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 168 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
169 | struct sysfs_dirent *parent_sd); | 169 | struct sysfs_dirent *parent_sd); |
170 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 170 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
171 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 171 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
172 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 172 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
173 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | 173 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); |
174 | 174 | ||
175 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | 175 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, |
176 | const void *ns, | 176 | const void *ns, |
177 | const unsigned char *name); | 177 | const unsigned char *name); |
178 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | 178 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, |
179 | const void *ns, | 179 | const void *ns, |
180 | const unsigned char *name); | 180 | const unsigned char *name); |
181 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); | 181 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); |
182 | 182 | ||
183 | void release_sysfs_dirent(struct sysfs_dirent *sd); | 183 | void release_sysfs_dirent(struct sysfs_dirent *sd); |
184 | 184 | ||
185 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | 185 | int sysfs_create_subdir(struct kobject *kobj, const char *name, |
186 | struct sysfs_dirent **p_sd); | 186 | struct sysfs_dirent **p_sd); |
187 | void sysfs_remove_subdir(struct sysfs_dirent *sd); | 187 | void sysfs_remove_subdir(struct sysfs_dirent *sd); |
188 | 188 | ||
189 | int sysfs_rename(struct sysfs_dirent *sd, | 189 | int sysfs_rename(struct sysfs_dirent *sd, |
190 | struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name); | 190 | struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name); |
191 | 191 | ||
192 | static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) | 192 | static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) |
193 | { | 193 | { |
194 | if (sd) { | 194 | if (sd) { |
195 | WARN_ON(!atomic_read(&sd->s_count)); | 195 | WARN_ON(!atomic_read(&sd->s_count)); |
196 | atomic_inc(&sd->s_count); | 196 | atomic_inc(&sd->s_count); |
197 | } | 197 | } |
198 | return sd; | 198 | return sd; |
199 | } | 199 | } |
200 | #define sysfs_get(sd) __sysfs_get(sd) | 200 | #define sysfs_get(sd) __sysfs_get(sd) |
201 | 201 | ||
202 | static inline void __sysfs_put(struct sysfs_dirent *sd) | 202 | static inline void __sysfs_put(struct sysfs_dirent *sd) |
203 | { | 203 | { |
204 | if (sd && atomic_dec_and_test(&sd->s_count)) | 204 | if (sd && atomic_dec_and_test(&sd->s_count)) |
205 | release_sysfs_dirent(sd); | 205 | release_sysfs_dirent(sd); |
206 | } | 206 | } |
207 | #define sysfs_put(sd) __sysfs_put(sd) | 207 | #define sysfs_put(sd) __sysfs_put(sd) |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * inode.c | 210 | * inode.c |
211 | */ | 211 | */ |
212 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); | 212 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); |
213 | void sysfs_evict_inode(struct inode *inode); | 213 | void sysfs_evict_inode(struct inode *inode); |
214 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | 214 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); |
215 | int sysfs_permission(struct inode *inode, int mask); | 215 | int sysfs_permission(struct inode *inode, int mask); |
216 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 216 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
217 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | 217 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); |
218 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 218 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
219 | size_t size, int flags); | 219 | size_t size, int flags); |
220 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name); | 220 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name); |
221 | int sysfs_inode_init(void); | 221 | int sysfs_inode_init(void); |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * file.c | 224 | * file.c |
225 | */ | 225 | */ |
226 | extern const struct file_operations sysfs_file_operations; | 226 | extern const struct file_operations sysfs_file_operations; |
227 | 227 | ||
228 | int sysfs_add_file(struct sysfs_dirent *dir_sd, | 228 | int sysfs_add_file(struct sysfs_dirent *dir_sd, |
229 | const struct attribute *attr, int type); | 229 | const struct attribute *attr, int type); |
230 | 230 | ||
231 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | 231 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, |
232 | const struct attribute *attr, int type, mode_t amode); | 232 | const struct attribute *attr, int type, umode_t amode); |
233 | /* | 233 | /* |
234 | * bin.c | 234 | * bin.c |
235 | */ | 235 | */ |
236 | extern const struct file_operations bin_fops; | 236 | extern const struct file_operations bin_fops; |
237 | void unmap_bin_file(struct sysfs_dirent *attr_sd); | 237 | void unmap_bin_file(struct sysfs_dirent *attr_sd); |
238 | 238 | ||
239 | /* | 239 | /* |
240 | * symlink.c | 240 | * symlink.c |
241 | */ | 241 | */ |
242 | extern const struct inode_operations sysfs_symlink_inode_operations; | 242 | extern const struct inode_operations sysfs_symlink_inode_operations; |
243 | 243 |