diff options
author | Tejun Heo <tj@kernel.org> | 2008-08-25 06:56:17 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:08 -0400 |
commit | 3e1a7ff8a0a7b948f2684930166954f9e8e776fe (patch) | |
tree | 0a8642f5cdbc6ddfdd66dc7241c915e57b3cb7ff /drivers/scsi/sd.c | |
parent | 689d6fac40b41c7bf154f362deaf442548e4dc81 (diff) |
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>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6598024531dd..bcb04b2a7676 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -89,7 +89,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); | |||
89 | #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) | 89 | #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) |
90 | #define SD_MINORS 16 | 90 | #define SD_MINORS 16 |
91 | #else | 91 | #else |
92 | #define SD_MINORS 1 | 92 | #define SD_MINORS 0 |
93 | #endif | 93 | #endif |
94 | 94 | ||
95 | static int sd_revalidate_disk(struct gendisk *); | 95 | static int sd_revalidate_disk(struct gendisk *); |
@@ -1770,6 +1770,52 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
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 | * sd_probe - called during driver initialization and whenever a | 1819 | * sd_probe - called during driver initialization and whenever a |
1774 | * new scsi device is attached to the system. It is called once | 1820 | * new scsi device is attached to the system. It is called once |
1775 | * for each scsi device (not just disks) present. | 1821 | * for each scsi device (not just disks) present. |
@@ -1821,8 +1867,8 @@ static int sd_probe(struct device *dev) | |||
1821 | if (error) | 1867 | if (error) |
1822 | goto out_put; | 1868 | goto out_put; |
1823 | 1869 | ||
1824 | error = -EBUSY; | 1870 | error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); |
1825 | if (index >= SD_MAX_DISKS) | 1871 | if (error) |
1826 | goto out_free_index; | 1872 | goto out_free_index; |
1827 | 1873 | ||
1828 | sdkp->device = sdp; | 1874 | sdkp->device = sdp; |
@@ -1849,24 +1895,12 @@ static int sd_probe(struct device *dev) | |||
1849 | 1895 | ||
1850 | get_device(&sdp->sdev_gendev); | 1896 | get_device(&sdp->sdev_gendev); |
1851 | 1897 | ||
1852 | gd->major = sd_major((index & 0xf0) >> 4); | 1898 | if (index < SD_MAX_DISKS) { |
1853 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | 1899 | gd->major = sd_major((index & 0xf0) >> 4); |
1854 | gd->minors = SD_MINORS; | 1900 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); |
1855 | gd->fops = &sd_fops; | 1901 | gd->minors = SD_MINORS; |
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); | ||
1868 | } | 1902 | } |
1869 | 1903 | gd->fops = &sd_fops; | |
1870 | gd->private_data = &sdkp->driver; | 1904 | gd->private_data = &sdkp->driver; |
1871 | gd->queue = sdkp->device->request_queue; | 1905 | gd->queue = sdkp->device->request_queue; |
1872 | 1906 | ||