clean
[linux-2.4.21-pre4.git] / fs / devfs / util.c
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
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
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
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
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
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
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
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
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);