]> git.hungrycats.org Git - linux/commitdiff
[PATCH] devfs: gendisk.devfs_name updates
authorChristoph Hellwig <hch@lst.de>
Sun, 20 Apr 2003 07:41:28 +0000 (00:41 -0700)
committerChristoph Hellwig <hch@lst.de>
Sun, 20 Apr 2003 07:41:28 +0000 (00:41 -0700)
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
drivers/scsi/sr.c
fs/devfs/util.c
fs/partitions/Makefile
fs/partitions/check.c
fs/partitions/devfs.c [new file with mode: 0644]
fs/partitions/devfs.h [new file with mode: 0644]
include/linux/devfs_fs_kernel.h

index 44303c540eb4ae68d70235722b5e63f7b981e269..3e7a5888bcd9870fa88f8280b74b297d5cc4b8b7 100644 (file)
@@ -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)) {
index 069a260bd879c77eb9a994a45b1fd778fc2ad5cc..ffb4478bef1ebfdd471383e852cd41427ddbcccd 100644 (file)
@@ -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);
index 3ce61ea5a0424958b5e9d1c36c46a6a2551c49f8..823652cb61bb973239bffc5782ba75b08665a07e 100644 (file)
@@ -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);
-}
index 4d9c91a4c33a867eaec835618bf1f06413063541..4c83c17969e12505248dc0767985af06b568062e 100644 (file)
@@ -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
index 647f0357e30c6ece940f07e6b15791fc8a3e8a2a..ddd1b88d78196911752b1f282a64b7db49704e46 100644 (file)
 #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");
diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c
new file mode 100644 (file)
index 0000000..6736248
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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);
+}
+
+
diff --git a/fs/partitions/devfs.h b/fs/partitions/devfs.h
new file mode 100644 (file)
index 0000000..176118b
--- /dev/null
@@ -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
index e19d6d1ec733093d320f90fca9ec821ffb4f28d3..a45a4060236d83f7838f5db688ae85786644000a 100644 (file)
@@ -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)
 {
 }