block: allow disk to have extended device number

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]>
This commit is contained in:
Tejun Heo 2008-08-25 19:56:17 +09:00 • committed by Jens Axboe
commit 3e1a7ff8a0
5 changed files with 82 additions and 23 deletions

View file

@ -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 *);
@ -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
@ -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;
@ -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;