From 995058f217a4091e22af5798a922e2ab25f842ae Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Apr 2003 00:41:28 -0700 Subject: [PATCH] [PATCH] devfs: gendisk.devfs_name updates Previously gendisk.devfs_name was used only for partitioned devices or CDroms, and for the latter it was slightly broken. Fix it to work genericly for all gendisks. --- drivers/ide/ide-cd.c | 3 +- drivers/scsi/sr.c | 3 +- fs/devfs/util.c | 149 -------------------------------- fs/partitions/Makefile | 1 + fs/partitions/check.c | 50 +++++------ fs/partitions/devfs.c | 134 ++++++++++++++++++++++++++++ fs/partitions/devfs.h | 10 +++ include/linux/devfs_fs_kernel.h | 16 ---- 8 files changed, 174 insertions(+), 192 deletions(-) create mode 100644 fs/partitions/devfs.c create mode 100644 fs/partitions/devfs.h diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 44303c540eb4a..3e7a5888bcd98 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3366,7 +3366,8 @@ static int ide_cdrom_attach (ide_drive_t *drive) 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)) { diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 069a260bd879c..ffb4478bef1eb 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -569,7 +569,8 @@ static int sr_attach(struct scsi_device *sdev) 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); diff --git a/fs/devfs/util.c b/fs/devfs/util.c index 3ce61ea5a0424..823652cb61bb9 100644 --- a/fs/devfs/util.c +++ b/fs/devfs/util.c @@ -74,8 +74,6 @@ #include #include "internal.h" -#define PRINTK(format, args...) \ - {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} int devfs_register_tape(const char *name) { @@ -257,139 +255,6 @@ void devfs_dealloc_devnum(umode_t mode, dev_t devnum) 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]; @@ -400,17 +265,3 @@ void devfs_register_partition(struct gendisk *dev, int part) 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); -} diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile index 4d9c91a4c33a8..4c83c17969e12 100644 --- a/fs/partitions/Makefile +++ b/fs/partitions/Makefile @@ -4,6 +4,7 @@ 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 diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 647f0357e30c6..ddd1b88d78196 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -19,8 +19,10 @@ #include #include #include +#include #include "check.h" +#include "devfs.h" #include "acorn.h" #include "amiga.h" @@ -94,25 +96,24 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = 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; } @@ -128,7 +129,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) 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"); } @@ -284,12 +285,12 @@ void register_disk(struct gendisk *disk) 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)) @@ -299,7 +300,7 @@ void register_disk(struct gendisk *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; @@ -392,10 +393,9 @@ void del_gendisk(struct gendisk *disk) 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"); diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c new file mode 100644 index 0000000000000..67362483b4dce --- /dev/null +++ b/fs/partitions/devfs.c @@ -0,0 +1,134 @@ +/* + * This tries to keep block devices away from devfs as much as possible. + */ +#include +#include +#include +#include +#include +#include + + +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); +} + + diff --git a/fs/partitions/devfs.h b/fs/partitions/devfs.h new file mode 100644 index 0000000000000..176118b4e492d --- /dev/null +++ b/fs/partitions/devfs.h @@ -0,0 +1,10 @@ + +#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 diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index e19d6d1ec7330..a45a4060236d8 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -34,10 +34,6 @@ extern void devfs_remove(const char *fmt, ...) __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 */ @@ -73,18 +69,6 @@ static inline int devfs_register_tape (devfs_handle_t de) 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) { } -- 2.53.0