Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* devfs (Device FileSystem) driver. |
2 | ||
3 | Copyright (C) 1998-2002 Richard Gooch | |
4 | ||
5 | This library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2 of the License, or (at your option) any later version. | |
9 | ||
10 | This library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with this library; if not, write to the Free | |
17 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | ||
19 | Richard Gooch may be reached by email at rgooch@atnf.csiro.au | |
20 | The postal address is: | |
21 | Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. | |
22 | ||
23 | ChangeLog | |
24 | ||
25 | 19980110 Richard Gooch <rgooch@atnf.csiro.au> | |
26 | Original version. | |
27 | v0.1 | |
28 | 19980111 Richard Gooch <rgooch@atnf.csiro.au> | |
29 | Created per-fs inode table rather than using inode->u.generic_ip | |
30 | v0.2 | |
31 | 19980111 Richard Gooch <rgooch@atnf.csiro.au> | |
32 | Created .epoch inode which has a ctime of 0. | |
33 | Fixed loss of named pipes when dentries lost. | |
34 | Fixed loss of inode data when devfs_register() follows mknod(). | |
35 | v0.3 | |
36 | 19980111 Richard Gooch <rgooch@atnf.csiro.au> | |
37 | Fix for when compiling with CONFIG_KERNELD. | |
38 | 19980112 Richard Gooch <rgooch@atnf.csiro.au> | |
39 | Fix for readdir() which sometimes didn't show entries. | |
40 | Added <<tolerant>> option to <devfs_register>. | |
41 | v0.4 | |
42 | 19980113 Richard Gooch <rgooch@atnf.csiro.au> | |
43 | Created <devfs_fill_file> function. | |
44 | v0.5 | |
45 | 19980115 Richard Gooch <rgooch@atnf.csiro.au> | |
46 | Added subdirectory support. Major restructuring. | |
47 | 19980116 Richard Gooch <rgooch@atnf.csiro.au> | |
48 | Fixed <find_by_dev> to not search major=0,minor=0. | |
49 | Added symlink support. | |
50 | v0.6 | |
51 | 19980120 Richard Gooch <rgooch@atnf.csiro.au> | |
52 | Created <devfs_mk_dir> function and support directory unregister | |
53 | 19980120 Richard Gooch <rgooch@atnf.csiro.au> | |
54 | Auto-ownership uses real uid/gid rather than effective uid/gid. | |
55 | v0.7 | |
56 | 19980121 Richard Gooch <rgooch@atnf.csiro.au> | |
57 | Supported creation of sockets. | |
58 | v0.8 | |
59 | 19980122 Richard Gooch <rgooch@atnf.csiro.au> | |
60 | Added DEVFS_FL_HIDE_UNREG flag. | |
61 | Interface change to <devfs_mk_symlink>. | |
62 | Created <devfs_symlink> to support symlink(2). | |
63 | v0.9 | |
64 | 19980123 Richard Gooch <rgooch@atnf.csiro.au> | |
65 | Added check to <devfs_fill_file> to check inode is in devfs. | |
66 | Added optional traversal of symlinks. | |
67 | v0.10 | |
68 | 19980124 Richard Gooch <rgooch@atnf.csiro.au> | |
69 | Created <devfs_get_flags> and <devfs_set_flags>. | |
70 | v0.11 | |
71 | 19980125 C. Scott Ananian <cananian@alumni.princeton.edu> | |
72 | Created <devfs_find_handle>. | |
73 | 19980125 Richard Gooch <rgooch@atnf.csiro.au> | |
74 | Allow removal of symlinks. | |
75 | v0.12 | |
76 | 19980125 Richard Gooch <rgooch@atnf.csiro.au> | |
77 | Created <devfs_set_symlink_destination>. | |
78 | 19980126 Richard Gooch <rgooch@atnf.csiro.au> | |
79 | Moved DEVFS_SUPER_MAGIC into header file. | |
80 | Added DEVFS_FL_HIDE flag. | |
81 | Created <devfs_get_maj_min>. | |
82 | Created <devfs_get_handle_from_inode>. | |
83 | Fixed minor bug in <find_by_dev>. | |
84 | 19980127 Richard Gooch <rgooch@atnf.csiro.au> | |
85 | Changed interface to <find_by_dev>, <find_entry>, | |
86 | <devfs_unregister>, <devfs_fill_file> and <devfs_find_handle>. | |
87 | Fixed inode times when symlink created with symlink(2). | |
88 | v0.13 | |
89 | 19980129 C. Scott Ananian <cananian@alumni.princeton.edu> | |
90 | Exported <devfs_set_symlink_destination>, <devfs_get_maj_min> | |
91 | and <devfs_get_handle_from_inode>. | |
92 | 19980129 Richard Gooch <rgooch@atnf.csiro.au> | |
93 | Created <devfs_unlink> to support unlink(2). | |
94 | v0.14 | |
95 | 19980129 Richard Gooch <rgooch@atnf.csiro.au> | |
96 | Fixed kerneld support for entries in devfs subdirectories. | |
97 | 19980130 Richard Gooch <rgooch@atnf.csiro.au> | |
98 | Bugfixes in <call_kerneld>. | |
99 | v0.15 | |
100 | 19980207 Richard Gooch <rgooch@atnf.csiro.au> | |
101 | Call kerneld when looking up unregistered entries. | |
102 | v0.16 | |
103 | 19980326 Richard Gooch <rgooch@atnf.csiro.au> | |
104 | Modified interface to <devfs_find_handle> for symlink traversal. | |
105 | v0.17 | |
106 | 19980331 Richard Gooch <rgooch@atnf.csiro.au> | |
107 | Fixed persistence bug with device numbers for manually created | |
108 | device files. | |
109 | Fixed problem with recreating symlinks with different content. | |
110 | v0.18 | |
111 | 19980401 Richard Gooch <rgooch@atnf.csiro.au> | |
112 | Changed to CONFIG_KMOD. | |
113 | Hide entries which are manually unlinked. | |
114 | Always invalidate devfs dentry cache when registering entries. | |
115 | Created <devfs_rmdir> to support rmdir(2). | |
116 | Ensure directories created by <devfs_mk_dir> are visible. | |
117 | v0.19 | |
118 | 19980402 Richard Gooch <rgooch@atnf.csiro.au> | |
119 | Invalidate devfs dentry cache when making directories. | |
120 | Invalidate devfs dentry cache when removing entries. | |
121 | Fixed persistence bug with fifos. | |
122 | v0.20 | |
123 | 19980421 Richard Gooch <rgooch@atnf.csiro.au> | |
124 | Print process command when debugging kerneld/kmod. | |
125 | Added debugging for register/unregister/change operations. | |
126 | 19980422 Richard Gooch <rgooch@atnf.csiro.au> | |
127 | Added "devfs=" boot options. | |
128 | v0.21 | |
129 | 19980426 Richard Gooch <rgooch@atnf.csiro.au> | |
130 | No longer lock/unlock superblock in <devfs_put_super>. | |
131 | Drop negative dentries when they are released. | |
132 | Manage dcache more efficiently. | |
133 | v0.22 | |
134 | 19980427 Richard Gooch <rgooch@atnf.csiro.au> | |
135 | Added DEVFS_FL_AUTO_DEVNUM flag. | |
136 | v0.23 | |
137 | 19980430 Richard Gooch <rgooch@atnf.csiro.au> | |
138 | No longer set unnecessary methods. | |
139 | v0.24 | |
140 | 19980504 Richard Gooch <rgooch@atnf.csiro.au> | |
141 | Added PID display to <call_kerneld> debugging message. | |
142 | Added "after" debugging message to <call_kerneld>. | |
143 | 19980519 Richard Gooch <rgooch@atnf.csiro.au> | |
144 | Added "diread" and "diwrite" boot options. | |
145 | 19980520 Richard Gooch <rgooch@atnf.csiro.au> | |
146 | Fixed persistence problem with permissions. | |
147 | v0.25 | |
148 | 19980602 Richard Gooch <rgooch@atnf.csiro.au> | |
149 | Support legacy device nodes. | |
150 | Fixed bug where recreated inodes were hidden. | |
151 | v0.26 | |
152 | 19980602 Richard Gooch <rgooch@atnf.csiro.au> | |
153 | Improved debugging in <get_vfs_inode>. | |
154 | 19980607 Richard Gooch <rgooch@atnf.csiro.au> | |
155 | No longer free old dentries in <devfs_mk_dir>. | |
156 | Free all dentries for a given entry when deleting inodes. | |
157 | v0.27 | |
158 | 19980627 Richard Gooch <rgooch@atnf.csiro.au> | |
159 | Limit auto-device numbering to majors 128 to 239. | |
160 | v0.28 | |
161 | 19980629 Richard Gooch <rgooch@atnf.csiro.au> | |
162 | Fixed inode times persistence problem. | |
163 | v0.29 | |
164 | 19980704 Richard Gooch <rgooch@atnf.csiro.au> | |
165 | Fixed spelling in <devfs_readlink> debug. | |
166 | Fixed bug in <devfs_setup> parsing "dilookup". | |
167 | v0.30 | |
168 | 19980705 Richard Gooch <rgooch@atnf.csiro.au> | |
169 | Fixed devfs inode leak when manually recreating inodes. | |
170 | Fixed permission persistence problem when recreating inodes. | |
171 | v0.31 | |
172 | 19980727 Richard Gooch <rgooch@atnf.csiro.au> | |
173 | Removed harmless "unused variable" compiler warning. | |
174 | Fixed modes for manually recreated device nodes. | |
175 | v0.32 | |
176 | 19980728 Richard Gooch <rgooch@atnf.csiro.au> | |
177 | Added NULL devfs inode warning in <devfs_read_inode>. | |
178 | Force all inode nlink values to 1. | |
179 | v0.33 | |
180 | 19980730 Richard Gooch <rgooch@atnf.csiro.au> | |
181 | Added "dimknod" boot option. | |
182 | Set inode nlink to 0 when freeing dentries. | |
183 | Fixed modes for manually recreated symlinks. | |
184 | v0.34 | |
185 | 19980802 Richard Gooch <rgooch@atnf.csiro.au> | |
186 | Fixed bugs in recreated directories and symlinks. | |
187 | v0.35 | |
188 | 19980806 Richard Gooch <rgooch@atnf.csiro.au> | |
189 | Fixed bugs in recreated device nodes. | |
190 | 19980807 Richard Gooch <rgooch@atnf.csiro.au> | |
191 | Fixed bug in currently unused <devfs_get_handle_from_inode>. | |
192 | Defined new <devfs_handle_t> type. | |
193 | Improved debugging when getting entries. | |
194 | Fixed bug where directories could be emptied. | |
195 | v0.36 | |
196 | 19980809 Richard Gooch <rgooch@atnf.csiro.au> | |
197 | Replaced dummy .epoch inode with .devfsd character device. | |
198 | 19980810 Richard Gooch <rgooch@atnf.csiro.au> | |
199 | Implemented devfsd protocol revision 0. | |
200 | v0.37 | |
201 | 19980819 Richard Gooch <rgooch@atnf.csiro.au> | |
202 | Added soothing message to warning in <devfs_d_iput>. | |
203 | v0.38 | |
204 | 19980829 Richard Gooch <rgooch@atnf.csiro.au> | |
205 | Use GCC extensions for structure initialisations. | |
206 | Implemented async open notification. | |
207 | Incremented devfsd protocol revision to 1. | |
208 | v0.39 | |
209 | 19980908 Richard Gooch <rgooch@atnf.csiro.au> | |
210 | Moved async open notification to end of <devfs_open>. | |
211 | v0.40 | |
212 | 19980910 Richard Gooch <rgooch@atnf.csiro.au> | |
213 | Prepended "/dev/" to module load request. | |
214 | Renamed <call_kerneld> to <call_kmod>. | |
215 | v0.41 | |
216 | 19980910 Richard Gooch <rgooch@atnf.csiro.au> | |
217 | Fixed typo "AYSNC" -> "ASYNC". | |
218 | v0.42 | |
219 | 19980910 Richard Gooch <rgooch@atnf.csiro.au> | |
220 | Added open flag for files. | |
221 | v0.43 | |
222 | 19980927 Richard Gooch <rgooch@atnf.csiro.au> | |
223 | Set i_blocks=0 and i_blksize=1024 in <devfs_read_inode>. | |
224 | v0.44 | |
225 | 19981005 Richard Gooch <rgooch@atnf.csiro.au> | |
226 | Added test for empty <<name>> in <devfs_find_handle>. | |
227 | Renamed <generate_path> to <devfs_generate_path> and published. | |
228 | v0.45 | |
229 | 19981006 Richard Gooch <rgooch@atnf.csiro.au> | |
230 | Created <devfs_get_fops>. | |
231 | v0.46 | |
232 | 19981007 Richard Gooch <rgooch@atnf.csiro.au> | |
233 | Limit auto-device numbering to majors 144 to 239. | |
234 | v0.47 | |
235 | 19981010 Richard Gooch <rgooch@atnf.csiro.au> | |
236 | Updated <devfs_follow_link> for VFS change in 2.1.125. | |
237 | v0.48 | |
238 | 19981022 Richard Gooch <rgooch@atnf.csiro.au> | |
239 | Created DEVFS_ FL_COMPAT flag. | |
240 | v0.49 | |
241 | 19981023 Richard Gooch <rgooch@atnf.csiro.au> | |
242 | Created "nocompat" boot option. | |
243 | v0.50 | |
244 | 19981025 Richard Gooch <rgooch@atnf.csiro.au> | |
245 | Replaced "mount" boot option with "nomount". | |
246 | v0.51 | |
247 | 19981110 Richard Gooch <rgooch@atnf.csiro.au> | |
248 | Created "only" boot option. | |
249 | v0.52 | |
250 | 19981112 Richard Gooch <rgooch@atnf.csiro.au> | |
251 | Added DEVFS_FL_REMOVABLE flag. | |
252 | v0.53 | |
253 | 19981114 Richard Gooch <rgooch@atnf.csiro.au> | |
254 | Only call <scan_dir_for_removable> on first call to | |
255 | <devfs_readdir>. | |
256 | v0.54 | |
257 | 19981205 Richard Gooch <rgooch@atnf.csiro.au> | |
258 | Updated <devfs_rmdir> for VFS change in 2.1.131. | |
259 | v0.55 | |
260 | 19981218 Richard Gooch <rgooch@atnf.csiro.au> | |
261 | Created <devfs_mk_compat>. | |
262 | 19981220 Richard Gooch <rgooch@atnf.csiro.au> | |
263 | Check for partitions on removable media in <devfs_lookup>. | |
264 | v0.56 | |
265 | 19990118 Richard Gooch <rgooch@atnf.csiro.au> | |
266 | Added support for registering regular files. | |
267 | Created <devfs_set_file_size>. | |
268 | Update devfs inodes from entries if not changed through FS. | |
269 | v0.57 | |
270 | 19990124 Richard Gooch <rgooch@atnf.csiro.au> | |
271 | Fixed <devfs_fill_file> to only initialise temporary inodes. | |
272 | Trap for NULL fops in <devfs_register>. | |
273 | Return -ENODEV in <devfs_fill_file> for non-driver inodes. | |
274 | v0.58 | |
275 | 19990126 Richard Gooch <rgooch@atnf.csiro.au> | |
276 | Switched from PATH_MAX to DEVFS_PATHLEN. | |
277 | v0.59 | |
278 | 19990127 Richard Gooch <rgooch@atnf.csiro.au> | |
279 | Created "nottycompat" boot option. | |
280 | v0.60 | |
281 | 19990318 Richard Gooch <rgooch@atnf.csiro.au> | |
282 | Fixed <devfsd_read> to not overrun event buffer. | |
283 | v0.61 | |
284 | 19990329 Richard Gooch <rgooch@atnf.csiro.au> | |
285 | Created <devfs_auto_unregister>. | |
286 | v0.62 | |
287 | 19990330 Richard Gooch <rgooch@atnf.csiro.au> | |
288 | Don't return unregistred entries in <devfs_find_handle>. | |
289 | Panic in <devfs_unregister> if entry unregistered. | |
290 | 19990401 Richard Gooch <rgooch@atnf.csiro.au> | |
291 | Don't panic in <devfs_auto_unregister> for duplicates. | |
292 | v0.63 | |
293 | 19990402 Richard Gooch <rgooch@atnf.csiro.au> | |
294 | Don't unregister already unregistered entries in <unregister>. | |
295 | v0.64 | |
296 | 19990510 Richard Gooch <rgooch@atnf.csiro.au> | |
297 | Disable warning messages when unable to read partition table for | |
298 | removable media. | |
299 | v0.65 | |
300 | 19990512 Richard Gooch <rgooch@atnf.csiro.au> | |
301 | Updated <devfs_lookup> for VFS change in 2.3.1-pre1. | |
302 | Created "oops-on-panic" boot option. | |
303 | Improved debugging in <devfs_register> and <devfs_unregister>. | |
304 | v0.66 | |
305 | 19990519 Richard Gooch <rgooch@atnf.csiro.au> | |
306 | Added documentation for some functions. | |
307 | 19990525 Richard Gooch <rgooch@atnf.csiro.au> | |
308 | Removed "oops-on-panic" boot option: now always Oops. | |
309 | v0.67 | |
310 | 19990531 Richard Gooch <rgooch@atnf.csiro.au> | |
311 | Improved debugging in <devfs_register>. | |
312 | v0.68 | |
313 | 19990604 Richard Gooch <rgooch@atnf.csiro.au> | |
314 | Added "diunlink" and "nokmod" boot options. | |
315 | Removed superfluous warning message in <devfs_d_iput>. | |
316 | v0.69 | |
317 | 19990611 Richard Gooch <rgooch@atnf.csiro.au> | |
318 | Took account of change to <d_alloc_root>. | |
319 | v0.70 | |
320 | 19990614 Richard Gooch <rgooch@atnf.csiro.au> | |
321 | Created separate event queue for each mounted devfs. | |
322 | Removed <devfs_invalidate_dcache>. | |
323 | Created new ioctl()s. | |
324 | Incremented devfsd protocol revision to 3. | |
325 | Fixed bug when re-creating directories: contents were lost. | |
326 | Block access to inodes until devfsd updates permissions. | |
327 | 19990615 Richard Gooch <rgooch@atnf.csiro.au> | |
328 | Support 2.2.x kernels. | |
329 | v0.71 | |
330 | 19990623 Richard Gooch <rgooch@atnf.csiro.au> | |
331 | Switched to sending process uid/gid to devfsd. | |
332 | Renamed <call_kmod> to <try_modload>. | |
333 | Added DEVFSD_NOTIFY_LOOKUP event. | |
334 | 19990624 Richard Gooch <rgooch@atnf.csiro.au> | |
335 | Added DEVFSD_NOTIFY_CHANGE event. | |
336 | Incremented devfsd protocol revision to 4. | |
337 | v0.72 | |
338 | 19990713 Richard Gooch <rgooch@atnf.csiro.au> | |
339 | Return EISDIR rather than EINVAL for read(2) on directories. | |
340 | v0.73 | |
341 | 19990809 Richard Gooch <rgooch@atnf.csiro.au> | |
342 | Changed <devfs_setup> to new __init scheme. | |
343 | v0.74 | |
344 | 19990901 Richard Gooch <rgooch@atnf.csiro.au> | |
345 | Changed remaining function declarations to new __init scheme. | |
346 | v0.75 | |
347 | 19991013 Richard Gooch <rgooch@atnf.csiro.au> | |
348 | Created <devfs_get_info>, <devfs_set_info>, | |
349 | <devfs_get_first_child> and <devfs_get_next_sibling>. | |
350 | Added <<dir>> parameter to <devfs_register>, <devfs_mk_compat>, | |
351 | <devfs_mk_dir> and <devfs_find_handle>. | |
352 | Work sponsored by SGI. | |
353 | v0.76 | |
354 | 19991017 Richard Gooch <rgooch@atnf.csiro.au> | |
355 | Allow multiple unregistrations. | |
356 | Work sponsored by SGI. | |
357 | v0.77 | |
358 | 19991026 Richard Gooch <rgooch@atnf.csiro.au> | |
359 | Added major and minor number to devfsd protocol. | |
360 | Incremented devfsd protocol revision to 5. | |
361 | Work sponsored by SGI. | |
362 | v0.78 | |
363 | 19991030 Richard Gooch <rgooch@atnf.csiro.au> | |
364 | Support info pointer for all devfs entry types. | |
365 | Added <<info>> parameter to <devfs_mk_dir> and | |
366 | <devfs_mk_symlink>. | |
367 | Work sponsored by SGI. | |
368 | v0.79 | |
369 | 19991031 Richard Gooch <rgooch@atnf.csiro.au> | |
370 | Support "../" when searching devfs namespace. | |
371 | Work sponsored by SGI. | |
372 | v0.80 | |
373 | 19991101 Richard Gooch <rgooch@atnf.csiro.au> | |
374 | Created <devfs_get_unregister_slave>. | |
375 | Work sponsored by SGI. | |
376 | v0.81 | |
377 | 19991103 Richard Gooch <rgooch@atnf.csiro.au> | |
378 | Exported <devfs_get_parent>. | |
379 | Work sponsored by SGI. | |
380 | v0.82 | |
381 | 19991104 Richard Gooch <rgooch@atnf.csiro.au> | |
382 | Removed unused <devfs_set_symlink_destination>. | |
383 | 19991105 Richard Gooch <rgooch@atnf.csiro.au> | |
384 | Do not hide entries from devfsd or children. | |
385 | Removed DEVFS_ FL_TTY_COMPAT flag. | |
386 | Removed "nottycompat" boot option. | |
387 | Removed <devfs_mk_compat>. | |
388 | Work sponsored by SGI. | |
389 | v0.83 | |
390 | 19991107 Richard Gooch <rgooch@atnf.csiro.au> | |
391 | Added DEVFS_FL_WAIT flag. | |
392 | Work sponsored by SGI. | |
393 | v0.84 | |
394 | 19991107 Richard Gooch <rgooch@atnf.csiro.au> | |
395 | Support new "disc" naming scheme in <get_removable_partition>. | |
396 | Allow NULL fops in <devfs_register>. | |
397 | Work sponsored by SGI. | |
398 | v0.85 | |
399 | 19991110 Richard Gooch <rgooch@atnf.csiro.au> | |
400 | Fall back to major table if NULL fops given to <devfs_register>. | |
401 | Work sponsored by SGI. | |
402 | v0.86 | |
403 | 19991204 Richard Gooch <rgooch@atnf.csiro.au> | |
404 | Support fifos when unregistering. | |
405 | Work sponsored by SGI. | |
406 | v0.87 | |
407 | 19991209 Richard Gooch <rgooch@atnf.csiro.au> | |
408 | Removed obsolete DEVFS_ FL_COMPAT and DEVFS_ FL_TOLERANT flags. | |
409 | Work sponsored by SGI. | |
410 | v0.88 | |
411 | 19991214 Richard Gooch <rgooch@atnf.csiro.au> | |
412 | Removed kmod support. | |
413 | Work sponsored by SGI. | |
414 | v0.89 | |
415 | 19991216 Richard Gooch <rgooch@atnf.csiro.au> | |
416 | Improved debugging in <get_vfs_inode>. | |
417 | Ensure dentries created by devfsd will be cleaned up. | |
418 | Work sponsored by SGI. | |
419 | v0.90 | |
420 | 19991223 Richard Gooch <rgooch@atnf.csiro.au> | |
421 | Created <devfs_get_name>. | |
422 | Work sponsored by SGI. | |
423 | v0.91 | |
424 | 20000203 Richard Gooch <rgooch@atnf.csiro.au> | |
425 | Ported to kernel 2.3.42. | |
426 | Removed <devfs_fill_file>. | |
427 | Work sponsored by SGI. | |
428 | v0.92 | |
429 | 20000306 Richard Gooch <rgooch@atnf.csiro.au> | |
430 | Added DEVFS_ FL_NO_PERSISTENCE flag. | |
431 | Removed unnecessary call to <update_devfs_inode_from_entry> in | |
432 | <devfs_readdir>. | |
433 | Work sponsored by SGI. | |
434 | v0.93 | |
435 | 20000413 Richard Gooch <rgooch@atnf.csiro.au> | |
436 | Set inode->i_size to correct size for symlinks. | |
437 | 20000414 Richard Gooch <rgooch@atnf.csiro.au> | |
438 | Only give lookup() method to directories to comply with new VFS | |
439 | assumptions. | |
440 | Work sponsored by SGI. | |
441 | 20000415 Richard Gooch <rgooch@atnf.csiro.au> | |
442 | Remove unnecessary tests in symlink methods. | |
443 | Don't kill existing block ops in <devfs_read_inode>. | |
444 | Work sponsored by SGI. | |
445 | v0.94 | |
446 | 20000424 Richard Gooch <rgooch@atnf.csiro.au> | |
447 | Don't create missing directories in <devfs_find_handle>. | |
448 | Work sponsored by SGI. | |
449 | v0.95 | |
450 | 20000430 Richard Gooch <rgooch@atnf.csiro.au> | |
451 | Added CONFIG_DEVFS_MOUNT. | |
452 | Work sponsored by SGI. | |
453 | v0.96 | |
454 | 20000608 Richard Gooch <rgooch@atnf.csiro.au> | |
455 | Disabled multi-mount capability (use VFS bindings instead). | |
456 | Work sponsored by SGI. | |
457 | v0.97 | |
458 | 20000610 Richard Gooch <rgooch@atnf.csiro.au> | |
459 | Switched to FS_SINGLE to disable multi-mounts. | |
460 | 20000612 Richard Gooch <rgooch@atnf.csiro.au> | |
461 | Removed module support. | |
462 | Removed multi-mount code. | |
463 | Removed compatibility macros: VFS has changed too much. | |
464 | Work sponsored by SGI. | |
465 | v0.98 | |
466 | 20000614 Richard Gooch <rgooch@atnf.csiro.au> | |
467 | Merged devfs inode into devfs entry. | |
468 | Work sponsored by SGI. | |
469 | v0.99 | |
470 | 20000619 Richard Gooch <rgooch@atnf.csiro.au> | |
471 | Removed dead code in <devfs_register> which used to call | |
472 | <free_dentries>. | |
473 | Work sponsored by SGI. | |
474 | v0.100 | |
475 | 20000621 Richard Gooch <rgooch@atnf.csiro.au> | |
476 | Changed interface to <devfs_register>. | |
477 | Work sponsored by SGI. | |
478 | v0.101 | |
479 | 20000622 Richard Gooch <rgooch@atnf.csiro.au> | |
480 | Simplified interface to <devfs_mk_symlink> and <devfs_mk_dir>. | |
481 | Simplified interface to <devfs_find_handle>. | |
482 | Work sponsored by SGI. | |
483 | v0.102 | |
484 | 20010519 Richard Gooch <rgooch@atnf.csiro.au> | |
485 | Ensure <devfs_generate_path> terminates string for root entry. | |
486 | Exported <devfs_get_name> to modules. | |
487 | 20010520 Richard Gooch <rgooch@atnf.csiro.au> | |
488 | Make <devfs_mk_symlink> send events to devfsd. | |
489 | Cleaned up option processing in <devfs_setup>. | |
490 | 20010521 Richard Gooch <rgooch@atnf.csiro.au> | |
491 | Fixed bugs in handling symlinks: could leak or cause Oops. | |
492 | 20010522 Richard Gooch <rgooch@atnf.csiro.au> | |
493 | Cleaned up directory handling by separating fops. | |
494 | v0.103 | |
495 | 20010601 Richard Gooch <rgooch@atnf.csiro.au> | |
496 | Fixed handling of inverted options in <devfs_setup>. | |
497 | v0.104 | |
498 | 20010604 Richard Gooch <rgooch@atnf.csiro.au> | |
499 | Adjusted <try_modload> to account for <devfs_generate_path> fix. | |
500 | v0.105 | |
501 | 20010617 Richard Gooch <rgooch@atnf.csiro.au> | |
502 | Answered question posed by Al Viro and removed his comments. | |
503 | Moved setting of registered flag after other fields are changed. | |
504 | Fixed race between <devfsd_close> and <devfsd_notify_one>. | |
505 | Global VFS changes added bogus BKL to <devfsd_close>: removed. | |
506 | Widened locking in <devfs_readlink> and <devfs_follow_link>. | |
507 | Replaced <devfsd_read> stack usage with <devfsd_ioctl> kmalloc. | |
508 | Simplified locking in <devfsd_ioctl> and fixed memory leak. | |
509 | v0.106 | |
510 | 20010709 Richard Gooch <rgooch@atnf.csiro.au> | |
511 | Removed broken devnum allocation and use <devfs_alloc_devnum>. | |
512 | Fixed old devnum leak by calling new <devfs_dealloc_devnum>. | |
513 | v0.107 | |
514 | 20010712 Richard Gooch <rgooch@atnf.csiro.au> | |
515 | Fixed bug in <devfs_setup> which could hang boot process. | |
516 | v0.108 | |
517 | 20010730 Richard Gooch <rgooch@atnf.csiro.au> | |
518 | Added DEVFSD_NOTIFY_DELETE event. | |
519 | 20010801 Richard Gooch <rgooch@atnf.csiro.au> | |
520 | Removed #include <asm/segment.h>. | |
521 | v0.109 | |
522 | 20010807 Richard Gooch <rgooch@atnf.csiro.au> | |
523 | Fixed inode table races by removing it and using | |
524 | inode->u.generic_ip instead. | |
525 | Moved <devfs_read_inode> into <get_vfs_inode>. | |
526 | Moved <devfs_write_inode> into <devfs_notify_change>. | |
527 | v0.110 | |
528 | 20010808 Richard Gooch <rgooch@atnf.csiro.au> | |
529 | Fixed race in <devfs_do_symlink> for uni-processor. | |
530 | v0.111 | |
531 | 20010818 Richard Gooch <rgooch@atnf.csiro.au> | |
532 | Removed remnant of multi-mount support in <devfs_mknod>. | |
533 | Removed unused DEVFS_FL_SHOW_UNREG flag. | |
534 | v0.112 | |
535 | 20010820 Richard Gooch <rgooch@atnf.csiro.au> | |
536 | Removed nlink field from struct devfs_inode. | |
537 | v0.113 | |
538 | 20010823 Richard Gooch <rgooch@atnf.csiro.au> | |
539 | Replaced BKL with global rwsem to protect symlink data (quick | |
540 | and dirty hack). | |
541 | v0.114 | |
542 | 20010827 Richard Gooch <rgooch@atnf.csiro.au> | |
543 | Replaced global rwsem for symlink with per-link refcount. | |
544 | v0.115 | |
545 | 20010919 Richard Gooch <rgooch@atnf.csiro.au> | |
546 | Set inode->i_mapping->a_ops for block nodes in <get_vfs_inode>. | |
547 | v0.116 | |
548 | 20011008 Richard Gooch <rgooch@atnf.csiro.au> | |
549 | Fixed overrun in <devfs_link> by removing function (not needed). | |
550 | 20011009 Richard Gooch <rgooch@atnf.csiro.au> | |
551 | Fixed buffer underrun in <try_modload>. | |
552 | 20011029 Richard Gooch <rgooch@atnf.csiro.au> | |
553 | Fixed race in <devfsd_ioctl> when setting event mask. | |
554 | 20011114 Richard Gooch <rgooch@atnf.csiro.au> | |
555 | First release of new locking code. | |
556 | v1.0 | |
557 | 20011117 Richard Gooch <rgooch@atnf.csiro.au> | |
558 | Discard temporary buffer, now use "%s" for dentry names. | |
559 | 20011118 Richard Gooch <rgooch@atnf.csiro.au> | |
560 | Don't generate path in <try_modload>: use fake entry instead. | |
561 | Use "existing" directory in <_devfs_make_parent_for_leaf>. | |
562 | 20011122 Richard Gooch <rgooch@atnf.csiro.au> | |
563 | Use slab cache rather than fixed buffer for devfsd events. | |
564 | v1.1 | |
565 | 20011125 Richard Gooch <rgooch@atnf.csiro.au> | |
566 | Send DEVFSD_NOTIFY_REGISTERED events in <devfs_mk_dir>. | |
567 | 20011127 Richard Gooch <rgooch@atnf.csiro.au> | |
568 | Fixed locking bug in <devfs_d_revalidate_wait> due to typo. | |
569 | Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from | |
570 | devfsd or children. | |
571 | v1.2 | |
572 | 20011202 Richard Gooch <rgooch@atnf.csiro.au> | |
573 | Fixed bug in <devfsd_read>: was dereferencing freed pointer. | |
574 | v1.3 | |
575 | 20011203 Richard Gooch <rgooch@atnf.csiro.au> | |
576 | Fixed bug in <devfsd_close>: was dereferencing freed pointer. | |
577 | Added process group check for devfsd privileges. | |
578 | v1.4 | |
579 | 20011204 Richard Gooch <rgooch@atnf.csiro.au> | |
580 | Use SLAB_ATOMIC in <devfsd_notify_de> from <devfs_d_delete>. | |
581 | v1.5 | |
582 | 20011211 Richard Gooch <rgooch@atnf.csiro.au> | |
583 | Return old entry in <devfs_mk_dir> for 2.4.x kernels. | |
584 | 20011212 Richard Gooch <rgooch@atnf.csiro.au> | |
585 | Increment refcount on module in <check_disc_changed>. | |
586 | 20011215 Richard Gooch <rgooch@atnf.csiro.au> | |
587 | Created <devfs_get_handle> and exported <devfs_put>. | |
588 | Increment refcount on module in <devfs_get_ops>. | |
589 | Created <devfs_put_ops>. | |
590 | v1.6 | |
591 | 20011216 Richard Gooch <rgooch@atnf.csiro.au> | |
592 | Added poisoning to <devfs_put>. | |
593 | Improved debugging messages. | |
594 | v1.7 | |
595 | 20011221 Richard Gooch <rgooch@atnf.csiro.au> | |
596 | Corrected (made useful) debugging message in <unregister>. | |
597 | Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs> | |
598 | 20011224 Richard Gooch <rgooch@atnf.csiro.au> | |
599 | Added magic number to guard against scribbling drivers. | |
600 | 20011226 Richard Gooch <rgooch@atnf.csiro.au> | |
601 | Only return old entry in <devfs_mk_dir> if a directory. | |
602 | Defined macros for error and debug messages. | |
603 | v1.8 | |
604 | 20020113 Richard Gooch <rgooch@atnf.csiro.au> | |
605 | Fixed (rare, old) race in <devfs_lookup>. | |
606 | v1.9 | |
607 | 20020120 Richard Gooch <rgooch@atnf.csiro.au> | |
608 | Fixed deadlock bug in <devfs_d_revalidate_wait>. | |
609 | Tag VFS deletable in <devfs_mk_symlink> if handle ignored. | |
610 | v1.10 | |
611 | 20020129 Richard Gooch <rgooch@atnf.csiro.au> | |
612 | Added KERN_* to remaining messages. | |
613 | Cleaned up declaration of <stat_read>. | |
614 | v1.11 | |
615 | 20020219 Richard Gooch <rgooch@atnf.csiro.au> | |
616 | Changed <devfs_rmdir> to allow later additions if not yet empty. | |
617 | v1.12 | |
618 | 20020406 Richard Gooch <rgooch@atnf.csiro.au> | |
619 | Removed silently introduced calls to lock_kernel() and | |
620 | unlock_kernel() due to recent VFS locking changes. BKL isn't | |
621 | required in devfs. | |
622 | v1.13 | |
623 | 20020428 Richard Gooch <rgooch@atnf.csiro.au> | |
624 | Removed 2.4.x compatibility code. | |
625 | v1.14 | |
626 | 20020510 Richard Gooch <rgooch@atnf.csiro.au> | |
627 | Added BKL to <devfs_open> because drivers still need it. | |
628 | v1.15 | |
629 | 20020512 Richard Gooch <rgooch@atnf.csiro.au> | |
630 | Protected <scan_dir_for_removable> and <get_removable_partition> | |
631 | from changing directory contents. | |
632 | v1.16 | |
633 | 20020514 Richard Gooch <rgooch@atnf.csiro.au> | |
634 | Minor cleanup of <scan_dir_for_removable>. | |
635 | v1.17 | |
636 | 20020721 Richard Gooch <rgooch@atnf.csiro.au> | |
637 | Switched to ISO C structure field initialisers. | |
638 | Switch to set_current_state() and move before add_wait_queue(). | |
639 | 20020722 Richard Gooch <rgooch@atnf.csiro.au> | |
640 | Fixed devfs entry leak in <devfs_readdir> when *readdir fails. | |
641 | v1.18 | |
642 | 20020725 Richard Gooch <rgooch@atnf.csiro.au> | |
643 | Created <devfs_find_and_unregister>. | |
644 | v1.19 | |
645 | 20020728 Richard Gooch <rgooch@atnf.csiro.au> | |
646 | Removed deprecated <devfs_find_handle>. | |
647 | v1.20 | |
648 | 20020820 Richard Gooch <rgooch@atnf.csiro.au> | |
649 | Fixed module unload race in <devfs_open>. | |
650 | v1.21 | |
651 | 20021013 Richard Gooch <rgooch@atnf.csiro.au> | |
652 | Removed DEVFS_ FL_AUTO_OWNER. | |
653 | Switched lingering structure field initialiser to ISO C. | |
654 | Added locking when updating FCB flags. | |
655 | v1.22 | |
656 | */ | |
657 | #include <linux/types.h> | |
658 | #include <linux/errno.h> | |
659 | #include <linux/time.h> | |
660 | #include <linux/tty.h> | |
661 | #include <linux/timer.h> | |
662 | #include <linux/config.h> | |
663 | #include <linux/kernel.h> | |
664 | #include <linux/wait.h> | |
665 | #include <linux/string.h> | |
666 | #include <linux/slab.h> | |
667 | #include <linux/ioport.h> | |
668 | #include <linux/delay.h> | |
669 | #include <linux/ctype.h> | |
670 | #include <linux/mm.h> | |
671 | #include <linux/module.h> | |
672 | #include <linux/init.h> | |
673 | #include <linux/devfs_fs.h> | |
674 | #include <linux/devfs_fs_kernel.h> | |
675 | #include <linux/smp_lock.h> | |
676 | #include <linux/smp.h> | |
677 | #include <linux/rwsem.h> | |
678 | #include <linux/sched.h> | |
679 | #include <linux/namei.h> | |
680 | #include <linux/bitops.h> | |
681 | ||
682 | #include <asm/uaccess.h> | |
683 | #include <asm/io.h> | |
684 | #include <asm/processor.h> | |
685 | #include <asm/system.h> | |
686 | #include <asm/pgtable.h> | |
687 | #include <asm/atomic.h> | |
688 | ||
689 | #define DEVFS_VERSION "2004-01-31" | |
690 | ||
691 | #define DEVFS_NAME "devfs" | |
692 | ||
693 | #define FIRST_INODE 1 | |
694 | ||
695 | #define STRING_LENGTH 256 | |
696 | #define FAKE_BLOCK_SIZE 1024 | |
697 | #define POISON_PTR ( *(void **) poison_array ) | |
698 | #define MAGIC_VALUE 0x327db823 | |
699 | ||
700 | #ifndef TRUE | |
701 | # define TRUE 1 | |
702 | # define FALSE 0 | |
703 | #endif | |
704 | ||
705 | #define MODE_DIR (S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO) | |
706 | ||
707 | #define DEBUG_NONE 0x0000000 | |
708 | #define DEBUG_MODULE_LOAD 0x0000001 | |
709 | #define DEBUG_REGISTER 0x0000002 | |
710 | #define DEBUG_UNREGISTER 0x0000004 | |
711 | #define DEBUG_FREE 0x0000008 | |
712 | #define DEBUG_SET_FLAGS 0x0000010 | |
713 | #define DEBUG_S_READ 0x0000100 /* Break */ | |
714 | #define DEBUG_I_LOOKUP 0x0001000 /* Break */ | |
715 | #define DEBUG_I_CREATE 0x0002000 | |
716 | #define DEBUG_I_GET 0x0004000 | |
717 | #define DEBUG_I_CHANGE 0x0008000 | |
718 | #define DEBUG_I_UNLINK 0x0010000 | |
719 | #define DEBUG_I_RLINK 0x0020000 | |
720 | #define DEBUG_I_FLINK 0x0040000 | |
721 | #define DEBUG_I_MKNOD 0x0080000 | |
722 | #define DEBUG_F_READDIR 0x0100000 /* Break */ | |
723 | #define DEBUG_D_DELETE 0x1000000 /* Break */ | |
724 | #define DEBUG_D_RELEASE 0x2000000 | |
725 | #define DEBUG_D_IPUT 0x4000000 | |
726 | #define DEBUG_ALL 0xfffffff | |
727 | #define DEBUG_DISABLED DEBUG_NONE | |
728 | ||
729 | #define OPTION_NONE 0x00 | |
730 | #define OPTION_MOUNT 0x01 | |
731 | ||
732 | #define PRINTK(format, args...) \ | |
733 | {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} | |
734 | ||
735 | #define OOPS(format, args...) \ | |
736 | {printk (KERN_CRIT "%s" format, __FUNCTION__ , ## args); \ | |
737 | printk ("Forcing Oops\n"); \ | |
738 | BUG();} | |
739 | ||
740 | #ifdef CONFIG_DEVFS_DEBUG | |
741 | # define VERIFY_ENTRY(de) \ | |
742 | {if ((de) && (de)->magic_number != MAGIC_VALUE) \ | |
743 | OOPS ("(%p): bad magic value: %x\n", (de), (de)->magic_number);} | |
744 | # define WRITE_ENTRY_MAGIC(de,magic) (de)->magic_number = (magic) | |
745 | # define DPRINTK(flag, format, args...) \ | |
746 | {if (devfs_debug & flag) \ | |
747 | printk (KERN_INFO "%s" format, __FUNCTION__ , ## args);} | |
748 | #else | |
749 | # define VERIFY_ENTRY(de) | |
750 | # define WRITE_ENTRY_MAGIC(de,magic) | |
751 | # define DPRINTK(flag, format, args...) | |
752 | #endif | |
753 | ||
754 | typedef struct devfs_entry *devfs_handle_t; | |
755 | ||
756 | struct directory_type { | |
757 | rwlock_t lock; /* Lock for searching(R)/updating(W) */ | |
758 | struct devfs_entry *first; | |
759 | struct devfs_entry *last; | |
760 | unsigned char no_more_additions:1; | |
761 | }; | |
762 | ||
763 | struct symlink_type { | |
764 | unsigned int length; /* Not including the NULL-termimator */ | |
765 | char *linkname; /* This is NULL-terminated */ | |
766 | }; | |
767 | ||
768 | struct devfs_inode { /* This structure is for "persistent" inode storage */ | |
769 | struct dentry *dentry; | |
770 | struct timespec atime; | |
771 | struct timespec mtime; | |
772 | struct timespec ctime; | |
773 | unsigned int ino; /* Inode number as seen in the VFS */ | |
774 | uid_t uid; | |
775 | gid_t gid; | |
776 | }; | |
777 | ||
778 | struct devfs_entry { | |
779 | #ifdef CONFIG_DEVFS_DEBUG | |
780 | unsigned int magic_number; | |
781 | #endif | |
782 | void *info; | |
783 | atomic_t refcount; /* When this drops to zero, it's unused */ | |
784 | union { | |
785 | struct directory_type dir; | |
786 | dev_t dev; | |
787 | struct symlink_type symlink; | |
788 | const char *name; /* Only used for (mode == 0) */ | |
789 | } u; | |
790 | struct devfs_entry *prev; /* Previous entry in the parent directory */ | |
791 | struct devfs_entry *next; /* Next entry in the parent directory */ | |
792 | struct devfs_entry *parent; /* The parent directory */ | |
793 | struct devfs_inode inode; | |
794 | umode_t mode; | |
795 | unsigned short namelen; /* I think 64k+ filenames are a way off... */ | |
796 | unsigned char vfs:1; /* Whether the VFS may delete the entry */ | |
797 | char name[1]; /* This is just a dummy: the allocated array | |
798 | is bigger. This is NULL-terminated */ | |
799 | }; | |
800 | ||
801 | /* The root of the device tree */ | |
802 | static struct devfs_entry *root_entry; | |
803 | ||
804 | struct devfsd_buf_entry { | |
805 | struct devfs_entry *de; /* The name is generated with this */ | |
806 | unsigned short type; /* The type of event */ | |
807 | umode_t mode; | |
808 | uid_t uid; | |
809 | gid_t gid; | |
810 | struct devfsd_buf_entry *next; | |
811 | }; | |
812 | ||
813 | struct fs_info { /* This structure is for the mounted devfs */ | |
814 | struct super_block *sb; | |
815 | spinlock_t devfsd_buffer_lock; /* Lock when inserting/deleting events */ | |
816 | struct devfsd_buf_entry *devfsd_first_event; | |
817 | struct devfsd_buf_entry *devfsd_last_event; | |
818 | volatile int devfsd_sleeping; | |
819 | volatile struct task_struct *devfsd_task; | |
820 | volatile pid_t devfsd_pgrp; | |
821 | volatile struct file *devfsd_file; | |
822 | struct devfsd_notify_struct *devfsd_info; | |
823 | volatile unsigned long devfsd_event_mask; | |
824 | atomic_t devfsd_overrun_count; | |
825 | wait_queue_head_t devfsd_wait_queue; /* Wake devfsd on input */ | |
826 | wait_queue_head_t revalidate_wait_queue; /* Wake when devfsd sleeps */ | |
827 | }; | |
828 | ||
829 | static struct fs_info fs_info = {.devfsd_buffer_lock = SPIN_LOCK_UNLOCKED }; | |
830 | static kmem_cache_t *devfsd_buf_cache; | |
831 | #ifdef CONFIG_DEVFS_DEBUG | |
832 | static unsigned int devfs_debug_init __initdata = DEBUG_NONE; | |
833 | static unsigned int devfs_debug = DEBUG_NONE; | |
834 | static DEFINE_SPINLOCK(stat_lock); | |
835 | static unsigned int stat_num_entries; | |
836 | static unsigned int stat_num_bytes; | |
837 | #endif | |
838 | static unsigned char poison_array[8] = | |
839 | { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a }; | |
840 | ||
841 | #ifdef CONFIG_DEVFS_MOUNT | |
842 | static unsigned int boot_options = OPTION_MOUNT; | |
843 | #else | |
844 | static unsigned int boot_options = OPTION_NONE; | |
845 | #endif | |
846 | ||
847 | /* Forward function declarations */ | |
848 | static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, | |
849 | const char *name, int namelen, | |
850 | int traverse_symlink); | |
851 | static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len, | |
852 | loff_t * ppos); | |
853 | static int devfsd_ioctl(struct inode *inode, struct file *file, | |
854 | unsigned int cmd, unsigned long arg); | |
855 | static int devfsd_close(struct inode *inode, struct file *file); | |
856 | #ifdef CONFIG_DEVFS_DEBUG | |
857 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, | |
858 | loff_t * ppos); | |
859 | static struct file_operations stat_fops = { | |
860 | .open = nonseekable_open, | |
861 | .read = stat_read, | |
862 | }; | |
863 | #endif | |
864 | ||
865 | /* Devfs daemon file operations */ | |
866 | static struct file_operations devfsd_fops = { | |
867 | .open = nonseekable_open, | |
868 | .read = devfsd_read, | |
869 | .ioctl = devfsd_ioctl, | |
870 | .release = devfsd_close, | |
871 | }; | |
872 | ||
873 | /* Support functions follow */ | |
874 | ||
875 | /** | |
876 | * devfs_get - Get a reference to a devfs entry. | |
877 | * @de: The devfs entry. | |
878 | */ | |
879 | ||
880 | static struct devfs_entry *devfs_get(struct devfs_entry *de) | |
881 | { | |
882 | VERIFY_ENTRY(de); | |
883 | if (de) | |
884 | atomic_inc(&de->refcount); | |
885 | return de; | |
886 | } /* End Function devfs_get */ | |
887 | ||
888 | /** | |
889 | * devfs_put - Put (release) a reference to a devfs entry. | |
890 | * @de: The handle to the devfs entry. | |
891 | */ | |
892 | ||
893 | static void devfs_put(devfs_handle_t de) | |
894 | { | |
895 | if (!de) | |
896 | return; | |
897 | VERIFY_ENTRY(de); | |
898 | if (de->info == POISON_PTR) | |
899 | OOPS("(%p): poisoned pointer\n", de); | |
900 | if (!atomic_dec_and_test(&de->refcount)) | |
901 | return; | |
902 | if (de == root_entry) | |
903 | OOPS("(%p): root entry being freed\n", de); | |
904 | DPRINTK(DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n", | |
905 | de->name, de, de->parent, | |
906 | de->parent ? de->parent->name : "no parent"); | |
907 | if (S_ISLNK(de->mode)) | |
908 | kfree(de->u.symlink.linkname); | |
909 | WRITE_ENTRY_MAGIC(de, 0); | |
910 | #ifdef CONFIG_DEVFS_DEBUG | |
911 | spin_lock(&stat_lock); | |
912 | --stat_num_entries; | |
913 | stat_num_bytes -= sizeof *de + de->namelen; | |
914 | if (S_ISLNK(de->mode)) | |
915 | stat_num_bytes -= de->u.symlink.length + 1; | |
916 | spin_unlock(&stat_lock); | |
917 | #endif | |
918 | de->info = POISON_PTR; | |
919 | kfree(de); | |
920 | } /* End Function devfs_put */ | |
921 | ||
922 | /** | |
923 | * _devfs_search_dir - Search for a devfs entry in a directory. | |
924 | * @dir: The directory to search. | |
925 | * @name: The name of the entry to search for. | |
926 | * @namelen: The number of characters in @name. | |
927 | * | |
928 | * Search for a devfs entry in a directory and returns a pointer to the entry | |
929 | * on success, else %NULL. The directory must be locked already. | |
930 | * An implicit devfs_get() is performed on the returned entry. | |
931 | */ | |
932 | ||
933 | static struct devfs_entry *_devfs_search_dir(struct devfs_entry *dir, | |
934 | const char *name, | |
935 | unsigned int namelen) | |
936 | { | |
937 | struct devfs_entry *curr; | |
938 | ||
939 | if (!S_ISDIR(dir->mode)) { | |
940 | PRINTK("(%s): not a directory\n", dir->name); | |
941 | return NULL; | |
942 | } | |
943 | for (curr = dir->u.dir.first; curr != NULL; curr = curr->next) { | |
944 | if (curr->namelen != namelen) | |
945 | continue; | |
946 | if (memcmp(curr->name, name, namelen) == 0) | |
947 | break; | |
948 | /* Not found: try the next one */ | |
949 | } | |
950 | return devfs_get(curr); | |
951 | } /* End Function _devfs_search_dir */ | |
952 | ||
953 | /** | |
954 | * _devfs_alloc_entry - Allocate a devfs entry. | |
955 | * @name: the name of the entry | |
956 | * @namelen: the number of characters in @name | |
957 | * @mode: the mode for the entry | |
958 | * | |
959 | * Allocate a devfs entry and returns a pointer to the entry on success, else | |
960 | * %NULL. | |
961 | */ | |
962 | ||
963 | static struct devfs_entry *_devfs_alloc_entry(const char *name, | |
964 | unsigned int namelen, | |
965 | umode_t mode) | |
966 | { | |
967 | struct devfs_entry *new; | |
968 | static unsigned long inode_counter = FIRST_INODE; | |
969 | static DEFINE_SPINLOCK(counter_lock); | |
970 | ||
971 | if (name && (namelen < 1)) | |
972 | namelen = strlen(name); | |
973 | if ((new = kmalloc(sizeof *new + namelen, GFP_KERNEL)) == NULL) | |
974 | return NULL; | |
975 | memset(new, 0, sizeof *new + namelen); /* Will set '\0' on name */ | |
976 | new->mode = mode; | |
977 | if (S_ISDIR(mode)) | |
978 | rwlock_init(&new->u.dir.lock); | |
979 | atomic_set(&new->refcount, 1); | |
980 | spin_lock(&counter_lock); | |
981 | new->inode.ino = inode_counter++; | |
982 | spin_unlock(&counter_lock); | |
983 | if (name) | |
984 | memcpy(new->name, name, namelen); | |
985 | new->namelen = namelen; | |
986 | WRITE_ENTRY_MAGIC(new, MAGIC_VALUE); | |
987 | #ifdef CONFIG_DEVFS_DEBUG | |
988 | spin_lock(&stat_lock); | |
989 | ++stat_num_entries; | |
990 | stat_num_bytes += sizeof *new + namelen; | |
991 | spin_unlock(&stat_lock); | |
992 | #endif | |
993 | return new; | |
994 | } /* End Function _devfs_alloc_entry */ | |
995 | ||
996 | /** | |
997 | * _devfs_append_entry - Append a devfs entry to a directory's child list. | |
998 | * @dir: The directory to add to. | |
999 | * @de: The devfs entry to append. | |
1000 | * @old_de: If an existing entry exists, it will be written here. This may | |
1001 | * be %NULL. An implicit devfs_get() is performed on this entry. | |
1002 | * | |
1003 | * Append a devfs entry to a directory's list of children, checking first to | |
1004 | * see if an entry of the same name exists. The directory will be locked. | |
1005 | * The value 0 is returned on success, else a negative error code. | |
1006 | * On failure, an implicit devfs_put() is performed on %de. | |
1007 | */ | |
1008 | ||
1009 | static int _devfs_append_entry(devfs_handle_t dir, devfs_handle_t de, | |
1010 | devfs_handle_t * old_de) | |
1011 | { | |
1012 | int retval; | |
1013 | ||
1014 | if (old_de) | |
1015 | *old_de = NULL; | |
1016 | if (!S_ISDIR(dir->mode)) { | |
1017 | PRINTK("(%s): dir: \"%s\" is not a directory\n", de->name, | |
1018 | dir->name); | |
1019 | devfs_put(de); | |
1020 | return -ENOTDIR; | |
1021 | } | |
1022 | write_lock(&dir->u.dir.lock); | |
1023 | if (dir->u.dir.no_more_additions) | |
1024 | retval = -ENOENT; | |
1025 | else { | |
1026 | struct devfs_entry *old; | |
1027 | ||
1028 | old = _devfs_search_dir(dir, de->name, de->namelen); | |
1029 | if (old_de) | |
1030 | *old_de = old; | |
1031 | else | |
1032 | devfs_put(old); | |
1033 | if (old == NULL) { | |
1034 | de->parent = dir; | |
1035 | de->prev = dir->u.dir.last; | |
1036 | /* Append to the directory's list of children */ | |
1037 | if (dir->u.dir.first == NULL) | |
1038 | dir->u.dir.first = de; | |
1039 | else | |
1040 | dir->u.dir.last->next = de; | |
1041 | dir->u.dir.last = de; | |
1042 | retval = 0; | |
1043 | } else | |
1044 | retval = -EEXIST; | |
1045 | } | |
1046 | write_unlock(&dir->u.dir.lock); | |
1047 | if (retval) | |
1048 | devfs_put(de); | |
1049 | return retval; | |
1050 | } /* End Function _devfs_append_entry */ | |
1051 | ||
1052 | /** | |
1053 | * _devfs_get_root_entry - Get the root devfs entry. | |
1054 | * | |
1055 | * Returns the root devfs entry on success, else %NULL. | |
1056 | * | |
1057 | * TODO it must be called asynchronously due to the fact | |
1058 | * that devfs is initialized relatively late. Proper way | |
1059 | * is to remove module_init from init_devfs_fs and manually | |
1060 | * call it early enough during system init | |
1061 | */ | |
1062 | ||
1063 | static struct devfs_entry *_devfs_get_root_entry(void) | |
1064 | { | |
1065 | struct devfs_entry *new; | |
1066 | static DEFINE_SPINLOCK(root_lock); | |
1067 | ||
1068 | if (root_entry) | |
1069 | return root_entry; | |
1070 | ||
1071 | new = _devfs_alloc_entry(NULL, 0, MODE_DIR); | |
1072 | if (new == NULL) | |
1073 | return NULL; | |
1074 | ||
1075 | spin_lock(&root_lock); | |
1076 | if (root_entry) { | |
1077 | spin_unlock(&root_lock); | |
1078 | devfs_put(new); | |
1079 | return root_entry; | |
1080 | } | |
1081 | root_entry = new; | |
1082 | spin_unlock(&root_lock); | |
1083 | ||
1084 | return root_entry; | |
1085 | } /* End Function _devfs_get_root_entry */ | |
1086 | ||
1087 | /** | |
1088 | * _devfs_descend - Descend down a tree using the next component name. | |
1089 | * @dir: The directory to search. | |
1090 | * @name: The component name to search for. | |
1091 | * @namelen: The length of %name. | |
1092 | * @next_pos: The position of the next '/' or '\0' is written here. | |
1093 | * | |
1094 | * Descend into a directory, searching for a component. This function forms | |
1095 | * the core of a tree-walking algorithm. The directory will be locked. | |
1096 | * The devfs entry corresponding to the component is returned. If there is | |
1097 | * no matching entry, %NULL is returned. | |
1098 | * An implicit devfs_get() is performed on the returned entry. | |
1099 | */ | |
1100 | ||
1101 | static struct devfs_entry *_devfs_descend(struct devfs_entry *dir, | |
1102 | const char *name, int namelen, | |
1103 | int *next_pos) | |
1104 | { | |
1105 | const char *stop, *ptr; | |
1106 | struct devfs_entry *entry; | |
1107 | ||
1108 | if ((namelen >= 3) && (strncmp(name, "../", 3) == 0)) { /* Special-case going to parent directory */ | |
1109 | *next_pos = 3; | |
1110 | return devfs_get(dir->parent); | |
1111 | } | |
1112 | stop = name + namelen; | |
1113 | /* Search for a possible '/' */ | |
1114 | for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr) ; | |
1115 | *next_pos = ptr - name; | |
1116 | read_lock(&dir->u.dir.lock); | |
1117 | entry = _devfs_search_dir(dir, name, *next_pos); | |
1118 | read_unlock(&dir->u.dir.lock); | |
1119 | return entry; | |
1120 | } /* End Function _devfs_descend */ | |
1121 | ||
1122 | static devfs_handle_t _devfs_make_parent_for_leaf(struct devfs_entry *dir, | |
1123 | const char *name, | |
1124 | int namelen, int *leaf_pos) | |
1125 | { | |
1126 | int next_pos = 0; | |
1127 | ||
1128 | if (dir == NULL) | |
1129 | dir = _devfs_get_root_entry(); | |
1130 | if (dir == NULL) | |
1131 | return NULL; | |
1132 | devfs_get(dir); | |
1133 | /* Search for possible trailing component and ignore it */ | |
1134 | for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen) ; | |
1135 | *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0; | |
1136 | for (; namelen > 0; name += next_pos, namelen -= next_pos) { | |
1137 | struct devfs_entry *de, *old = NULL; | |
1138 | ||
1139 | if ((de = | |
1140 | _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { | |
1141 | de = _devfs_alloc_entry(name, next_pos, MODE_DIR); | |
1142 | devfs_get(de); | |
1143 | if (!de || _devfs_append_entry(dir, de, &old)) { | |
1144 | devfs_put(de); | |
1145 | if (!old || !S_ISDIR(old->mode)) { | |
1146 | devfs_put(old); | |
1147 | devfs_put(dir); | |
1148 | return NULL; | |
1149 | } | |
1150 | de = old; /* Use the existing directory */ | |
1151 | } | |
1152 | } | |
1153 | if (de == dir->parent) { | |
1154 | devfs_put(dir); | |
1155 | devfs_put(de); | |
1156 | return NULL; | |
1157 | } | |
1158 | devfs_put(dir); | |
1159 | dir = de; | |
1160 | if (name[next_pos] == '/') | |
1161 | ++next_pos; | |
1162 | } | |
1163 | return dir; | |
1164 | } /* End Function _devfs_make_parent_for_leaf */ | |
1165 | ||
1166 | static devfs_handle_t _devfs_prepare_leaf(devfs_handle_t * dir, | |
1167 | const char *name, umode_t mode) | |
1168 | { | |
1169 | int namelen, leaf_pos; | |
1170 | struct devfs_entry *de; | |
1171 | ||
1172 | namelen = strlen(name); | |
1173 | if ((*dir = _devfs_make_parent_for_leaf(*dir, name, namelen, | |
1174 | &leaf_pos)) == NULL) { | |
1175 | PRINTK("(%s): could not create parent path\n", name); | |
1176 | return NULL; | |
1177 | } | |
1178 | if ((de = _devfs_alloc_entry(name + leaf_pos, namelen - leaf_pos, mode)) | |
1179 | == NULL) { | |
1180 | PRINTK("(%s): could not allocate entry\n", name); | |
1181 | devfs_put(*dir); | |
1182 | return NULL; | |
1183 | } | |
1184 | return de; | |
1185 | } /* End Function _devfs_prepare_leaf */ | |
1186 | ||
1187 | static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, | |
1188 | const char *name, int namelen, | |
1189 | int traverse_symlink) | |
1190 | { | |
1191 | int next_pos = 0; | |
1192 | ||
1193 | if (dir == NULL) | |
1194 | dir = _devfs_get_root_entry(); | |
1195 | if (dir == NULL) | |
1196 | return NULL; | |
1197 | devfs_get(dir); | |
1198 | for (; namelen > 0; name += next_pos, namelen -= next_pos) { | |
1199 | struct devfs_entry *de, *link; | |
1200 | ||
1201 | if (!S_ISDIR(dir->mode)) { | |
1202 | devfs_put(dir); | |
1203 | return NULL; | |
1204 | } | |
1205 | ||
1206 | if ((de = | |
1207 | _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { | |
1208 | devfs_put(dir); | |
1209 | return NULL; | |
1210 | } | |
1211 | if (S_ISLNK(de->mode) && traverse_symlink) { /* Need to follow the link: this is a stack chomper */ | |
1212 | /* FIXME what if it puts outside of mounted tree? */ | |
1213 | link = _devfs_walk_path(dir, de->u.symlink.linkname, | |
1214 | de->u.symlink.length, TRUE); | |
1215 | devfs_put(de); | |
1216 | if (!link) { | |
1217 | devfs_put(dir); | |
1218 | return NULL; | |
1219 | } | |
1220 | de = link; | |
1221 | } | |
1222 | devfs_put(dir); | |
1223 | dir = de; | |
1224 | if (name[next_pos] == '/') | |
1225 | ++next_pos; | |
1226 | } | |
1227 | return dir; | |
1228 | } /* End Function _devfs_walk_path */ | |
1229 | ||
1230 | /** | |
1231 | * _devfs_find_entry - Find a devfs entry. | |
1232 | * @dir: The handle to the parent devfs directory entry. If this is %NULL the | |
1233 | * name is relative to the root of the devfs. | |
1234 | * @name: The name of the entry. This may be %NULL. | |
1235 | * @traverse_symlink: If %TRUE then symbolic links are traversed. | |
1236 | * | |
1237 | * Returns the devfs_entry pointer on success, else %NULL. An implicit | |
1238 | * devfs_get() is performed. | |
1239 | */ | |
1240 | ||
1241 | static struct devfs_entry *_devfs_find_entry(devfs_handle_t dir, | |
1242 | const char *name, | |
1243 | int traverse_symlink) | |
1244 | { | |
1245 | unsigned int namelen = strlen(name); | |
1246 | ||
1247 | if (name[0] == '/') { | |
1248 | /* Skip leading pathname component */ | |
1249 | if (namelen < 2) { | |
1250 | PRINTK("(%s): too short\n", name); | |
1251 | return NULL; | |
1252 | } | |
1253 | for (++name, --namelen; (*name != '/') && (namelen > 0); | |
1254 | ++name, --namelen) ; | |
1255 | if (namelen < 2) { | |
1256 | PRINTK("(%s): too short\n", name); | |
1257 | return NULL; | |
1258 | } | |
1259 | ++name; | |
1260 | --namelen; | |
1261 | } | |
1262 | return _devfs_walk_path(dir, name, namelen, traverse_symlink); | |
1263 | } /* End Function _devfs_find_entry */ | |
1264 | ||
1265 | static struct devfs_entry *get_devfs_entry_from_vfs_inode(struct inode *inode) | |
1266 | { | |
1267 | if (inode == NULL) | |
1268 | return NULL; | |
1269 | VERIFY_ENTRY((struct devfs_entry *)inode->u.generic_ip); | |
1270 | return inode->u.generic_ip; | |
1271 | } /* End Function get_devfs_entry_from_vfs_inode */ | |
1272 | ||
1273 | /** | |
1274 | * free_dentry - Free the dentry for a device entry and invalidate inode. | |
1275 | * @de: The entry. | |
1276 | * | |
1277 | * This must only be called after the entry has been unhooked from its | |
1278 | * parent directory. | |
1279 | */ | |
1280 | ||
1281 | static void free_dentry(struct devfs_entry *de) | |
1282 | { | |
1283 | struct dentry *dentry = de->inode.dentry; | |
1284 | ||
1285 | if (!dentry) | |
1286 | return; | |
1287 | spin_lock(&dcache_lock); | |
1288 | dget_locked(dentry); | |
1289 | spin_unlock(&dcache_lock); | |
1290 | /* Forcefully remove the inode */ | |
1291 | if (dentry->d_inode != NULL) | |
1292 | dentry->d_inode->i_nlink = 0; | |
1293 | d_drop(dentry); | |
1294 | dput(dentry); | |
1295 | } /* End Function free_dentry */ | |
1296 | ||
1297 | /** | |
1298 | * is_devfsd_or_child - Test if the current process is devfsd or one of its children. | |
1299 | * @fs_info: The filesystem information. | |
1300 | * | |
1301 | * Returns %TRUE if devfsd or child, else %FALSE. | |
1302 | */ | |
1303 | ||
1304 | static int is_devfsd_or_child(struct fs_info *fs_info) | |
1305 | { | |
1306 | struct task_struct *p = current; | |
1307 | ||
1308 | if (p == fs_info->devfsd_task) | |
1309 | return (TRUE); | |
1310 | if (process_group(p) == fs_info->devfsd_pgrp) | |
1311 | return (TRUE); | |
1312 | read_lock(&tasklist_lock); | |
1313 | for (; p != &init_task; p = p->real_parent) { | |
1314 | if (p == fs_info->devfsd_task) { | |
1315 | read_unlock(&tasklist_lock); | |
1316 | return (TRUE); | |
1317 | } | |
1318 | } | |
1319 | read_unlock(&tasklist_lock); | |
1320 | return (FALSE); | |
1321 | } /* End Function is_devfsd_or_child */ | |
1322 | ||
1323 | /** | |
1324 | * devfsd_queue_empty - Test if devfsd has work pending in its event queue. | |
1325 | * @fs_info: The filesystem information. | |
1326 | * | |
1327 | * Returns %TRUE if the queue is empty, else %FALSE. | |
1328 | */ | |
1329 | ||
1330 | static inline int devfsd_queue_empty(struct fs_info *fs_info) | |
1331 | { | |
1332 | return (fs_info->devfsd_last_event) ? FALSE : TRUE; | |
1333 | } /* End Function devfsd_queue_empty */ | |
1334 | ||
1335 | /** | |
1336 | * wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue. | |
1337 | * @fs_info: The filesystem information. | |
1338 | * | |
1339 | * Returns %TRUE if no more waiting will be required, else %FALSE. | |
1340 | */ | |
1341 | ||
1342 | static int wait_for_devfsd_finished(struct fs_info *fs_info) | |
1343 | { | |
1344 | DECLARE_WAITQUEUE(wait, current); | |
1345 | ||
1346 | if (fs_info->devfsd_task == NULL) | |
1347 | return (TRUE); | |
1348 | if (devfsd_queue_empty(fs_info) && fs_info->devfsd_sleeping) | |
1349 | return TRUE; | |
1350 | if (is_devfsd_or_child(fs_info)) | |
1351 | return (FALSE); | |
1352 | set_current_state(TASK_UNINTERRUPTIBLE); | |
1353 | add_wait_queue(&fs_info->revalidate_wait_queue, &wait); | |
1354 | if (!devfsd_queue_empty(fs_info) || !fs_info->devfsd_sleeping) | |
1355 | if (fs_info->devfsd_task) | |
1356 | schedule(); | |
1357 | remove_wait_queue(&fs_info->revalidate_wait_queue, &wait); | |
1358 | __set_current_state(TASK_RUNNING); | |
1359 | return (TRUE); | |
1360 | } /* End Function wait_for_devfsd_finished */ | |
1361 | ||
1362 | /** | |
1363 | * devfsd_notify_de - Notify the devfsd daemon of a change. | |
1364 | * @de: The devfs entry that has changed. This and all parent entries will | |
1365 | * have their reference counts incremented if the event was queued. | |
1366 | * @type: The type of change. | |
1367 | * @mode: The mode of the entry. | |
1368 | * @uid: The user ID. | |
1369 | * @gid: The group ID. | |
1370 | * @fs_info: The filesystem info. | |
1371 | * | |
1372 | * Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. | |
1373 | */ | |
1374 | ||
1375 | static int devfsd_notify_de(struct devfs_entry *de, | |
1376 | unsigned short type, umode_t mode, | |
1377 | uid_t uid, gid_t gid, struct fs_info *fs_info) | |
1378 | { | |
1379 | struct devfsd_buf_entry *entry; | |
1380 | struct devfs_entry *curr; | |
1381 | ||
1382 | if (!(fs_info->devfsd_event_mask & (1 << type))) | |
1383 | return (FALSE); | |
1384 | if ((entry = kmem_cache_alloc(devfsd_buf_cache, SLAB_KERNEL)) == NULL) { | |
1385 | atomic_inc(&fs_info->devfsd_overrun_count); | |
1386 | return (FALSE); | |
1387 | } | |
1388 | for (curr = de; curr != NULL; curr = curr->parent) | |
1389 | devfs_get(curr); | |
1390 | entry->de = de; | |
1391 | entry->type = type; | |
1392 | entry->mode = mode; | |
1393 | entry->uid = uid; | |
1394 | entry->gid = gid; | |
1395 | entry->next = NULL; | |
1396 | spin_lock(&fs_info->devfsd_buffer_lock); | |
1397 | if (!fs_info->devfsd_first_event) | |
1398 | fs_info->devfsd_first_event = entry; | |
1399 | if (fs_info->devfsd_last_event) | |
1400 | fs_info->devfsd_last_event->next = entry; | |
1401 | fs_info->devfsd_last_event = entry; | |
1402 | spin_unlock(&fs_info->devfsd_buffer_lock); | |
1403 | wake_up_interruptible(&fs_info->devfsd_wait_queue); | |
1404 | return (TRUE); | |
1405 | } /* End Function devfsd_notify_de */ | |
1406 | ||
1407 | /** | |
1408 | * devfsd_notify - Notify the devfsd daemon of a change. | |
1409 | * @de: The devfs entry that has changed. | |
1410 | * @type: The type of change event. | |
1411 | * @wait: If TRUE, the function waits for the daemon to finish processing | |
1412 | * the event. | |
1413 | */ | |
1414 | ||
1415 | static void devfsd_notify(struct devfs_entry *de, unsigned short type) | |
1416 | { | |
1417 | devfsd_notify_de(de, type, de->mode, current->euid, | |
1418 | current->egid, &fs_info); | |
1419 | } | |
1420 | ||
1421 | static int devfs_mk_dev(dev_t dev, umode_t mode, const char *fmt, va_list args) | |
1422 | { | |
1423 | struct devfs_entry *dir = NULL, *de; | |
1424 | char buf[64]; | |
1425 | int error, n; | |
1426 | ||
1427 | n = vsnprintf(buf, sizeof(buf), fmt, args); | |
1428 | if (n >= sizeof(buf) || !buf[0]) { | |
1429 | printk(KERN_WARNING "%s: invalid format string %s\n", | |
1430 | __FUNCTION__, fmt); | |
1431 | return -EINVAL; | |
1432 | } | |
1433 | ||
1434 | de = _devfs_prepare_leaf(&dir, buf, mode); | |
1435 | if (!de) { | |
1436 | printk(KERN_WARNING "%s: could not prepare leaf for %s\n", | |
1437 | __FUNCTION__, buf); | |
1438 | return -ENOMEM; /* could be more accurate... */ | |
1439 | } | |
1440 | ||
1441 | de->u.dev = dev; | |
1442 | ||
1443 | error = _devfs_append_entry(dir, de, NULL); | |
1444 | if (error) { | |
1445 | printk(KERN_WARNING "%s: could not append to parent for %s\n", | |
1446 | __FUNCTION__, buf); | |
1447 | goto out; | |
1448 | } | |
1449 | ||
1450 | devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); | |
1451 | out: | |
1452 | devfs_put(dir); | |
1453 | return error; | |
1454 | } | |
1455 | ||
1456 | int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) | |
1457 | { | |
1458 | va_list args; | |
1459 | ||
1460 | if (!S_ISBLK(mode)) { | |
1461 | printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", | |
1462 | __FUNCTION__, mode, fmt); | |
1463 | return -EINVAL; | |
1464 | } | |
1465 | ||
1466 | va_start(args, fmt); | |
1467 | return devfs_mk_dev(dev, mode, fmt, args); | |
1468 | } | |
1469 | ||
1470 | EXPORT_SYMBOL(devfs_mk_bdev); | |
1471 | ||
1472 | int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) | |
1473 | { | |
1474 | va_list args; | |
1475 | ||
1476 | if (!S_ISCHR(mode)) { | |
1477 | printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", | |
1478 | __FUNCTION__, mode, fmt); | |
1479 | return -EINVAL; | |
1480 | } | |
1481 | ||
1482 | va_start(args, fmt); | |
1483 | return devfs_mk_dev(dev, mode, fmt, args); | |
1484 | } | |
1485 | ||
1486 | EXPORT_SYMBOL(devfs_mk_cdev); | |
1487 | ||
1488 | /** | |
1489 | * _devfs_unhook - Unhook a device entry from its parents list | |
1490 | * @de: The entry to unhook. | |
1491 | * | |
1492 | * Returns %TRUE if the entry was unhooked, else %FALSE if it was | |
1493 | * previously unhooked. | |
1494 | * The caller must have a write lock on the parent directory. | |
1495 | */ | |
1496 | ||
1497 | static int _devfs_unhook(struct devfs_entry *de) | |
1498 | { | |
1499 | struct devfs_entry *parent; | |
1500 | ||
1501 | if (!de || (de->prev == de)) | |
1502 | return FALSE; | |
1503 | parent = de->parent; | |
1504 | if (de->prev == NULL) | |
1505 | parent->u.dir.first = de->next; | |
1506 | else | |
1507 | de->prev->next = de->next; | |
1508 | if (de->next == NULL) | |
1509 | parent->u.dir.last = de->prev; | |
1510 | else | |
1511 | de->next->prev = de->prev; | |
1512 | de->prev = de; /* Indicate we're unhooked */ | |
1513 | de->next = NULL; /* Force early termination for <devfs_readdir> */ | |
1514 | return TRUE; | |
1515 | } /* End Function _devfs_unhook */ | |
1516 | ||
1517 | /** | |
1518 | * _devfs_unregister - Unregister a device entry from its parent. | |
1519 | * @dir: The parent directory. | |
1520 | * @de: The entry to unregister. | |
1521 | * | |
1522 | * The caller must have a write lock on the parent directory, which is | |
1523 | * unlocked by this function. | |
1524 | */ | |
1525 | ||
1526 | static void _devfs_unregister(struct devfs_entry *dir, struct devfs_entry *de) | |
1527 | { | |
1528 | int unhooked = _devfs_unhook(de); | |
1529 | ||
1530 | write_unlock(&dir->u.dir.lock); | |
1531 | if (!unhooked) | |
1532 | return; | |
1533 | devfs_get(dir); | |
1534 | devfsd_notify(de, DEVFSD_NOTIFY_UNREGISTERED); | |
1535 | free_dentry(de); | |
1536 | devfs_put(dir); | |
1537 | if (!S_ISDIR(de->mode)) | |
1538 | return; | |
1539 | while (TRUE) { /* Recursively unregister: this is a stack chomper */ | |
1540 | struct devfs_entry *child; | |
1541 | ||
1542 | write_lock(&de->u.dir.lock); | |
1543 | de->u.dir.no_more_additions = TRUE; | |
1544 | child = de->u.dir.first; | |
1545 | VERIFY_ENTRY(child); | |
1546 | _devfs_unregister(de, child); | |
1547 | if (!child) | |
1548 | break; | |
1549 | DPRINTK(DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n", | |
1550 | child->name, child, atomic_read(&child->refcount)); | |
1551 | devfs_put(child); | |
1552 | } | |
1553 | } /* End Function _devfs_unregister */ | |
1554 | ||
1555 | static int devfs_do_symlink(devfs_handle_t dir, const char *name, | |
1556 | const char *link, devfs_handle_t * handle) | |
1557 | { | |
1558 | int err; | |
1559 | unsigned int linklength; | |
1560 | char *newlink; | |
1561 | struct devfs_entry *de; | |
1562 | ||
1563 | if (handle != NULL) | |
1564 | *handle = NULL; | |
1565 | if (name == NULL) { | |
1566 | PRINTK("(): NULL name pointer\n"); | |
1567 | return -EINVAL; | |
1568 | } | |
1569 | if (link == NULL) { | |
1570 | PRINTK("(%s): NULL link pointer\n", name); | |
1571 | return -EINVAL; | |
1572 | } | |
1573 | linklength = strlen(link); | |
1574 | if ((newlink = kmalloc(linklength + 1, GFP_KERNEL)) == NULL) | |
1575 | return -ENOMEM; | |
1576 | memcpy(newlink, link, linklength); | |
1577 | newlink[linklength] = '\0'; | |
1578 | if ((de = _devfs_prepare_leaf(&dir, name, S_IFLNK | S_IRUGO | S_IXUGO)) | |
1579 | == NULL) { | |
1580 | PRINTK("(%s): could not prepare leaf\n", name); | |
1581 | kfree(newlink); | |
1582 | return -ENOTDIR; | |
1583 | } | |
1584 | de->info = NULL; | |
1585 | de->u.symlink.linkname = newlink; | |
1586 | de->u.symlink.length = linklength; | |
1587 | if ((err = _devfs_append_entry(dir, de, NULL)) != 0) { | |
1588 | PRINTK("(%s): could not append to parent, err: %d\n", name, | |
1589 | err); | |
1590 | devfs_put(dir); | |
1591 | return err; | |
1592 | } | |
1593 | devfs_put(dir); | |
1594 | #ifdef CONFIG_DEVFS_DEBUG | |
1595 | spin_lock(&stat_lock); | |
1596 | stat_num_bytes += linklength + 1; | |
1597 | spin_unlock(&stat_lock); | |
1598 | #endif | |
1599 | if (handle != NULL) | |
1600 | *handle = de; | |
1601 | return 0; | |
1602 | } /* End Function devfs_do_symlink */ | |
1603 | ||
1604 | /** | |
1605 | * devfs_mk_symlink Create a symbolic link in the devfs namespace. | |
1606 | * @from: The name of the entry. | |
1607 | * @to: Name of the destination | |
1608 | * | |
1609 | * Returns 0 on success, else a negative error code is returned. | |
1610 | */ | |
1611 | ||
1612 | int devfs_mk_symlink(const char *from, const char *to) | |
1613 | { | |
1614 | devfs_handle_t de; | |
1615 | int err; | |
1616 | ||
1617 | err = devfs_do_symlink(NULL, from, to, &de); | |
1618 | if (!err) { | |
1619 | de->vfs = TRUE; | |
1620 | devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); | |
1621 | } | |
1622 | ||
1623 | return err; | |
1624 | } | |
1625 | ||
1626 | /** | |
1627 | * devfs_mk_dir - Create a directory in the devfs namespace. | |
1628 | * new name is relative to the root of the devfs. | |
1629 | * @fmt: The name of the entry. | |
1630 | * | |
1631 | * Use of this function is optional. The devfs_register() function | |
1632 | * will automatically create intermediate directories as needed. This function | |
1633 | * is provided for efficiency reasons, as it provides a handle to a directory. | |
1634 | * On failure %NULL is returned. | |
1635 | */ | |
1636 | ||
1637 | int devfs_mk_dir(const char *fmt, ...) | |
1638 | { | |
1639 | struct devfs_entry *dir = NULL, *de = NULL, *old; | |
1640 | char buf[64]; | |
1641 | va_list args; | |
1642 | int error, n; | |
1643 | ||
1644 | va_start(args, fmt); | |
1645 | n = vsnprintf(buf, 64, fmt, args); | |
1646 | if (n >= 64 || !buf[0]) { | |
1647 | printk(KERN_WARNING "%s: invalid argument.", __FUNCTION__); | |
1648 | return -EINVAL; | |
1649 | } | |
1650 | ||
1651 | de = _devfs_prepare_leaf(&dir, buf, MODE_DIR); | |
1652 | if (!de) { | |
1653 | PRINTK("(%s): could not prepare leaf\n", buf); | |
1654 | return -EINVAL; | |
1655 | } | |
1656 | ||
1657 | error = _devfs_append_entry(dir, de, &old); | |
1658 | if (error == -EEXIST && S_ISDIR(old->mode)) { | |
1659 | /* | |
1660 | * devfs_mk_dir() of an already-existing directory will | |
1661 | * return success. | |
1662 | */ | |
1663 | error = 0; | |
1664 | goto out_put; | |
1665 | } else if (error) { | |
1666 | PRINTK("(%s): could not append to dir: %p \"%s\"\n", | |
1667 | buf, dir, dir->name); | |
1668 | devfs_put(old); | |
1669 | goto out_put; | |
1670 | } | |
1671 | ||
1672 | devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); | |
1673 | ||
1674 | out_put: | |
1675 | devfs_put(dir); | |
1676 | return error; | |
1677 | } | |
1678 | ||
1679 | void devfs_remove(const char *fmt, ...) | |
1680 | { | |
1681 | char buf[64]; | |
1682 | va_list args; | |
1683 | int n; | |
1684 | ||
1685 | va_start(args, fmt); | |
1686 | n = vsnprintf(buf, sizeof(buf), fmt, args); | |
1687 | if (n < sizeof(buf) && buf[0]) { | |
1688 | devfs_handle_t de = _devfs_find_entry(NULL, buf, 0); | |
1689 | ||
1690 | if (!de) { | |
1691 | printk(KERN_ERR "%s: %s not found, cannot remove\n", | |
1692 | __FUNCTION__, buf); | |
1693 | dump_stack(); | |
1694 | return; | |
1695 | } | |
1696 | ||
1697 | write_lock(&de->parent->u.dir.lock); | |
1698 | _devfs_unregister(de->parent, de); | |
1699 | devfs_put(de); | |
1700 | devfs_put(de); | |
1701 | } | |
1702 | } | |
1703 | ||
1704 | /** | |
1705 | * devfs_generate_path - Generate a pathname for an entry, relative to the devfs root. | |
1706 | * @de: The devfs entry. | |
1707 | * @path: The buffer to write the pathname to. The pathname and '\0' | |
1708 | * terminator will be written at the end of the buffer. | |
1709 | * @buflen: The length of the buffer. | |
1710 | * | |
1711 | * Returns the offset in the buffer where the pathname starts on success, | |
1712 | * else a negative error code. | |
1713 | */ | |
1714 | ||
1715 | static int devfs_generate_path(devfs_handle_t de, char *path, int buflen) | |
1716 | { | |
1717 | int pos; | |
1718 | #define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name ) | |
1719 | ||
1720 | if (de == NULL) | |
1721 | return -EINVAL; | |
1722 | VERIFY_ENTRY(de); | |
1723 | if (de->namelen >= buflen) | |
1724 | return -ENAMETOOLONG; /* Must be first */ | |
1725 | path[buflen - 1] = '\0'; | |
1726 | if (de->parent == NULL) | |
1727 | return buflen - 1; /* Don't prepend root */ | |
1728 | pos = buflen - de->namelen - 1; | |
1729 | memcpy(path + pos, NAMEOF(de), de->namelen); | |
1730 | for (de = de->parent; de->parent != NULL; de = de->parent) { | |
1731 | if (pos - de->namelen - 1 < 0) | |
1732 | return -ENAMETOOLONG; | |
1733 | path[--pos] = '/'; | |
1734 | pos -= de->namelen; | |
1735 | memcpy(path + pos, NAMEOF(de), de->namelen); | |
1736 | } | |
1737 | return pos; | |
1738 | } /* End Function devfs_generate_path */ | |
1739 | ||
1740 | /** | |
1741 | * devfs_setup - Process kernel boot options. | |
1742 | * @str: The boot options after the "devfs=". | |
1743 | */ | |
1744 | ||
1745 | static int __init devfs_setup(char *str) | |
1746 | { | |
1747 | static struct { | |
1748 | char *name; | |
1749 | unsigned int mask; | |
1750 | unsigned int *opt; | |
1751 | } devfs_options_tab[] __initdata = { | |
1752 | #ifdef CONFIG_DEVFS_DEBUG | |
1753 | { | |
1754 | "dall", DEBUG_ALL, &devfs_debug_init}, { | |
1755 | "dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, { | |
1756 | "dreg", DEBUG_REGISTER, &devfs_debug_init}, { | |
1757 | "dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, { | |
1758 | "dfree", DEBUG_FREE, &devfs_debug_init}, { | |
1759 | "diget", DEBUG_I_GET, &devfs_debug_init}, { | |
1760 | "dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, { | |
1761 | "dsread", DEBUG_S_READ, &devfs_debug_init}, { | |
1762 | "dichange", DEBUG_I_CHANGE, &devfs_debug_init}, { | |
1763 | "dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, { | |
1764 | "dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, { | |
1765 | "diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, | |
1766 | #endif /* CONFIG_DEVFS_DEBUG */ | |
1767 | { | |
1768 | "mount", OPTION_MOUNT, &boot_options}, { | |
1769 | NULL, 0, NULL} | |
1770 | }; | |
1771 | ||
1772 | while ((*str != '\0') && !isspace(*str)) { | |
1773 | int i, found = 0, invert = 0; | |
1774 | ||
1775 | if (strncmp(str, "no", 2) == 0) { | |
1776 | invert = 1; | |
1777 | str += 2; | |
1778 | } | |
1779 | for (i = 0; devfs_options_tab[i].name != NULL; i++) { | |
1780 | int len = strlen(devfs_options_tab[i].name); | |
1781 | ||
1782 | if (strncmp(str, devfs_options_tab[i].name, len) == 0) { | |
1783 | if (invert) | |
1784 | *devfs_options_tab[i].opt &= | |
1785 | ~devfs_options_tab[i].mask; | |
1786 | else | |
1787 | *devfs_options_tab[i].opt |= | |
1788 | devfs_options_tab[i].mask; | |
1789 | str += len; | |
1790 | found = 1; | |
1791 | break; | |
1792 | } | |
1793 | } | |
1794 | if (!found) | |
1795 | return 0; /* No match */ | |
1796 | if (*str != ',') | |
1797 | return 0; /* No more options */ | |
1798 | ++str; | |
1799 | } | |
1800 | return 1; | |
1801 | } /* End Function devfs_setup */ | |
1802 | ||
1803 | __setup("devfs=", devfs_setup); | |
1804 | ||
1805 | EXPORT_SYMBOL(devfs_mk_dir); | |
1806 | EXPORT_SYMBOL(devfs_remove); | |
1807 | ||
1808 | /** | |
1809 | * try_modload - Notify devfsd of an inode lookup by a non-devfsd process. | |
1810 | * @parent: The parent devfs entry. | |
1811 | * @fs_info: The filesystem info. | |
1812 | * @name: The device name. | |
1813 | * @namelen: The number of characters in @name. | |
1814 | * @buf: A working area that will be used. This must not go out of scope | |
1815 | * until devfsd is idle again. | |
1816 | * | |
1817 | * Returns 0 on success (event was queued), else a negative error code. | |
1818 | */ | |
1819 | ||
1820 | static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, | |
1821 | const char *name, unsigned namelen, | |
1822 | struct devfs_entry *buf) | |
1823 | { | |
1824 | if (!(fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP))) | |
1825 | return -ENOENT; | |
1826 | if (is_devfsd_or_child(fs_info)) | |
1827 | return -ENOENT; | |
1828 | memset(buf, 0, sizeof *buf); | |
1829 | atomic_set(&buf->refcount, 1); | |
1830 | buf->parent = parent; | |
1831 | buf->namelen = namelen; | |
1832 | buf->u.name = name; | |
1833 | WRITE_ENTRY_MAGIC(buf, MAGIC_VALUE); | |
1834 | if (!devfsd_notify_de(buf, DEVFSD_NOTIFY_LOOKUP, 0, | |
1835 | current->euid, current->egid, fs_info)) | |
1836 | return -ENOENT; | |
1837 | /* Possible success: event has been queued */ | |
1838 | return 0; | |
1839 | } /* End Function try_modload */ | |
1840 | ||
1841 | /* Superblock operations follow */ | |
1842 | ||
1843 | static struct inode_operations devfs_iops; | |
1844 | static struct inode_operations devfs_dir_iops; | |
1845 | static struct file_operations devfs_fops; | |
1846 | static struct file_operations devfs_dir_fops; | |
1847 | static struct inode_operations devfs_symlink_iops; | |
1848 | ||
1849 | static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) | |
1850 | { | |
1851 | int retval; | |
1852 | struct devfs_entry *de; | |
1853 | struct inode *inode = dentry->d_inode; | |
1854 | struct fs_info *fs_info = inode->i_sb->s_fs_info; | |
1855 | ||
1856 | de = get_devfs_entry_from_vfs_inode(inode); | |
1857 | if (de == NULL) | |
1858 | return -ENODEV; | |
1859 | retval = inode_change_ok(inode, iattr); | |
1860 | if (retval != 0) | |
1861 | return retval; | |
1862 | retval = inode_setattr(inode, iattr); | |
1863 | if (retval != 0) | |
1864 | return retval; | |
1865 | DPRINTK(DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n", | |
1866 | (int)inode->i_ino, inode, de); | |
1867 | DPRINTK(DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n", | |
1868 | (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); | |
1869 | /* Inode is not on hash chains, thus must save permissions here rather | |
1870 | than in a write_inode() method */ | |
1871 | de->mode = inode->i_mode; | |
1872 | de->inode.uid = inode->i_uid; | |
1873 | de->inode.gid = inode->i_gid; | |
1874 | de->inode.atime = inode->i_atime; | |
1875 | de->inode.mtime = inode->i_mtime; | |
1876 | de->inode.ctime = inode->i_ctime; | |
1877 | if ((iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) && | |
1878 | !is_devfsd_or_child(fs_info)) | |
1879 | devfsd_notify_de(de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, | |
1880 | inode->i_uid, inode->i_gid, fs_info); | |
1881 | return 0; | |
1882 | } /* End Function devfs_notify_change */ | |
1883 | ||
1884 | static struct super_operations devfs_sops = { | |
1885 | .drop_inode = generic_delete_inode, | |
1886 | .statfs = simple_statfs, | |
1887 | }; | |
1888 | ||
1889 | /** | |
1890 | * _devfs_get_vfs_inode - Get a VFS inode. | |
1891 | * @sb: The super block. | |
1892 | * @de: The devfs inode. | |
1893 | * @dentry: The dentry to register with the devfs inode. | |
1894 | * | |
1895 | * Returns the inode on success, else %NULL. An implicit devfs_get() is | |
1896 | * performed if the inode is created. | |
1897 | */ | |
1898 | ||
1899 | static struct inode *_devfs_get_vfs_inode(struct super_block *sb, | |
1900 | struct devfs_entry *de, | |
1901 | struct dentry *dentry) | |
1902 | { | |
1903 | struct inode *inode; | |
1904 | ||
1905 | if (de->prev == de) | |
1906 | return NULL; /* Quick check to see if unhooked */ | |
1907 | if ((inode = new_inode(sb)) == NULL) { | |
1908 | PRINTK("(%s): new_inode() failed, de: %p\n", de->name, de); | |
1909 | return NULL; | |
1910 | } | |
1911 | if (de->parent) { | |
1912 | read_lock(&de->parent->u.dir.lock); | |
1913 | if (de->prev != de) | |
1914 | de->inode.dentry = dentry; /* Not unhooked */ | |
1915 | read_unlock(&de->parent->u.dir.lock); | |
1916 | } else | |
1917 | de->inode.dentry = dentry; /* Root: no locking needed */ | |
1918 | if (de->inode.dentry != dentry) { /* Must have been unhooked */ | |
1919 | iput(inode); | |
1920 | return NULL; | |
1921 | } | |
1922 | /* FIXME where is devfs_put? */ | |
1923 | inode->u.generic_ip = devfs_get(de); | |
1924 | inode->i_ino = de->inode.ino; | |
1925 | DPRINTK(DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n", | |
1926 | (int)inode->i_ino, inode, de); | |
1927 | inode->i_blocks = 0; | |
1928 | inode->i_blksize = FAKE_BLOCK_SIZE; | |
1929 | inode->i_op = &devfs_iops; | |
1930 | inode->i_mode = de->mode; | |
1931 | if (S_ISDIR(de->mode)) { | |
1932 | inode->i_op = &devfs_dir_iops; | |
1933 | inode->i_fop = &devfs_dir_fops; | |
1934 | } else if (S_ISLNK(de->mode)) { | |
1935 | inode->i_op = &devfs_symlink_iops; | |
1936 | inode->i_size = de->u.symlink.length; | |
1937 | } else if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { | |
1938 | init_special_inode(inode, de->mode, de->u.dev); | |
1939 | } else if (S_ISFIFO(de->mode) || S_ISSOCK(de->mode)) { | |
1940 | init_special_inode(inode, de->mode, 0); | |
1941 | } else { | |
1942 | PRINTK("(%s): unknown mode %o de: %p\n", | |
1943 | de->name, de->mode, de); | |
1944 | iput(inode); | |
1945 | devfs_put(de); | |
1946 | return NULL; | |
1947 | } | |
1948 | ||
1949 | inode->i_uid = de->inode.uid; | |
1950 | inode->i_gid = de->inode.gid; | |
1951 | inode->i_atime = de->inode.atime; | |
1952 | inode->i_mtime = de->inode.mtime; | |
1953 | inode->i_ctime = de->inode.ctime; | |
1954 | DPRINTK(DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n", | |
1955 | (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); | |
1956 | return inode; | |
1957 | } /* End Function _devfs_get_vfs_inode */ | |
1958 | ||
1959 | /* File operations for device entries follow */ | |
1960 | ||
1961 | static int devfs_readdir(struct file *file, void *dirent, filldir_t filldir) | |
1962 | { | |
1963 | int err, count; | |
1964 | int stored = 0; | |
1965 | struct fs_info *fs_info; | |
1966 | struct devfs_entry *parent, *de, *next = NULL; | |
1967 | struct inode *inode = file->f_dentry->d_inode; | |
1968 | ||
1969 | fs_info = inode->i_sb->s_fs_info; | |
1970 | parent = get_devfs_entry_from_vfs_inode(file->f_dentry->d_inode); | |
1971 | if ((long)file->f_pos < 0) | |
1972 | return -EINVAL; | |
1973 | DPRINTK(DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n", | |
1974 | parent->name, fs_info, (long)file->f_pos); | |
1975 | switch ((long)file->f_pos) { | |
1976 | case 0: | |
1977 | err = (*filldir) (dirent, "..", 2, file->f_pos, | |
1978 | parent_ino(file->f_dentry), DT_DIR); | |
1979 | if (err == -EINVAL) | |
1980 | break; | |
1981 | if (err < 0) | |
1982 | return err; | |
1983 | file->f_pos++; | |
1984 | ++stored; | |
1985 | /* Fall through */ | |
1986 | case 1: | |
1987 | err = | |
1988 | (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino, | |
1989 | DT_DIR); | |
1990 | if (err == -EINVAL) | |
1991 | break; | |
1992 | if (err < 0) | |
1993 | return err; | |
1994 | file->f_pos++; | |
1995 | ++stored; | |
1996 | /* Fall through */ | |
1997 | default: | |
1998 | /* Skip entries */ | |
1999 | count = file->f_pos - 2; | |
2000 | read_lock(&parent->u.dir.lock); | |
2001 | for (de = parent->u.dir.first; de && (count > 0); de = de->next) | |
2002 | --count; | |
2003 | devfs_get(de); | |
2004 | read_unlock(&parent->u.dir.lock); | |
2005 | /* Now add all remaining entries */ | |
2006 | while (de) { | |
2007 | err = (*filldir) (dirent, de->name, de->namelen, | |
2008 | file->f_pos, de->inode.ino, | |
2009 | de->mode >> 12); | |
2010 | if (err < 0) | |
2011 | devfs_put(de); | |
2012 | else { | |
2013 | file->f_pos++; | |
2014 | ++stored; | |
2015 | } | |
2016 | if (err == -EINVAL) | |
2017 | break; | |
2018 | if (err < 0) | |
2019 | return err; | |
2020 | read_lock(&parent->u.dir.lock); | |
2021 | next = devfs_get(de->next); | |
2022 | read_unlock(&parent->u.dir.lock); | |
2023 | devfs_put(de); | |
2024 | de = next; | |
2025 | } | |
2026 | break; | |
2027 | } | |
2028 | return stored; | |
2029 | } /* End Function devfs_readdir */ | |
2030 | ||
2031 | /* Open devfs specific special files */ | |
2032 | static int devfs_open(struct inode *inode, struct file *file) | |
2033 | { | |
2034 | int err; | |
2035 | int minor = MINOR(inode->i_rdev); | |
2036 | struct file_operations *old_fops, *new_fops; | |
2037 | ||
2038 | switch (minor) { | |
2039 | case 0: /* /dev/.devfsd */ | |
2040 | new_fops = fops_get(&devfsd_fops); | |
2041 | break; | |
2042 | #ifdef CONFIG_DEVFS_DEBUG | |
2043 | case 1: /* /dev/.stat */ | |
2044 | new_fops = fops_get(&stat_fops); | |
2045 | break; | |
2046 | #endif | |
2047 | default: | |
2048 | return -ENODEV; | |
2049 | } | |
2050 | ||
2051 | if (new_fops == NULL) | |
2052 | return -ENODEV; | |
2053 | old_fops = file->f_op; | |
2054 | file->f_op = new_fops; | |
2055 | err = new_fops->open ? new_fops->open(inode, file) : 0; | |
2056 | if (err) { | |
2057 | file->f_op = old_fops; | |
2058 | fops_put(new_fops); | |
2059 | } else | |
2060 | fops_put(old_fops); | |
2061 | return err; | |
2062 | } /* End Function devfs_open */ | |
2063 | ||
2064 | static struct file_operations devfs_fops = { | |
2065 | .open = devfs_open, | |
2066 | }; | |
2067 | ||
2068 | static struct file_operations devfs_dir_fops = { | |
2069 | .read = generic_read_dir, | |
2070 | .readdir = devfs_readdir, | |
2071 | }; | |
2072 | ||
2073 | /* Dentry operations for device entries follow */ | |
2074 | ||
2075 | /** | |
2076 | * devfs_d_release - Callback for when a dentry is freed. | |
2077 | * @dentry: The dentry. | |
2078 | */ | |
2079 | ||
2080 | static void devfs_d_release(struct dentry *dentry) | |
2081 | { | |
2082 | DPRINTK(DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode); | |
2083 | } /* End Function devfs_d_release */ | |
2084 | ||
2085 | /** | |
2086 | * devfs_d_iput - Callback for when a dentry loses its inode. | |
2087 | * @dentry: The dentry. | |
2088 | * @inode: The inode. | |
2089 | */ | |
2090 | ||
2091 | static void devfs_d_iput(struct dentry *dentry, struct inode *inode) | |
2092 | { | |
2093 | struct devfs_entry *de; | |
2094 | ||
2095 | de = get_devfs_entry_from_vfs_inode(inode); | |
2096 | DPRINTK(DEBUG_D_IPUT, | |
2097 | "(%s): dentry: %p inode: %p de: %p de->dentry: %p\n", de->name, | |
2098 | dentry, inode, de, de->inode.dentry); | |
2099 | if (de->inode.dentry && (de->inode.dentry != dentry)) | |
2100 | OOPS("(%s): de: %p dentry: %p de->dentry: %p\n", | |
2101 | de->name, de, dentry, de->inode.dentry); | |
2102 | de->inode.dentry = NULL; | |
2103 | iput(inode); | |
2104 | devfs_put(de); | |
2105 | } /* End Function devfs_d_iput */ | |
2106 | ||
2107 | static int devfs_d_delete(struct dentry *dentry); | |
2108 | ||
2109 | static struct dentry_operations devfs_dops = { | |
2110 | .d_delete = devfs_d_delete, | |
2111 | .d_release = devfs_d_release, | |
2112 | .d_iput = devfs_d_iput, | |
2113 | }; | |
2114 | ||
2115 | static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *); | |
2116 | ||
2117 | static struct dentry_operations devfs_wait_dops = { | |
2118 | .d_delete = devfs_d_delete, | |
2119 | .d_release = devfs_d_release, | |
2120 | .d_iput = devfs_d_iput, | |
2121 | .d_revalidate = devfs_d_revalidate_wait, | |
2122 | }; | |
2123 | ||
2124 | /** | |
2125 | * devfs_d_delete - Callback for when all files for a dentry are closed. | |
2126 | * @dentry: The dentry. | |
2127 | */ | |
2128 | ||
2129 | static int devfs_d_delete(struct dentry *dentry) | |
2130 | { | |
2131 | struct inode *inode = dentry->d_inode; | |
2132 | ||
2133 | if (dentry->d_op == &devfs_wait_dops) | |
2134 | dentry->d_op = &devfs_dops; | |
2135 | /* Unhash dentry if negative (has no inode) */ | |
2136 | if (inode == NULL) { | |
2137 | DPRINTK(DEBUG_D_DELETE, "(%p): dropping negative dentry\n", | |
2138 | dentry); | |
2139 | return 1; | |
2140 | } | |
2141 | return 0; | |
2142 | } /* End Function devfs_d_delete */ | |
2143 | ||
2144 | struct devfs_lookup_struct { | |
2145 | devfs_handle_t de; | |
2146 | wait_queue_head_t wait_queue; | |
2147 | }; | |
2148 | ||
2149 | /* XXX: this doesn't handle the case where we got a negative dentry | |
2150 | but a devfs entry has been registered in the meanwhile */ | |
2151 | static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) | |
2152 | { | |
2153 | struct inode *dir = dentry->d_parent->d_inode; | |
2154 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2155 | devfs_handle_t parent = get_devfs_entry_from_vfs_inode(dir); | |
2156 | struct devfs_lookup_struct *lookup_info = dentry->d_fsdata; | |
2157 | DECLARE_WAITQUEUE(wait, current); | |
2158 | int need_lock; | |
2159 | ||
2160 | /* | |
2161 | * FIXME HACK | |
2162 | * | |
2163 | * make sure that | |
2164 | * d_instantiate always runs under lock | |
1b1dcc1b | 2165 | * we release i_mutex lock before going to sleep |
1da177e4 LT |
2166 | * |
2167 | * unfortunately sometimes d_revalidate is called with | |
1b1dcc1b | 2168 | * and sometimes without i_mutex lock held. The following checks |
1da177e4 LT |
2169 | * attempt to deduce when we need to add (and drop resp.) lock |
2170 | * here. This relies on current (2.6.2) calling coventions: | |
2171 | * | |
1b1dcc1b | 2172 | * lookup_hash is always run under i_mutex and is passing NULL |
1da177e4 LT |
2173 | * as nd |
2174 | * | |
1b1dcc1b | 2175 | * open(...,O_CREATE,...) calls _lookup_hash under i_mutex |
1da177e4 LT |
2176 | * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE |
2177 | * | |
2178 | * all other invocations of ->d_revalidate seem to happen | |
1b1dcc1b | 2179 | * outside of i_mutex |
1da177e4 LT |
2180 | */ |
2181 | need_lock = nd && | |
2182 | (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT)); | |
2183 | ||
2184 | if (need_lock) | |
1b1dcc1b | 2185 | mutex_lock(&dir->i_mutex); |
1da177e4 LT |
2186 | |
2187 | if (is_devfsd_or_child(fs_info)) { | |
2188 | devfs_handle_t de = lookup_info->de; | |
2189 | struct inode *inode; | |
2190 | ||
2191 | DPRINTK(DEBUG_I_LOOKUP, | |
2192 | "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n", | |
2193 | dentry->d_name.name, dentry, dentry->d_inode, de, | |
2194 | current->comm); | |
2195 | if (dentry->d_inode) | |
2196 | goto out; | |
2197 | if (de == NULL) { | |
2198 | read_lock(&parent->u.dir.lock); | |
2199 | de = _devfs_search_dir(parent, dentry->d_name.name, | |
2200 | dentry->d_name.len); | |
2201 | read_unlock(&parent->u.dir.lock); | |
2202 | if (de == NULL) | |
2203 | goto out; | |
2204 | lookup_info->de = de; | |
2205 | } | |
2206 | /* Create an inode, now that the driver information is available */ | |
2207 | inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); | |
2208 | if (!inode) | |
2209 | goto out; | |
2210 | DPRINTK(DEBUG_I_LOOKUP, | |
2211 | "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", | |
2212 | de->name, de->inode.ino, inode, de, current->comm); | |
2213 | d_instantiate(dentry, inode); | |
2214 | goto out; | |
2215 | } | |
2216 | if (lookup_info == NULL) | |
2217 | goto out; /* Early termination */ | |
2218 | read_lock(&parent->u.dir.lock); | |
2219 | if (dentry->d_fsdata) { | |
2220 | set_current_state(TASK_UNINTERRUPTIBLE); | |
2221 | add_wait_queue(&lookup_info->wait_queue, &wait); | |
2222 | read_unlock(&parent->u.dir.lock); | |
2223 | /* at this point it is always (hopefully) locked */ | |
1b1dcc1b | 2224 | mutex_unlock(&dir->i_mutex); |
1da177e4 | 2225 | schedule(); |
1b1dcc1b | 2226 | mutex_lock(&dir->i_mutex); |
1da177e4 LT |
2227 | /* |
2228 | * This does not need nor should remove wait from wait_queue. | |
2229 | * Wait queue head is never reused - nothing is ever added to it | |
2230 | * after all waiters have been waked up and head itself disappears | |
2231 | * very soon after it. Moreover it is local variable on stack that | |
2232 | * is likely to have already disappeared so any reference to it | |
2233 | * at this point is buggy. | |
2234 | */ | |
2235 | ||
2236 | } else | |
2237 | read_unlock(&parent->u.dir.lock); | |
2238 | ||
2239 | out: | |
2240 | if (need_lock) | |
1b1dcc1b | 2241 | mutex_unlock(&dir->i_mutex); |
1da177e4 LT |
2242 | return 1; |
2243 | } /* End Function devfs_d_revalidate_wait */ | |
2244 | ||
2245 | /* Inode operations for device entries follow */ | |
2246 | ||
2247 | static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry, | |
2248 | struct nameidata *nd) | |
2249 | { | |
2250 | struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */ | |
2251 | struct devfs_lookup_struct lookup_info; | |
2252 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2253 | struct devfs_entry *parent, *de; | |
2254 | struct inode *inode; | |
2255 | struct dentry *retval = NULL; | |
2256 | ||
2257 | /* Set up the dentry operations before anything else, to ensure cleaning | |
2258 | up on any error */ | |
2259 | dentry->d_op = &devfs_dops; | |
2260 | /* First try to get the devfs entry for this directory */ | |
2261 | parent = get_devfs_entry_from_vfs_inode(dir); | |
2262 | DPRINTK(DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n", | |
2263 | dentry->d_name.name, dentry, parent, current->comm); | |
2264 | if (parent == NULL) | |
2265 | return ERR_PTR(-ENOENT); | |
2266 | read_lock(&parent->u.dir.lock); | |
2267 | de = _devfs_search_dir(parent, dentry->d_name.name, dentry->d_name.len); | |
2268 | read_unlock(&parent->u.dir.lock); | |
2269 | lookup_info.de = de; | |
2270 | init_waitqueue_head(&lookup_info.wait_queue); | |
2271 | dentry->d_fsdata = &lookup_info; | |
2272 | if (de == NULL) { /* Try with devfsd. For any kind of failure, leave a negative dentry | |
2273 | so someone else can deal with it (in the case where the sysadmin | |
2274 | does a mknod()). It's important to do this before hashing the | |
2275 | dentry, so that the devfsd queue is filled before revalidates | |
2276 | can start */ | |
2277 | if (try_modload(parent, fs_info, dentry->d_name.name, dentry->d_name.len, &tmp) < 0) { /* Lookup event was not queued to devfsd */ | |
2278 | d_add(dentry, NULL); | |
2279 | return NULL; | |
2280 | } | |
2281 | } | |
2282 | dentry->d_op = &devfs_wait_dops; | |
2283 | d_add(dentry, NULL); /* Open the floodgates */ | |
2284 | /* Unlock directory semaphore, which will release any waiters. They | |
2285 | will get the hashed dentry, and may be forced to wait for | |
2286 | revalidation */ | |
1b1dcc1b | 2287 | mutex_unlock(&dir->i_mutex); |
1da177e4 | 2288 | wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */ |
1b1dcc1b | 2289 | mutex_lock(&dir->i_mutex); /* Grab it again because them's the rules */ |
1da177e4 LT |
2290 | de = lookup_info.de; |
2291 | /* If someone else has been so kind as to make the inode, we go home | |
2292 | early */ | |
2293 | if (dentry->d_inode) | |
2294 | goto out; | |
2295 | if (de == NULL) { | |
2296 | read_lock(&parent->u.dir.lock); | |
2297 | de = _devfs_search_dir(parent, dentry->d_name.name, | |
2298 | dentry->d_name.len); | |
2299 | read_unlock(&parent->u.dir.lock); | |
2300 | if (de == NULL) | |
2301 | goto out; | |
2302 | /* OK, there's an entry now, but no VFS inode yet */ | |
2303 | } | |
2304 | /* Create an inode, now that the driver information is available */ | |
2305 | inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); | |
2306 | if (!inode) { | |
2307 | retval = ERR_PTR(-ENOMEM); | |
2308 | goto out; | |
2309 | } | |
2310 | DPRINTK(DEBUG_I_LOOKUP, | |
2311 | "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", de->name, | |
2312 | de->inode.ino, inode, de, current->comm); | |
2313 | d_instantiate(dentry, inode); | |
2314 | out: | |
2315 | write_lock(&parent->u.dir.lock); | |
2316 | dentry->d_op = &devfs_dops; | |
2317 | dentry->d_fsdata = NULL; | |
2318 | wake_up(&lookup_info.wait_queue); | |
2319 | write_unlock(&parent->u.dir.lock); | |
2320 | devfs_put(de); | |
2321 | return retval; | |
2322 | } /* End Function devfs_lookup */ | |
2323 | ||
2324 | static int devfs_unlink(struct inode *dir, struct dentry *dentry) | |
2325 | { | |
2326 | int unhooked; | |
2327 | struct devfs_entry *de; | |
2328 | struct inode *inode = dentry->d_inode; | |
2329 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2330 | ||
2331 | de = get_devfs_entry_from_vfs_inode(inode); | |
2332 | DPRINTK(DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de); | |
2333 | if (de == NULL) | |
2334 | return -ENOENT; | |
2335 | if (!de->vfs) | |
2336 | return -EPERM; | |
2337 | write_lock(&de->parent->u.dir.lock); | |
2338 | unhooked = _devfs_unhook(de); | |
2339 | write_unlock(&de->parent->u.dir.lock); | |
2340 | if (!unhooked) | |
2341 | return -ENOENT; | |
2342 | if (!is_devfsd_or_child(fs_info)) | |
2343 | devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, | |
2344 | inode->i_uid, inode->i_gid, fs_info); | |
2345 | free_dentry(de); | |
2346 | devfs_put(de); | |
2347 | return 0; | |
2348 | } /* End Function devfs_unlink */ | |
2349 | ||
2350 | static int devfs_symlink(struct inode *dir, struct dentry *dentry, | |
2351 | const char *symname) | |
2352 | { | |
2353 | int err; | |
2354 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2355 | struct devfs_entry *parent, *de; | |
2356 | struct inode *inode; | |
2357 | ||
2358 | /* First try to get the devfs entry for this directory */ | |
2359 | parent = get_devfs_entry_from_vfs_inode(dir); | |
2360 | if (parent == NULL) | |
2361 | return -ENOENT; | |
2362 | err = devfs_do_symlink(parent, dentry->d_name.name, symname, &de); | |
2363 | DPRINTK(DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n", | |
2364 | dentry->d_name.name, err); | |
2365 | if (err < 0) | |
2366 | return err; | |
2367 | de->vfs = TRUE; | |
2368 | de->inode.uid = current->euid; | |
2369 | de->inode.gid = current->egid; | |
2370 | de->inode.atime = CURRENT_TIME; | |
2371 | de->inode.mtime = CURRENT_TIME; | |
2372 | de->inode.ctime = CURRENT_TIME; | |
2373 | if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) | |
2374 | return -ENOMEM; | |
2375 | DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", | |
2376 | dentry->d_name.name, de->inode.ino, inode, dentry); | |
2377 | d_instantiate(dentry, inode); | |
2378 | if (!is_devfsd_or_child(fs_info)) | |
2379 | devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, | |
2380 | inode->i_uid, inode->i_gid, fs_info); | |
2381 | return 0; | |
2382 | } /* End Function devfs_symlink */ | |
2383 | ||
2384 | static int devfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |
2385 | { | |
2386 | int err; | |
2387 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2388 | struct devfs_entry *parent, *de; | |
2389 | struct inode *inode; | |
2390 | ||
2391 | mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */ | |
2392 | parent = get_devfs_entry_from_vfs_inode(dir); | |
2393 | if (parent == NULL) | |
2394 | return -ENOENT; | |
2395 | de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); | |
2396 | if (!de) | |
2397 | return -ENOMEM; | |
2398 | de->vfs = TRUE; | |
2399 | if ((err = _devfs_append_entry(parent, de, NULL)) != 0) | |
2400 | return err; | |
2401 | de->inode.uid = current->euid; | |
2402 | de->inode.gid = current->egid; | |
2403 | de->inode.atime = CURRENT_TIME; | |
2404 | de->inode.mtime = CURRENT_TIME; | |
2405 | de->inode.ctime = CURRENT_TIME; | |
2406 | if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) | |
2407 | return -ENOMEM; | |
2408 | DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", | |
2409 | dentry->d_name.name, de->inode.ino, inode, dentry); | |
2410 | d_instantiate(dentry, inode); | |
2411 | if (!is_devfsd_or_child(fs_info)) | |
2412 | devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, | |
2413 | inode->i_uid, inode->i_gid, fs_info); | |
2414 | return 0; | |
2415 | } /* End Function devfs_mkdir */ | |
2416 | ||
2417 | static int devfs_rmdir(struct inode *dir, struct dentry *dentry) | |
2418 | { | |
2419 | int err = 0; | |
2420 | struct devfs_entry *de; | |
2421 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2422 | struct inode *inode = dentry->d_inode; | |
2423 | ||
2424 | if (dir->i_sb->s_fs_info != inode->i_sb->s_fs_info) | |
2425 | return -EINVAL; | |
2426 | de = get_devfs_entry_from_vfs_inode(inode); | |
2427 | if (de == NULL) | |
2428 | return -ENOENT; | |
2429 | if (!S_ISDIR(de->mode)) | |
2430 | return -ENOTDIR; | |
2431 | if (!de->vfs) | |
2432 | return -EPERM; | |
2433 | /* First ensure the directory is empty and will stay that way */ | |
2434 | write_lock(&de->u.dir.lock); | |
2435 | if (de->u.dir.first) | |
2436 | err = -ENOTEMPTY; | |
2437 | else | |
2438 | de->u.dir.no_more_additions = TRUE; | |
2439 | write_unlock(&de->u.dir.lock); | |
2440 | if (err) | |
2441 | return err; | |
2442 | /* Now unhook the directory from its parent */ | |
2443 | write_lock(&de->parent->u.dir.lock); | |
2444 | if (!_devfs_unhook(de)) | |
2445 | err = -ENOENT; | |
2446 | write_unlock(&de->parent->u.dir.lock); | |
2447 | if (err) | |
2448 | return err; | |
2449 | if (!is_devfsd_or_child(fs_info)) | |
2450 | devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, | |
2451 | inode->i_uid, inode->i_gid, fs_info); | |
2452 | free_dentry(de); | |
2453 | devfs_put(de); | |
2454 | return 0; | |
2455 | } /* End Function devfs_rmdir */ | |
2456 | ||
2457 | static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |
2458 | dev_t rdev) | |
2459 | { | |
2460 | int err; | |
2461 | struct fs_info *fs_info = dir->i_sb->s_fs_info; | |
2462 | struct devfs_entry *parent, *de; | |
2463 | struct inode *inode; | |
2464 | ||
2465 | DPRINTK(DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", | |
2466 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); | |
2467 | parent = get_devfs_entry_from_vfs_inode(dir); | |
2468 | if (parent == NULL) | |
2469 | return -ENOENT; | |
2470 | de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); | |
2471 | if (!de) | |
2472 | return -ENOMEM; | |
2473 | de->vfs = TRUE; | |
2474 | if (S_ISCHR(mode) || S_ISBLK(mode)) | |
2475 | de->u.dev = rdev; | |
2476 | if ((err = _devfs_append_entry(parent, de, NULL)) != 0) | |
2477 | return err; | |
2478 | de->inode.uid = current->euid; | |
2479 | de->inode.gid = current->egid; | |
2480 | de->inode.atime = CURRENT_TIME; | |
2481 | de->inode.mtime = CURRENT_TIME; | |
2482 | de->inode.ctime = CURRENT_TIME; | |
2483 | if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) | |
2484 | return -ENOMEM; | |
2485 | DPRINTK(DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n", | |
2486 | de->inode.ino, inode, dentry); | |
2487 | d_instantiate(dentry, inode); | |
2488 | if (!is_devfsd_or_child(fs_info)) | |
2489 | devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, | |
2490 | inode->i_uid, inode->i_gid, fs_info); | |
2491 | return 0; | |
2492 | } /* End Function devfs_mknod */ | |
2493 | ||
008b150a | 2494 | static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
1da177e4 LT |
2495 | { |
2496 | struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode); | |
2497 | nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV)); | |
008b150a | 2498 | return NULL; |
1da177e4 LT |
2499 | } /* End Function devfs_follow_link */ |
2500 | ||
2501 | static struct inode_operations devfs_iops = { | |
2502 | .setattr = devfs_notify_change, | |
2503 | }; | |
2504 | ||
2505 | static struct inode_operations devfs_dir_iops = { | |
2506 | .lookup = devfs_lookup, | |
2507 | .unlink = devfs_unlink, | |
2508 | .symlink = devfs_symlink, | |
2509 | .mkdir = devfs_mkdir, | |
2510 | .rmdir = devfs_rmdir, | |
2511 | .mknod = devfs_mknod, | |
2512 | .setattr = devfs_notify_change, | |
2513 | }; | |
2514 | ||
2515 | static struct inode_operations devfs_symlink_iops = { | |
2516 | .readlink = generic_readlink, | |
2517 | .follow_link = devfs_follow_link, | |
2518 | .setattr = devfs_notify_change, | |
2519 | }; | |
2520 | ||
2521 | static int devfs_fill_super(struct super_block *sb, void *data, int silent) | |
2522 | { | |
2523 | struct inode *root_inode = NULL; | |
2524 | ||
2525 | if (_devfs_get_root_entry() == NULL) | |
2526 | goto out_no_root; | |
2527 | atomic_set(&fs_info.devfsd_overrun_count, 0); | |
2528 | init_waitqueue_head(&fs_info.devfsd_wait_queue); | |
2529 | init_waitqueue_head(&fs_info.revalidate_wait_queue); | |
2530 | fs_info.sb = sb; | |
2531 | sb->s_fs_info = &fs_info; | |
2532 | sb->s_blocksize = 1024; | |
2533 | sb->s_blocksize_bits = 10; | |
2534 | sb->s_magic = DEVFS_SUPER_MAGIC; | |
2535 | sb->s_op = &devfs_sops; | |
2536 | sb->s_time_gran = 1; | |
2537 | if ((root_inode = _devfs_get_vfs_inode(sb, root_entry, NULL)) == NULL) | |
2538 | goto out_no_root; | |
2539 | sb->s_root = d_alloc_root(root_inode); | |
2540 | if (!sb->s_root) | |
2541 | goto out_no_root; | |
2542 | DPRINTK(DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->s_fs_info); | |
2543 | return 0; | |
2544 | ||
2545 | out_no_root: | |
2546 | PRINTK("(): get root inode failed\n"); | |
2547 | if (root_inode) | |
2548 | iput(root_inode); | |
2549 | return -EINVAL; | |
2550 | } /* End Function devfs_fill_super */ | |
2551 | ||
2552 | static struct super_block *devfs_get_sb(struct file_system_type *fs_type, | |
2553 | int flags, const char *dev_name, | |
2554 | void *data) | |
2555 | { | |
2556 | return get_sb_single(fs_type, flags, data, devfs_fill_super); | |
2557 | } | |
2558 | ||
2559 | static struct file_system_type devfs_fs_type = { | |
2560 | .name = DEVFS_NAME, | |
2561 | .get_sb = devfs_get_sb, | |
2562 | .kill_sb = kill_anon_super, | |
2563 | }; | |
2564 | ||
2565 | /* File operations for devfsd follow */ | |
2566 | ||
2567 | static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len, | |
2568 | loff_t * ppos) | |
2569 | { | |
2570 | int done = FALSE; | |
2571 | int ival; | |
2572 | loff_t pos, devname_offset, tlen, rpos; | |
2573 | devfs_handle_t de; | |
2574 | struct devfsd_buf_entry *entry; | |
2575 | struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->s_fs_info; | |
2576 | struct devfsd_notify_struct *info = fs_info->devfsd_info; | |
2577 | DECLARE_WAITQUEUE(wait, current); | |
2578 | ||
2579 | /* Verify the task has grabbed the queue */ | |
2580 | if (fs_info->devfsd_task != current) | |
2581 | return -EPERM; | |
2582 | info->major = 0; | |
2583 | info->minor = 0; | |
2584 | /* Block for a new entry */ | |
2585 | set_current_state(TASK_INTERRUPTIBLE); | |
2586 | add_wait_queue(&fs_info->devfsd_wait_queue, &wait); | |
2587 | while (devfsd_queue_empty(fs_info)) { | |
2588 | fs_info->devfsd_sleeping = TRUE; | |
2589 | wake_up(&fs_info->revalidate_wait_queue); | |
2590 | schedule(); | |
2591 | fs_info->devfsd_sleeping = FALSE; | |
2592 | if (signal_pending(current)) { | |
2593 | remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); | |
2594 | __set_current_state(TASK_RUNNING); | |
2595 | return -EINTR; | |
2596 | } | |
2597 | set_current_state(TASK_INTERRUPTIBLE); | |
2598 | } | |
2599 | remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); | |
2600 | __set_current_state(TASK_RUNNING); | |
2601 | /* Now play with the data */ | |
2602 | ival = atomic_read(&fs_info->devfsd_overrun_count); | |
2603 | info->overrun_count = ival; | |
2604 | entry = fs_info->devfsd_first_event; | |
2605 | info->type = entry->type; | |
2606 | info->mode = entry->mode; | |
2607 | info->uid = entry->uid; | |
2608 | info->gid = entry->gid; | |
2609 | de = entry->de; | |
2610 | if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { | |
2611 | info->major = MAJOR(de->u.dev); | |
2612 | info->minor = MINOR(de->u.dev); | |
2613 | } | |
2614 | pos = devfs_generate_path(de, info->devname, DEVFS_PATHLEN); | |
2615 | if (pos < 0) | |
2616 | return pos; | |
2617 | info->namelen = DEVFS_PATHLEN - pos - 1; | |
2618 | if (info->mode == 0) | |
2619 | info->mode = de->mode; | |
2620 | devname_offset = info->devname - (char *)info; | |
2621 | rpos = *ppos; | |
2622 | if (rpos < devname_offset) { | |
2623 | /* Copy parts of the header */ | |
2624 | tlen = devname_offset - rpos; | |
2625 | if (tlen > len) | |
2626 | tlen = len; | |
2627 | if (copy_to_user(buf, (char *)info + rpos, tlen)) { | |
2628 | return -EFAULT; | |
2629 | } | |
2630 | rpos += tlen; | |
2631 | buf += tlen; | |
2632 | len -= tlen; | |
2633 | } | |
2634 | if ((rpos >= devname_offset) && (len > 0)) { | |
2635 | /* Copy the name */ | |
2636 | tlen = info->namelen + 1; | |
2637 | if (tlen > len) | |
2638 | tlen = len; | |
2639 | else | |
2640 | done = TRUE; | |
2641 | if (copy_to_user | |
2642 | (buf, info->devname + pos + rpos - devname_offset, tlen)) { | |
2643 | return -EFAULT; | |
2644 | } | |
2645 | rpos += tlen; | |
2646 | } | |
2647 | tlen = rpos - *ppos; | |
2648 | if (done) { | |
2649 | devfs_handle_t parent; | |
2650 | ||
2651 | spin_lock(&fs_info->devfsd_buffer_lock); | |
2652 | fs_info->devfsd_first_event = entry->next; | |
2653 | if (entry->next == NULL) | |
2654 | fs_info->devfsd_last_event = NULL; | |
2655 | spin_unlock(&fs_info->devfsd_buffer_lock); | |
2656 | for (; de != NULL; de = parent) { | |
2657 | parent = de->parent; | |
2658 | devfs_put(de); | |
2659 | } | |
2660 | kmem_cache_free(devfsd_buf_cache, entry); | |
2661 | if (ival > 0) | |
2662 | atomic_sub(ival, &fs_info->devfsd_overrun_count); | |
2663 | *ppos = 0; | |
2664 | } else | |
2665 | *ppos = rpos; | |
2666 | return tlen; | |
2667 | } /* End Function devfsd_read */ | |
2668 | ||
2669 | static int devfsd_ioctl(struct inode *inode, struct file *file, | |
2670 | unsigned int cmd, unsigned long arg) | |
2671 | { | |
2672 | int ival; | |
2673 | struct fs_info *fs_info = inode->i_sb->s_fs_info; | |
2674 | ||
2675 | switch (cmd) { | |
2676 | case DEVFSDIOC_GET_PROTO_REV: | |
2677 | ival = DEVFSD_PROTOCOL_REVISION_KERNEL; | |
2678 | if (copy_to_user((void __user *)arg, &ival, sizeof ival)) | |
2679 | return -EFAULT; | |
2680 | break; | |
2681 | case DEVFSDIOC_SET_EVENT_MASK: | |
2682 | /* Ensure only one reader has access to the queue. This scheme will | |
2683 | work even if the global kernel lock were to be removed, because it | |
2684 | doesn't matter who gets in first, as long as only one gets it */ | |
2685 | if (fs_info->devfsd_task == NULL) { | |
2686 | static DEFINE_SPINLOCK(lock); | |
2687 | ||
2688 | if (!spin_trylock(&lock)) | |
2689 | return -EBUSY; | |
2690 | if (fs_info->devfsd_task != NULL) { /* We lost the race... */ | |
2691 | spin_unlock(&lock); | |
2692 | return -EBUSY; | |
2693 | } | |
2694 | fs_info->devfsd_task = current; | |
2695 | spin_unlock(&lock); | |
2696 | fs_info->devfsd_pgrp = | |
2697 | (process_group(current) == | |
2698 | current->pid) ? process_group(current) : 0; | |
2699 | fs_info->devfsd_file = file; | |
2700 | fs_info->devfsd_info = | |
2701 | kmalloc(sizeof *fs_info->devfsd_info, GFP_KERNEL); | |
2702 | if (!fs_info->devfsd_info) { | |
2703 | devfsd_close(inode, file); | |
2704 | return -ENOMEM; | |
2705 | } | |
2706 | } else if (fs_info->devfsd_task != current) | |
2707 | return -EBUSY; | |
2708 | fs_info->devfsd_event_mask = arg; /* Let the masses come forth */ | |
2709 | break; | |
2710 | case DEVFSDIOC_RELEASE_EVENT_QUEUE: | |
2711 | if (fs_info->devfsd_file != file) | |
2712 | return -EPERM; | |
2713 | return devfsd_close(inode, file); | |
2714 | /*break; */ | |
2715 | #ifdef CONFIG_DEVFS_DEBUG | |
2716 | case DEVFSDIOC_SET_DEBUG_MASK: | |
2717 | if (copy_from_user(&ival, (void __user *)arg, sizeof ival)) | |
2718 | return -EFAULT; | |
2719 | devfs_debug = ival; | |
2720 | break; | |
2721 | #endif | |
2722 | default: | |
2723 | return -ENOIOCTLCMD; | |
2724 | } | |
2725 | return 0; | |
2726 | } /* End Function devfsd_ioctl */ | |
2727 | ||
2728 | static int devfsd_close(struct inode *inode, struct file *file) | |
2729 | { | |
2730 | struct devfsd_buf_entry *entry, *next; | |
2731 | struct fs_info *fs_info = inode->i_sb->s_fs_info; | |
2732 | ||
2733 | if (fs_info->devfsd_file != file) | |
2734 | return 0; | |
2735 | fs_info->devfsd_event_mask = 0; | |
2736 | fs_info->devfsd_file = NULL; | |
2737 | spin_lock(&fs_info->devfsd_buffer_lock); | |
2738 | entry = fs_info->devfsd_first_event; | |
2739 | fs_info->devfsd_first_event = NULL; | |
2740 | fs_info->devfsd_last_event = NULL; | |
f99d49ad JJ |
2741 | kfree(fs_info->devfsd_info); |
2742 | fs_info->devfsd_info = NULL; | |
1da177e4 LT |
2743 | spin_unlock(&fs_info->devfsd_buffer_lock); |
2744 | fs_info->devfsd_pgrp = 0; | |
2745 | fs_info->devfsd_task = NULL; | |
2746 | wake_up(&fs_info->revalidate_wait_queue); | |
2747 | for (; entry; entry = next) { | |
2748 | next = entry->next; | |
2749 | kmem_cache_free(devfsd_buf_cache, entry); | |
2750 | } | |
2751 | return 0; | |
2752 | } /* End Function devfsd_close */ | |
2753 | ||
2754 | #ifdef CONFIG_DEVFS_DEBUG | |
2755 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, | |
2756 | loff_t * ppos) | |
2757 | { | |
2758 | ssize_t num; | |
2759 | char txt[80]; | |
2760 | ||
2761 | num = sprintf(txt, "Number of entries: %u number of bytes: %u\n", | |
2762 | stat_num_entries, stat_num_bytes) + 1; | |
2763 | if (*ppos >= num) | |
2764 | return 0; | |
2765 | if (*ppos + len > num) | |
2766 | len = num - *ppos; | |
2767 | if (copy_to_user(buf, txt + *ppos, len)) | |
2768 | return -EFAULT; | |
2769 | *ppos += len; | |
2770 | return len; | |
2771 | } /* End Function stat_read */ | |
2772 | #endif | |
2773 | ||
2774 | static int __init init_devfs_fs(void) | |
2775 | { | |
2776 | int err; | |
2777 | int major; | |
2778 | struct devfs_entry *devfsd; | |
2779 | #ifdef CONFIG_DEVFS_DEBUG | |
2780 | struct devfs_entry *stat; | |
2781 | #endif | |
2782 | ||
2783 | if (_devfs_get_root_entry() == NULL) | |
2784 | return -ENOMEM; | |
2785 | ||
2786 | printk(KERN_INFO "%s: %s Richard Gooch (rgooch@atnf.csiro.au)\n", | |
2787 | DEVFS_NAME, DEVFS_VERSION); | |
2788 | devfsd_buf_cache = kmem_cache_create("devfsd_event", | |
2789 | sizeof(struct devfsd_buf_entry), | |
2790 | 0, 0, NULL, NULL); | |
2791 | if (!devfsd_buf_cache) | |
2792 | OOPS("(): unable to allocate event slab\n"); | |
2793 | #ifdef CONFIG_DEVFS_DEBUG | |
2794 | devfs_debug = devfs_debug_init; | |
2795 | printk(KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug); | |
2796 | #endif | |
2797 | printk(KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options); | |
2798 | ||
2799 | /* register special device for devfsd communication */ | |
2800 | major = register_chrdev(0, "devfs", &devfs_fops); | |
2801 | if (major < 0) | |
2802 | return major; | |
2803 | ||
2804 | /* And create the entry for ".devfsd" */ | |
2805 | devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR | S_IRUSR | S_IWUSR); | |
2806 | if (devfsd == NULL) | |
2807 | return -ENOMEM; | |
2808 | devfsd->u.dev = MKDEV(major, 0); | |
2809 | _devfs_append_entry(root_entry, devfsd, NULL); | |
2810 | ||
2811 | #ifdef CONFIG_DEVFS_DEBUG | |
2812 | stat = _devfs_alloc_entry(".stat", 0, S_IFCHR | S_IRUGO); | |
2813 | if (stat == NULL) | |
2814 | return -ENOMEM; | |
2815 | stat->u.dev = MKDEV(major, 1); | |
2816 | _devfs_append_entry(root_entry, stat, NULL); | |
2817 | #endif | |
2818 | ||
2819 | err = register_filesystem(&devfs_fs_type); | |
2820 | return err; | |
2821 | } /* End Function init_devfs_fs */ | |
2822 | ||
2823 | void __init mount_devfs_fs(void) | |
2824 | { | |
2825 | int err; | |
2826 | ||
2827 | if (!(boot_options & OPTION_MOUNT)) | |
2828 | return; | |
2829 | err = do_mount("none", "/dev", "devfs", 0, NULL); | |
2830 | if (err == 0) | |
2831 | printk(KERN_INFO "Mounted devfs on /dev\n"); | |
2832 | else | |
2833 | PRINTK("(): unable to mount devfs, err: %d\n", err); | |
2834 | } /* End Function mount_devfs_fs */ | |
2835 | ||
2836 | module_init(init_devfs_fs) |