Commit 995058f2 authored by Christoph Hellwig's avatar Christoph Hellwig

[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.
parent 02da7e62
No related merge requests found
......@@ -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)) {
......
......@@ -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);
......
......@@ -74,8 +74,6 @@
#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)
{
......@@ -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);
}
......@@ -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
......
......@@ -19,8 +19,10 @@
#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"
......@@ -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");
......
/*
* 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);
}
#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
......@@ -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)
{
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment