Commit 3e1a7ff8a0a7b948f2684930166954f9e8e776fe
Committed by
Jens Axboe
1 parent
689d6fac40
Exists in
master
and in
7 other branches
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 <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Showing 5 changed files with 82 additions and 23 deletions Side-by-side Diff
block/genhd.c
... | ... | @@ -478,14 +478,37 @@ |
478 | 478 | * |
479 | 479 | * This function registers the partitioning information in @disk |
480 | 480 | * with the kernel. |
481 | + * | |
482 | + * FIXME: error handling | |
481 | 483 | */ |
482 | 484 | void add_disk(struct gendisk *disk) |
483 | 485 | { |
484 | 486 | struct backing_dev_info *bdi; |
487 | + dev_t devt; | |
485 | 488 | int retval; |
486 | 489 | |
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 | + | |
487 | 497 | 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 | + | |
489 | 512 | blk_register_region(disk_devt(disk), disk->minors, NULL, |
490 | 513 | exact_match, exact_lock, disk); |
491 | 514 | register_disk(disk); |
drivers/ide/ide-disk.c
drivers/scsi/sd.c
... | ... | @@ -89,7 +89,7 @@ |
89 | 89 | #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) |
90 | 90 | #define SD_MINORS 16 |
91 | 91 | #else |
92 | -#define SD_MINORS 1 | |
92 | +#define SD_MINORS 0 | |
93 | 93 | #endif |
94 | 94 | |
95 | 95 | static int sd_revalidate_disk(struct gendisk *); |
... | ... | @@ -1770,6 +1770,52 @@ |
1770 | 1770 | } |
1771 | 1771 | |
1772 | 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 | + | |
1818 | +/** | |
1773 | 1819 | * sd_probe - called during driver initialization and whenever a |
1774 | 1820 | * new scsi device is attached to the system. It is called once |
1775 | 1821 | * for each scsi device (not just disks) present. |
... | ... | @@ -1821,8 +1867,8 @@ |
1821 | 1867 | if (error) |
1822 | 1868 | goto out_put; |
1823 | 1869 | |
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) | |
1826 | 1872 | goto out_free_index; |
1827 | 1873 | |
1828 | 1874 | sdkp->device = sdp; |
1829 | 1875 | |
... | ... | @@ -1849,24 +1895,12 @@ |
1849 | 1895 | |
1850 | 1896 | get_device(&sdp->sdev_gendev); |
1851 | 1897 | |
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; | |
1868 | 1902 | } |
1869 | - | |
1903 | + gd->fops = &sd_fops; | |
1870 | 1904 | gd->private_data = &sdkp->driver; |
1871 | 1905 | gd->queue = sdkp->device->request_queue; |
1872 | 1906 |
fs/partitions/check.c
include/linux/genhd.h
... | ... | @@ -59,6 +59,7 @@ |
59 | 59 | }; |
60 | 60 | |
61 | 61 | #define DISK_MAX_PARTS 256 |
62 | +#define DISK_NAME_LEN 32 | |
62 | 63 | |
63 | 64 | #include <linux/major.h> |
64 | 65 | #include <linux/device.h> |
... | ... | @@ -140,7 +141,7 @@ |
140 | 141 | int minors; /* maximum number of minors, =1 for |
141 | 142 | * disks that can't be partitioned. */ |
142 | 143 | |
143 | - char disk_name[32]; /* name of major driver */ | |
144 | + char disk_name[DISK_NAME_LEN]; /* name of major driver */ | |
144 | 145 | |
145 | 146 | /* Array of pointers to partitions indexed by partno. |
146 | 147 | * Protected with matching bdev lock but stat and other |