Skip to content

Commit 3e1a7ff

Browse files
htejunJens Axboe
authored andcommitted
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]>
1 parent 689d6fa commit 3e1a7ff

File tree

5 files changed

+82
-23
lines changed

5 files changed

+82
-23
lines changed

block/genhd.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,37 @@ static int exact_lock(dev_t devt, void *data)
478478
*
479479
* This function registers the partitioning information in @disk
480480
* with the kernel.
481+
*
482+
* FIXME: error handling
481483
*/
482484
void add_disk(struct gendisk *disk)
483485
{
484486
struct backing_dev_info *bdi;
487+
dev_t devt;
485488
int retval;
486489

490+
/* minors == 0 indicates to use ext devt from part0 and should
491+
* be accompanied with EXT_DEVT flag. Make sure all
492+
* parameters make sense.
493+
*/
494+
WARN_ON(disk->minors && !(disk->major || disk->first_minor));
495+
WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
496+
487497
disk->flags |= GENHD_FL_UP;
488-
disk_to_dev(disk)->devt = MKDEV(disk->major, disk->first_minor);
498+
499+
retval = blk_alloc_devt(&disk->part0, &devt);
500+
if (retval) {
501+
WARN_ON(1);
502+
return;
503+
}
504+
disk_to_dev(disk)->devt = devt;
505+
506+
/* ->major and ->first_minor aren't supposed to be
507+
* dereferenced from here on, but set them just in case.
508+
*/
509+
disk->major = MAJOR(devt);
510+
disk->first_minor = MINOR(devt);
511+
489512
blk_register_region(disk_devt(disk), disk->minors, NULL,
490513
exact_match, exact_lock, disk);
491514
register_disk(disk);

drivers/ide/ide-disk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
4545
#define IDE_DISK_MINORS (1 << PARTN_BITS)
4646
#else
47-
#define IDE_DISK_MINORS 1
47+
#define IDE_DISK_MINORS 0
4848
#endif
4949

5050
struct ide_disk_obj {

drivers/scsi/sd.c

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
8989
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
9090
#define SD_MINORS 16
9191
#else
92-
#define SD_MINORS 1
92+
#define SD_MINORS 0
9393
#endif
9494

9595
static int sd_revalidate_disk(struct gendisk *);
@@ -1769,6 +1769,52 @@ static int sd_revalidate_disk(struct gendisk *disk)
17691769
return 0;
17701770
}
17711771

1772+
/**
1773+
* sd_format_disk_name - format disk name
1774+
* @prefix: name prefix - ie. "sd" for SCSI disks
1775+
* @index: index of the disk to format name for
1776+
* @buf: output buffer
1777+
* @buflen: length of the output buffer
1778+
*
1779+
* SCSI disk names starts at sda. The 26th device is sdz and the
1780+
* 27th is sdaa. The last one for two lettered suffix is sdzz
1781+
* which is followed by sdaaa.
1782+
*
1783+
* This is basically 26 base counting with one extra 'nil' entry
1784+
* at the beggining from the second digit on and can be
1785+
* determined using similar method as 26 base conversion with the
1786+
* index shifted -1 after each digit is computed.
1787+
*
1788+
* CONTEXT:
1789+
* Don't care.
1790+
*
1791+
* RETURNS:
1792+
* 0 on success, -errno on failure.
1793+
*/
1794+
static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
1795+
{
1796+
const int base = 'z' - 'a' + 1;
1797+
char *begin = buf + strlen(prefix);
1798+
char *end = buf + buflen;
1799+
char *p;
1800+
int unit;
1801+
1802+
p = end - 1;
1803+
*p = '\0';
1804+
unit = base;
1805+
do {
1806+
if (p == begin)
1807+
return -EINVAL;
1808+
*--p = 'a' + (index % unit);
1809+
index = (index / unit) - 1;
1810+
} while (index >= 0);
1811+
1812+
memmove(begin, p, end - p);
1813+
memcpy(buf, prefix, strlen(prefix));
1814+
1815+
return 0;
1816+
}
1817+
17721818
/**
17731819
* sd_probe - called during driver initialization and whenever a
17741820
* new scsi device is attached to the system. It is called once
@@ -1821,8 +1867,8 @@ static int sd_probe(struct device *dev)
18211867
if (error)
18221868
goto out_put;
18231869

1824-
error = -EBUSY;
1825-
if (index >= SD_MAX_DISKS)
1870+
error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
1871+
if (error)
18261872
goto out_free_index;
18271873

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

18501896
get_device(&sdp->sdev_gendev);
18511897

1852-
gd->major = sd_major((index & 0xf0) >> 4);
1853-
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
1854-
gd->minors = SD_MINORS;
1855-
gd->fops = &sd_fops;
1856-
1857-
if (index < 26) {
1858-
sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
1859-
} else if (index < (26 + 1) * 26) {
1860-
sprintf(gd->disk_name, "sd%c%c",
1861-
'a' + index / 26 - 1,'a' + index % 26);
1862-
} else {
1863-
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
1864-
const unsigned int m2 = (index / 26 - 1) % 26;
1865-
const unsigned int m3 = index % 26;
1866-
sprintf(gd->disk_name, "sd%c%c%c",
1867-
'a' + m1, 'a' + m2, 'a' + m3);
1898+
if (index < SD_MAX_DISKS) {
1899+
gd->major = sd_major((index & 0xf0) >> 4);
1900+
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
1901+
gd->minors = SD_MINORS;
18681902
}
1869-
1903+
gd->fops = &sd_fops;
18701904
gd->private_data = &sdkp->driver;
18711905
gd->queue = sdkp->device->request_queue;
18721906

fs/partitions/check.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ void del_gendisk(struct gendisk *disk)
593593
disk_part_iter_exit(&piter);
594594

595595
invalidate_partition(disk, 0);
596+
blk_free_devt(disk_to_dev(disk)->devt);
596597
set_capacity(disk, 0);
597598
disk->flags &= ~GENHD_FL_UP;
598599
unlink_gendisk(disk);

include/linux/genhd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ enum {
5959
};
6060

6161
#define DISK_MAX_PARTS 256
62+
#define DISK_NAME_LEN 32
6263

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

143-
char disk_name[32]; /* name of major driver */
144+
char disk_name[DISK_NAME_LEN]; /* name of major driver */
144145

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

0 commit comments

Comments
 (0)