DRIVER(drive)->busy++;
g->minors = 1;
g->minor_shift = 0;
- strcpy(g->devfs_name, drive->devfs_name);
+ snprintf(g->devfs_name, sizeof(g->devfs_name),
+ "%s/cd", drive->devfs_name);
g->driverfs_dev = &drive->gendev;
g->flags = GENHD_FL_CD;
if (ide_cdrom_setup(drive)) {
get_capabilities(cd);
sr_vendor_init(cd);
- strcpy(disk->devfs_name, sdev->devfs_name);
+ snprintf(disk->devfs_name, sizeof(disk->devfs_name),
+ "%s/cd", sdev->devfs_name);
disk->driverfs_dev = &sdev->sdev_driverfs_dev;
register_cdrom(&cd->cdi);
set_capacity(disk, cd->capacity);
#include <asm/bitops.h>
#include "internal.h"
-#define PRINTK(format, args...) \
- {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
int devfs_register_tape(const char *name)
{
up(&device_list_mutex);
}
-struct unique_numspace
-{
- spinlock_t init_lock;
- unsigned char sem_initialised;
- unsigned int num_free; /* Num free in bits */
- unsigned int length; /* Array length in bytes */
- unsigned long *bits;
- struct semaphore semaphore;
-};
-
-#define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL}
-
-
-/**
- * devfs_alloc_unique_number - Allocate a unique (positive) number.
- * @space: The number space to allocate from.
- *
- * Returns the allocated unique number, else a negative error code.
- * This routine is thread safe and may block.
- */
-
-int devfs_alloc_unique_number (struct unique_numspace *space)
-{
- int number;
- unsigned int length;
-
- /* Get around stupid lack of semaphore initialiser */
- spin_lock (&space->init_lock);
- if (!space->sem_initialised)
- {
- sema_init (&space->semaphore, 1);
- space->sem_initialised = 1;
- }
- spin_unlock (&space->init_lock);
- down (&space->semaphore);
- if (space->num_free < 1)
- {
- void *bits;
-
- if (space->length < 16) length = 16;
- else length = space->length << 1;
- if ( ( bits = vmalloc (length) ) == NULL )
- {
- up (&space->semaphore);
- return -ENOMEM;
- }
- if (space->bits != NULL)
- {
- memcpy (bits, space->bits, space->length);
- vfree (space->bits);
- }
- space->num_free = (length - space->length) << 3;
- space->bits = bits;
- memset (bits + space->length, 0, length - space->length);
- space->length = length;
- }
- number = find_first_zero_bit (space->bits, space->length << 3);
- --space->num_free;
- __set_bit (number, space->bits);
- up (&space->semaphore);
- return number;
-} /* End Function devfs_alloc_unique_number */
-EXPORT_SYMBOL(devfs_alloc_unique_number);
-
-
-/**
- * devfs_dealloc_unique_number - Deallocate a unique (positive) number.
- * @space: The number space to deallocate from.
- * @number: The number to deallocate.
- *
- * This routine is thread safe and may block.
- */
-
-void devfs_dealloc_unique_number (struct unique_numspace *space, int number)
-{
- int was_set;
-
- if (number < 0) return;
- down (&space->semaphore);
- was_set = __test_and_clear_bit (number, space->bits);
- if (was_set) ++space->num_free;
- up (&space->semaphore);
- if (!was_set) PRINTK ("(): number %d was already free\n", number);
-} /* End Function devfs_dealloc_unique_number */
-EXPORT_SYMBOL(devfs_dealloc_unique_number);
-
-static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
-static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
-
-void devfs_create_partitions(struct gendisk *disk)
-{
- char dirname[64], diskname[64], symlink[16];
-
- if (!disk->devfs_name)
- sprintf(disk->devfs_name, "%s/disc%d", disk->disk_name,
- disk->first_minor >> disk->minor_shift);
-
- devfs_mk_dir(disk->devfs_name);
- disk->number = devfs_alloc_unique_number(&disc_numspace);
-
- sprintf(diskname, "%s/disc", disk->devfs_name);
- devfs_register(NULL, diskname, 0,
- disk->major, disk->first_minor,
- S_IFBLK | S_IRUSR | S_IWUSR,
- disk->fops, NULL);
-
- sprintf(symlink, "discs/disc%d", disk->number);
- sprintf(dirname, "../%s", disk->devfs_name);
- devfs_mk_symlink(symlink, dirname);
-
-}
-
-void devfs_create_cdrom(struct gendisk *disk)
-{
- char dirname[64], cdname[64], symlink[16];
-
- if (!disk->devfs_name)
- strcat(disk->devfs_name, disk->disk_name);
-
- devfs_mk_dir(disk->devfs_name);
- disk->number = devfs_alloc_unique_number(&cdrom_numspace);
-
- sprintf(cdname, "%s/cd", disk->devfs_name);
- devfs_register(NULL, cdname, 0,
- disk->major, disk->first_minor,
- S_IFBLK | S_IRUGO | S_IWUGO,
- disk->fops, NULL);
-
- sprintf(symlink, "cdroms/cdrom%d", disk->number);
- sprintf(dirname, "../%s", disk->devfs_name);
- devfs_mk_symlink(symlink, dirname);
-}
-
void devfs_register_partition(struct gendisk *dev, int part)
{
char devname[64];
S_IFBLK | S_IRUSR | S_IWUSR,
dev->fops, NULL);
}
-
-void devfs_remove_partitions(struct gendisk *disk)
-{
- devfs_remove("discs/disc%d", disk->number);
- devfs_remove(disk->devfs_name);
- devfs_dealloc_unique_number(&disc_numspace, disk->number);
-}
-
-void devfs_remove_cdrom(struct gendisk *disk)
-{
- devfs_remove("cdroms/cdrom%d", disk->number);
- devfs_remove(disk->devfs_name);
- devfs_dealloc_unique_number(&cdrom_numspace, disk->number);
-}
obj-y := check.o
+obj-$(CONFIG_DEVFS_FS) += devfs.o
obj-$(CONFIG_ACORN_PARTITION) += acorn.o
obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
obj-$(CONFIG_ATARI_PARTITION) += atari.o
#include <linux/blk.h>
#include <linux/kmod.h>
#include <linux/ctype.h>
+#include <linux/devfs_fs_kernel.h>
#include "check.h"
+#include "devfs.h"
#include "acorn.h"
#include "amiga.h"
char *disk_name(struct gendisk *hd, int part, char *buf)
{
- if (!part) {
#ifdef CONFIG_DEVFS_FS
- if (hd->devfs_name)
- sprintf(buf, "%s/%s", hd->devfs_name,
- (hd->flags & GENHD_FL_CD) ? "cd" : "disc");
- else
-#endif
- sprintf(buf, "%s", hd->disk_name);
- } else {
-#ifdef CONFIG_DEVFS_FS
- if (hd->devfs_name)
+ if (hd->devfs_name[0] != '\0') {
+ if (part)
sprintf(buf, "%s/part%d", hd->devfs_name, part);
+ else if (hd->minors != 1)
+ sprintf(buf, "%s/disc", hd->devfs_name);
else
-#endif
- if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
- sprintf(buf, "%sp%d", hd->disk_name, part);
- else
- sprintf(buf, "%s%d", hd->disk_name, part);
+ sprintf(buf, "%s", hd->devfs_name);
+ return buf;
}
+#endif
+
+ if (!part)
+ sprintf(buf, "%s", hd->disk_name);
+ else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
+ sprintf(buf, "%sp%d", hd->disk_name, part);
+ else
+ sprintf(buf, "%s%d", hd->disk_name, part);
return buf;
}
return NULL;
#ifdef CONFIG_DEVFS_FS
- if (hd->devfs_name) {
+ if (hd->devfs_name[0] != '\0') {
printk(KERN_INFO " /dev/%s:", hd->devfs_name);
sprintf(state->name, "p");
}
return;
disk_sysfs_symlinks(disk);
- if (disk->flags & GENHD_FL_CD)
- devfs_create_cdrom(disk);
-
/* No minors to use for partitions */
- if (disk->minors == 1)
+ if (disk->minors == 1) {
+ if (disk->devfs_name[0] != '\0')
+ devfs_add_disk(disk);
return;
+ }
/* No such device (e.g., media were just removed) */
if (!get_capacity(disk))
if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
return;
state = check_partition(disk, bdev);
- devfs_create_partitions(disk);
+ devfs_add_partitioned(disk);
if (state) {
for (j = 1; j < state->limit; j++) {
sector_t size = state->parts[j].size;
unlink_gendisk(disk);
disk_stat_set_all(disk, 0);
disk->stamp = disk->stamp_idle = 0;
- if (disk->flags & GENHD_FL_CD)
- devfs_remove_cdrom(disk);
- else
- devfs_remove_partitions(disk);
+
+ devfs_remove_disk(disk);
+
if (disk->driverfs_dev) {
sysfs_remove_link(&disk->kobj, "device");
sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
--- /dev/null
+/*
+ * This tries to keep block devices away from devfs as much as possible.
+ */
+#include <linux/fs.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/genhd.h>
+#include <asm/bitops.h>
+#include <asm/semaphore.h>
+
+
+struct unique_numspace {
+ u32 num_free; /* Num free in bits */
+ u32 length; /* Array length in bytes */
+ unsigned long *bits;
+ struct semaphore mutex;
+};
+
+static DECLARE_MUTEX(numspace_mutex);
+
+static int expand_numspace(struct unique_numspace *s)
+{
+ u32 length;
+ void *bits;
+
+ if (s->length < 16)
+ length = 16;
+ else
+ length = s->length << 1;
+
+ bits = vmalloc(length);
+ if (!bits)
+ return -ENOMEM;
+ if (s->bits) {
+ memcpy(bits, s->bits, s->length);
+ vfree(s->bits);
+ }
+
+ s->num_free = (length - s->length) << 3;
+ s->bits = bits;
+ memset(bits + s->length, 0, length - s->length);
+ s->length = length;
+
+ return 0;
+}
+
+static int alloc_unique_number(struct unique_numspace *s)
+{
+ int rval = 0;
+
+ down(&numspace_mutex);
+ if (s->num_free < 1)
+ rval = expand_numspace(s);
+ if (!rval) {
+ rval = find_first_zero_bit(s->bits, s->length << 3);
+ --s->num_free;
+ __set_bit(rval, s->bits);
+ }
+ up(&numspace_mutex);
+
+ return rval;
+}
+
+static void dealloc_unique_number(struct unique_numspace *s, int number)
+{
+ int old_val;
+
+ if (number >= 0) {
+ down(&numspace_mutex);
+ old_val = __test_and_clear_bit(number, s->bits);
+ if (old_val)
+ ++s->num_free;
+ up(&numspace_mutex);
+ }
+}
+
+static struct unique_numspace disc_numspace;
+static struct unique_numspace cdrom_numspace;
+
+void devfs_add_partitioned(struct gendisk *disk)
+{
+ char dirname[64], symlink[16];
+
+ if (disk->devfs_name[0] != '\0')
+ sprintf(disk->devfs_name, "%s/disc%d", disk->disk_name,
+ disk->first_minor >> disk->minor_shift);
+
+ devfs_mk_dir(disk->devfs_name);
+ devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
+ S_IFBLK|S_IRUSR|S_IWUSR,
+ "%s/disc", disk->devfs_name);
+
+ disk->number = alloc_unique_number(&disc_numspace);
+
+ sprintf(symlink, "discs/disc%d", disk->number);
+ sprintf(dirname, "../%s", disk->devfs_name);
+ devfs_mk_symlink(symlink, dirname);
+
+}
+
+void devfs_add_disk(struct gendisk *disk)
+{
+ devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
+ (disk->flags & GENHD_FL_CD) ?
+ S_IFBLK|S_IRUGO|S_IWUGO :
+ S_IFBLK|S_IRUSR|S_IWUSR,
+ "%s", disk->devfs_name);
+
+ if (disk->flags & GENHD_FL_CD) {
+ char dirname[64], symlink[16];
+
+ disk->number = alloc_unique_number(&cdrom_numspace);
+
+ sprintf(symlink, "cdroms/cdrom%d", disk->number);
+ sprintf(dirname, "../%s", disk->devfs_name);
+ devfs_mk_symlink(symlink, dirname);
+ }
+}
+
+void devfs_remove_disk(struct gendisk *disk)
+{
+ if (disk->minors != 1) {
+ devfs_remove("discs/disc%d", disk->number);
+ dealloc_unique_number(&disc_numspace, disk->number);
+ devfs_remove("%s/disc", disk->devfs_name);
+ }
+ if (disk->flags & GENHD_FL_CD) {
+ devfs_remove("cdroms/cdrom%d", disk->number);
+ dealloc_unique_number(&cdrom_numspace, disk->number);
+ }
+ devfs_remove(disk->devfs_name);
+}
+
+
--- /dev/null
+
+#ifdef CONFIG_DEVFS_FS
+void devfs_add_disk(struct gendisk *dev);
+void devfs_add_partitioned(struct gendisk *dev);
+void devfs_remove_disk(struct gendisk *dev);
+#else
+# define devfs_add_disk(disk) do { } while (0)
+# define devfs_add_partitioned(disk) do { } while (0)
+# define devfs_remove_disk(disk) do { } while (0)
+#endif
__attribute__((format (printf, 1, 2)));
extern int devfs_register_tape(const char *name);
extern void devfs_unregister_tape(int num);
-extern void devfs_create_partitions(struct gendisk *dev);
-extern void devfs_create_cdrom(struct gendisk *dev);
-extern void devfs_remove_partitions(struct gendisk *dev);
-extern void devfs_remove_cdrom(struct gendisk *dev);
extern void devfs_register_partition(struct gendisk *dev, int part);
extern void mount_devfs_fs(void);
#else /* CONFIG_DEVFS_FS */
static inline void devfs_unregister_tape(int num)
{
}
-static inline void devfs_create_partitions(struct gendisk *dev)
-{
-}
-static inline void devfs_create_cdrom(struct gendisk *dev)
-{
-}
-static inline void devfs_remove_partitions(struct gendisk *dev)
-{
-}
-static inline void devfs_remove_cdrom(struct gendisk *dev)
-{
-}
static inline void devfs_register_partition(struct gendisk *dev, int part)
{
}