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
......@@ -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