1 /* devfs (Device FileSystem) utilities.
2
3 Copyright (C) 1999-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 19991031 Richard Gooch <rgooch@atnf.csiro.au>
26 Created.
27 19991103 Richard Gooch <rgooch@atnf.csiro.au>
28 Created <_devfs_convert_name> and supported SCSI and IDE CD-ROMs
29 20000203 Richard Gooch <rgooch@atnf.csiro.au>
30 Changed operations pointer type to void *.
31 20000621 Richard Gooch <rgooch@atnf.csiro.au>
32 Changed interface to <devfs_register_series>.
33 20000622 Richard Gooch <rgooch@atnf.csiro.au>
34 Took account of interface change to <devfs_mk_symlink>.
35 Took account of interface change to <devfs_mk_dir>.
36 20010519 Richard Gooch <rgooch@atnf.csiro.au>
37 Documentation cleanup.
38 20010709 Richard Gooch <rgooch@atnf.csiro.au>
39 Created <devfs_*alloc_major> and <devfs_*alloc_devnum>.
40 20010710 Richard Gooch <rgooch@atnf.csiro.au>
41 Created <devfs_*alloc_unique_number>.
42 20010730 Richard Gooch <rgooch@atnf.csiro.au>
43 Documentation typo fix.
44 20010806 Richard Gooch <rgooch@atnf.csiro.au>
45 Made <block_semaphore> and <char_semaphore> private.
46 20010813 Richard Gooch <rgooch@atnf.csiro.au>
47 Fixed bug in <devfs_alloc_unique_number>: limited to 128 numbers
48 20010818 Richard Gooch <rgooch@atnf.csiro.au>
49 Updated major masks up to Linus' "no new majors" proclamation.
50 Block: were 126 now 122 free, char: were 26 now 19 free.
51 20020324 Richard Gooch <rgooch@atnf.csiro.au>
52 Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
53 bitfield.
54 20020326 Richard Gooch <rgooch@atnf.csiro.au>
55 Fixed bitfield data type for <devfs_*alloc_devnum>.
56 Made major bitfield type and initialiser 64 bit safe.
57 20020413 Richard Gooch <rgooch@atnf.csiro.au>
58 Fixed shift warning on 64 bit machines.
59 20020428 Richard Gooch <rgooch@atnf.csiro.au>
60 Copied and used macro for error messages from fs/devfs/base.c
61 */
62 #include <linux/module.h>
63 #include <linux/init.h>
64 #include <linux/devfs_fs_kernel.h>
65 #include <linux/slab.h>
66 #include <linux/vmalloc.h>
67
68 #include <asm/bitops.h>
69
70 #define PRINTK(format, args...) \
71 {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
72
73
74 /* Private functions follow */
75
76 /**
77 * devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy.
78 * @de: Any tape device entry in the device directory.
79 */
80
devfs_register_tape(devfs_handle_t de)81 void devfs_register_tape (devfs_handle_t de)
82 {
83 int pos;
84 devfs_handle_t parent, slave;
85 char name[16], dest[64];
86 static unsigned int tape_counter;
87 static devfs_handle_t tape_dir;
88
89 if (tape_dir == NULL) tape_dir = devfs_mk_dir (NULL, "tapes", NULL);
90 parent = devfs_get_parent (de);
91 pos = devfs_generate_path (parent, dest + 3, sizeof dest - 3);
92 if (pos < 0) return;
93 strncpy (dest + pos, "../", 3);
94 sprintf (name, "tape%u", tape_counter++);
95 devfs_mk_symlink (tape_dir, name, DEVFS_FL_DEFAULT, dest + pos,
96 &slave, NULL);
97 devfs_auto_unregister (de, slave);
98 } /* End Function devfs_register_tape */
99 EXPORT_SYMBOL(devfs_register_tape);
100
101
102 /**
103 * devfs_register_series - Register a sequence of device entries.
104 * @dir: The handle to the parent devfs directory entry. If this is %NULL
105 * the new names are relative to the root of the devfs.
106 * @format: The printf-style format string. A single "\%u" is allowed.
107 * @num_entries: The number of entries to register.
108 * @flags: A set of bitwise-ORed flags (DEVFS_FL_*).
109 * @major: The major number. Not needed for regular files.
110 * @minor_start: The starting minor number. Not needed for regular files.
111 * @mode: The default file mode.
112 * @ops: The &file_operations or &block_device_operations structure.
113 * This must not be externally deallocated.
114 * @info: An arbitrary pointer which will be written to the private_data
115 * field of the &file structure passed to the device driver. You
116 * can set this to whatever you like, and change it once the file
117 * is opened (the next file opened will not see this change).
118 */
119
devfs_register_series(devfs_handle_t dir,const char * format,unsigned int num_entries,unsigned int flags,unsigned int major,unsigned int minor_start,umode_t mode,void * ops,void * info)120 void devfs_register_series (devfs_handle_t dir, const char *format,
121 unsigned int num_entries, unsigned int flags,
122 unsigned int major, unsigned int minor_start,
123 umode_t mode, void *ops, void *info)
124 {
125 unsigned int count;
126 char devname[128];
127
128 for (count = 0; count < num_entries; ++count)
129 {
130 sprintf (devname, format, count);
131 devfs_register (dir, devname, flags, major, minor_start + count,
132 mode, ops, info);
133 }
134 } /* End Function devfs_register_series */
135 EXPORT_SYMBOL(devfs_register_series);
136
137
138 struct major_list
139 {
140 spinlock_t lock;
141 unsigned long bits[256 / BITS_PER_LONG];
142 };
143 #if BITS_PER_LONG == 32
144 # define INITIALISER64(low,high) (low), (high)
145 #else
146 # define INITIALISER64(low,high) ( (unsigned long) (high) << 32 | (low) )
147 #endif
148
149 /* Block majors already assigned:
150 0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
151 Total free: 122
152 */
153 static struct major_list block_major_list =
154 {SPIN_LOCK_UNLOCKED,
155 {INITIALISER64 (0xfffffb8f, 0xffffffff), /* Majors 0-31, 32-63 */
156 INITIALISER64 (0xfffffffe, 0xff03ffef), /* Majors 64-95, 96-127 */
157 INITIALISER64 (0x00000000, 0x00000000), /* Majors 128-159, 160-191 */
158 INITIALISER64 (0x00000280, 0xffff0000), /* Majors 192-223, 224-255 */
159 }
160 };
161
162 /* Char majors already assigned:
163 0-7, 9-151, 154-158, 160-211, 216-221, 224-230, 240-255
164 Total free: 19
165 */
166 static struct major_list char_major_list =
167 {SPIN_LOCK_UNLOCKED,
168 {INITIALISER64 (0xfffffeff, 0xffffffff), /* Majors 0-31, 32-63 */
169 INITIALISER64 (0xffffffff, 0xffffffff), /* Majors 64-95, 96-127 */
170 INITIALISER64 (0x7cffffff, 0xffffffff), /* Majors 128-159, 160-191 */
171 INITIALISER64 (0x3f0fffff, 0xffff007f), /* Majors 192-223, 224-255 */
172 }
173 };
174
175
176 /**
177 * devfs_alloc_major - Allocate a major number.
178 * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
179
180 * Returns the allocated major, else -1 if none are available.
181 * This routine is thread safe and does not block.
182 */
183
devfs_alloc_major(char type)184 int devfs_alloc_major (char type)
185 {
186 int major;
187 struct major_list *list;
188
189 list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
190 spin_lock (&list->lock);
191 major = find_first_zero_bit (list->bits, 256);
192 if (major < 256) __set_bit (major, list->bits);
193 else major = -1;
194 spin_unlock (&list->lock);
195 return major;
196 } /* End Function devfs_alloc_major */
197 EXPORT_SYMBOL(devfs_alloc_major);
198
199
200 /**
201 * devfs_dealloc_major - Deallocate a major number.
202 * @type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK)
203 * @major: The major number.
204 * This routine is thread safe and does not block.
205 */
206
devfs_dealloc_major(char type,int major)207 void devfs_dealloc_major (char type, int major)
208 {
209 int was_set;
210 struct major_list *list;
211
212 if (major < 0) return;
213 list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
214 spin_lock (&list->lock);
215 was_set = __test_and_clear_bit (major, list->bits);
216 spin_unlock (&list->lock);
217 if (!was_set) PRINTK ("(): major %d was already free\n", major);
218 } /* End Function devfs_dealloc_major */
219 EXPORT_SYMBOL(devfs_dealloc_major);
220
221
222 struct minor_list
223 {
224 int major;
225 unsigned long bits[256 / BITS_PER_LONG];
226 struct minor_list *next;
227 };
228
229 struct device_list
230 {
231 struct minor_list *first, *last;
232 int none_free;
233 };
234
235 static DECLARE_MUTEX (block_semaphore);
236 static struct device_list block_list;
237
238 static DECLARE_MUTEX (char_semaphore);
239 static struct device_list char_list;
240
241
242 /**
243 * devfs_alloc_devnum - Allocate a device number.
244 * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK).
245 *
246 * Returns the allocated device number, else NODEV if none are available.
247 * This routine is thread safe and may block.
248 */
249
devfs_alloc_devnum(char type)250 kdev_t devfs_alloc_devnum (char type)
251 {
252 int minor;
253 struct semaphore *semaphore;
254 struct device_list *list;
255 struct minor_list *entry;
256
257 if (type == DEVFS_SPECIAL_CHR)
258 {
259 semaphore = &char_semaphore;
260 list = &char_list;
261 }
262 else
263 {
264 semaphore = &block_semaphore;
265 list = &block_list;
266 }
267 if (list->none_free) return NODEV; /* Fast test */
268 down (semaphore);
269 if (list->none_free)
270 {
271 up (semaphore);
272 return NODEV;
273 }
274 for (entry = list->first; entry != NULL; entry = entry->next)
275 {
276 minor = find_first_zero_bit (entry->bits, 256);
277 if (minor >= 256) continue;
278 __set_bit (minor, entry->bits);
279 up (semaphore);
280 return mk_kdev (entry->major, minor);
281 }
282 /* Need to allocate a new major */
283 if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL )
284 {
285 list->none_free = 1;
286 up (semaphore);
287 return NODEV;
288 }
289 memset (entry, 0, sizeof *entry);
290 if ( ( entry->major = devfs_alloc_major (type) ) < 0 )
291 {
292 list->none_free = 1;
293 up (semaphore);
294 kfree (entry);
295 return NODEV;
296 }
297 __set_bit (0, entry->bits);
298 if (list->first == NULL) list->first = entry;
299 else list->last->next = entry;
300 list->last = entry;
301 up (semaphore);
302 return mk_kdev (entry->major, 0);
303 } /* End Function devfs_alloc_devnum */
304 EXPORT_SYMBOL(devfs_alloc_devnum);
305
306
307 /**
308 * devfs_dealloc_devnum - Dellocate a device number.
309 * @type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK).
310 * @devnum: The device number.
311 *
312 * This routine is thread safe and does not block.
313 */
314
devfs_dealloc_devnum(char type,kdev_t devnum)315 void devfs_dealloc_devnum (char type, kdev_t devnum)
316 {
317 int major, minor;
318 struct semaphore *semaphore;
319 struct device_list *list;
320 struct minor_list *entry;
321
322 if ( kdev_none (devnum) ) return;
323 if (type == DEVFS_SPECIAL_CHR)
324 {
325 semaphore = &char_semaphore;
326 list = &char_list;
327 }
328 else
329 {
330 semaphore = &block_semaphore;
331 list = &block_list;
332 }
333 major = major (devnum);
334 minor = minor (devnum);
335 down (semaphore);
336 for (entry = list->first; entry != NULL; entry = entry->next)
337 {
338 int was_set;
339
340 if (entry->major != major) continue;
341 was_set = __test_and_clear_bit (minor, entry->bits);
342 if (was_set) list->none_free = 0;
343 up (semaphore);
344 if (!was_set)
345 PRINTK ( "(): device %s was already free\n", kdevname (devnum) );
346 return;
347 }
348 up (semaphore);
349 PRINTK ( "(): major for %s not previously allocated\n",
350 kdevname (devnum) );
351 } /* End Function devfs_dealloc_devnum */
352 EXPORT_SYMBOL(devfs_dealloc_devnum);
353
354
355 /**
356 * devfs_alloc_unique_number - Allocate a unique (positive) number.
357 * @space: The number space to allocate from.
358 *
359 * Returns the allocated unique number, else a negative error code.
360 * This routine is thread safe and may block.
361 */
362
devfs_alloc_unique_number(struct unique_numspace * space)363 int devfs_alloc_unique_number (struct unique_numspace *space)
364 {
365 int number;
366 unsigned int length;
367
368 /* Get around stupid lack of semaphore initialiser */
369 spin_lock (&space->init_lock);
370 if (!space->sem_initialised)
371 {
372 sema_init (&space->semaphore, 1);
373 space->sem_initialised = 1;
374 }
375 spin_unlock (&space->init_lock);
376 down (&space->semaphore);
377 if (space->num_free < 1)
378 {
379 void *bits;
380
381 if (space->length < 16) length = 16;
382 else length = space->length << 1;
383 if ( ( bits = vmalloc (length) ) == NULL )
384 {
385 up (&space->semaphore);
386 return -ENOMEM;
387 }
388 if (space->bits != NULL)
389 {
390 memcpy (bits, space->bits, space->length);
391 vfree (space->bits);
392 }
393 space->num_free = (length - space->length) << 3;
394 space->bits = bits;
395 memset (bits + space->length, 0, length - space->length);
396 space->length = length;
397 }
398 number = find_first_zero_bit (space->bits, space->length << 3);
399 --space->num_free;
400 __set_bit (number, space->bits);
401 up (&space->semaphore);
402 return number;
403 } /* End Function devfs_alloc_unique_number */
404 EXPORT_SYMBOL(devfs_alloc_unique_number);
405
406
407 /**
408 * devfs_dealloc_unique_number - Deallocate a unique (positive) number.
409 * @space: The number space to deallocate from.
410 * @number: The number to deallocate.
411 *
412 * This routine is thread safe and may block.
413 */
414
devfs_dealloc_unique_number(struct unique_numspace * space,int number)415 void devfs_dealloc_unique_number (struct unique_numspace *space, int number)
416 {
417 int was_set;
418
419 if (number < 0) return;
420 down (&space->semaphore);
421 was_set = __test_and_clear_bit (number, space->bits);
422 if (was_set) ++space->num_free;
423 up (&space->semaphore);
424 if (!was_set) PRINTK ("(): number %d was already free\n", number);
425 } /* End Function devfs_dealloc_unique_number */
426 EXPORT_SYMBOL(devfs_dealloc_unique_number);
427