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