Skip to content

Commit

Permalink
block: allow disk to have extended device number
Browse files Browse the repository at this point in the history
Now that disk and partition handlings are mostly unified, it's easy to
allow disk to have extended device number.  This patch makes
add_disk() use extended device number if disk->minors is zero.  Both
sd and ide-disk are updated to use this.

* sd_format_disk_name() is implemented which can generically determine
  the drive name.  This removes disk number restriction stemming from
  limited device names.

* If sd index goes over SD_MAX_DISKS (which can be increased now BTW),
  sd simply doesn't initialize minors letting block layer choose
  extended device number.

* If CONFIG_DEBUG_EXT_DEVT is set, both sd and ide-disk always set
  minors to 0 and use extended device numbers.

Signed-off-by: Tejun Heo <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
htejun authored and Jens Axboe committed Oct 9, 2008
1 parent 689d6fa commit 3e1a7ff
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 23 deletions.
25 changes: 24 additions & 1 deletion block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,14 +478,37 @@ static int exact_lock(dev_t devt, void *data)
*
* This function registers the partitioning information in @disk
* with the kernel.
*
* FIXME: error handling
*/
void add_disk(struct gendisk *disk)
{
struct backing_dev_info *bdi;
dev_t devt;
int retval;

/* minors == 0 indicates to use ext devt from part0 and should
* be accompanied with EXT_DEVT flag. Make sure all
* parameters make sense.
*/
WARN_ON(disk->minors && !(disk->major || disk->first_minor));
WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));

disk->flags |= GENHD_FL_UP;
disk_to_dev(disk)->devt = MKDEV(disk->major, disk->first_minor);

retval = blk_alloc_devt(&disk->part0, &devt);
if (retval) {
WARN_ON(1);
return;
}
disk_to_dev(disk)->devt = devt;

/* ->major and ->first_minor aren't supposed to be
* dereferenced from here on, but set them just in case.
*/
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);

blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
register_disk(disk);
Expand Down
2 changes: 1 addition & 1 deletion drivers/ide/ide-disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
#define IDE_DISK_MINORS (1 << PARTN_BITS)
#else
#define IDE_DISK_MINORS 1
#define IDE_DISK_MINORS 0
#endif

struct ide_disk_obj {
Expand Down
74 changes: 54 additions & 20 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
#define SD_MINORS 16
#else
#define SD_MINORS 1
#define SD_MINORS 0
#endif

static int sd_revalidate_disk(struct gendisk *);
Expand Down Expand Up @@ -1769,6 +1769,52 @@ static int sd_revalidate_disk(struct gendisk *disk)
return 0;
}

/**
* sd_format_disk_name - format disk name
* @prefix: name prefix - ie. "sd" for SCSI disks
* @index: index of the disk to format name for
* @buf: output buffer
* @buflen: length of the output buffer
*
* SCSI disk names starts at sda. The 26th device is sdz and the
* 27th is sdaa. The last one for two lettered suffix is sdzz
* which is followed by sdaaa.
*
* This is basically 26 base counting with one extra 'nil' entry
* at the beggining from the second digit on and can be
* determined using similar method as 26 base conversion with the
* index shifted -1 after each digit is computed.
*
* CONTEXT:
* Don't care.
*
* RETURNS:
* 0 on success, -errno on failure.
*/
static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
{
const int base = 'z' - 'a' + 1;
char *begin = buf + strlen(prefix);
char *end = buf + buflen;
char *p;
int unit;

p = end - 1;
*p = '\0';
unit = base;
do {
if (p == begin)
return -EINVAL;
*--p = 'a' + (index % unit);
index = (index / unit) - 1;
} while (index >= 0);

memmove(begin, p, end - p);
memcpy(buf, prefix, strlen(prefix));

return 0;
}

/**
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
Expand Down Expand Up @@ -1821,8 +1867,8 @@ static int sd_probe(struct device *dev)
if (error)
goto out_put;

error = -EBUSY;
if (index >= SD_MAX_DISKS)
error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
if (error)
goto out_free_index;

sdkp->device = sdp;
Expand All @@ -1849,24 +1895,12 @@ static int sd_probe(struct device *dev)

get_device(&sdp->sdev_gendev);

gd->major = sd_major((index & 0xf0) >> 4);
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
gd->minors = SD_MINORS;
gd->fops = &sd_fops;

if (index < 26) {
sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
} else if (index < (26 + 1) * 26) {
sprintf(gd->disk_name, "sd%c%c",
'a' + index / 26 - 1,'a' + index % 26);
} else {
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
const unsigned int m2 = (index / 26 - 1) % 26;
const unsigned int m3 = index % 26;
sprintf(gd->disk_name, "sd%c%c%c",
'a' + m1, 'a' + m2, 'a' + m3);
if (index < SD_MAX_DISKS) {
gd->major = sd_major((index & 0xf0) >> 4);
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
gd->minors = SD_MINORS;
}

gd->fops = &sd_fops;
gd->private_data = &sdkp->driver;
gd->queue = sdkp->device->request_queue;

Expand Down
1 change: 1 addition & 0 deletions fs/partitions/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ void del_gendisk(struct gendisk *disk)
disk_part_iter_exit(&piter);

invalidate_partition(disk, 0);
blk_free_devt(disk_to_dev(disk)->devt);
set_capacity(disk, 0);
disk->flags &= ~GENHD_FL_UP;
unlink_gendisk(disk);
Expand Down
3 changes: 2 additions & 1 deletion include/linux/genhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum {
};

#define DISK_MAX_PARTS 256
#define DISK_NAME_LEN 32

#include <linux/major.h>
#include <linux/device.h>
Expand Down Expand Up @@ -140,7 +141,7 @@ struct gendisk {
int minors; /* maximum number of minors, =1 for
* disks that can't be partitioned. */

char disk_name[32]; /* name of major driver */
char disk_name[DISK_NAME_LEN]; /* name of major driver */

/* Array of pointers to partitions indexed by partno.
* Protected with matching bdev lock but stat and other
Expand Down

0 comments on commit 3e1a7ff

Please sign in to comment.