aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-08-25 06:56:17 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:08 -0400
commit3e1a7ff8a0a7b948f2684930166954f9e8e776fe (patch)
tree0a8642f5cdbc6ddfdd66dc7241c915e57b3cb7ff
parent689d6fac40b41c7bf154f362deaf442548e4dc81 (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>
-rw-r--r--block/genhd.c25
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/scsi/sd.c74
-rw-r--r--fs/partitions/check.c1
-rw-r--r--include/linux/genhd.h3
5 files changed, 82 insertions, 23 deletions
diff --git a/block/genhd.c b/block/genhd.c
index eedab5b4685b..d9de3e482d1e 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -478,14 +478,37 @@ static int exact_lock(dev_t devt, void *data)
478 * 478 *
479 * This function registers the partitioning information in @disk 479 * This function registers the partitioning information in @disk
480 * with the kernel. 480 * with the kernel.
481 *
482 * FIXME: error handling
481 */ 483 */
482void add_disk(struct gendisk *disk) 484void add_disk(struct gendisk *disk)
483{ 485{
484 struct backing_dev_info *bdi; 486 struct backing_dev_info *bdi;
487 dev_t devt;
485 int retval; 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 disk->flags |= GENHD_FL_UP; 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 blk_register_region(disk_devt(disk), disk->minors, NULL, 512 blk_register_region(disk_devt(disk), disk->minors, NULL,
490 exact_match, exact_lock, disk); 513 exact_match, exact_lock, disk);
491 register_disk(disk); 514 register_disk(disk);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 29c8ae752683..33ea8c048717 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -44,7 +44,7 @@
44#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) 44#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
45#define IDE_DISK_MINORS (1 << PARTN_BITS) 45#define IDE_DISK_MINORS (1 << PARTN_BITS)
46#else 46#else
47#define IDE_DISK_MINORS 1 47#define IDE_DISK_MINORS 0
48#endif 48#endif
49 49
50struct ide_disk_obj { 50struct ide_disk_obj {
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
95static int sd_revalidate_disk(struct gendisk *); 95static 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 */
1794static 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
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 772b2ed8d239..0e411603fdf5 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -593,6 +593,7 @@ void del_gendisk(struct gendisk *disk)
593 disk_part_iter_exit(&piter); 593 disk_part_iter_exit(&piter);
594 594
595 invalidate_partition(disk, 0); 595 invalidate_partition(disk, 0);
596 blk_free_devt(disk_to_dev(disk)->devt);
596 set_capacity(disk, 0); 597 set_capacity(disk, 0);
597 disk->flags &= ~GENHD_FL_UP; 598 disk->flags &= ~GENHD_FL_UP;
598 unlink_gendisk(disk); 599 unlink_gendisk(disk);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 04524c213de1..206cdf96c3a7 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -59,6 +59,7 @@ enum {
59}; 59};
60 60
61#define DISK_MAX_PARTS 256 61#define DISK_MAX_PARTS 256
62#define DISK_NAME_LEN 32
62 63
63#include <linux/major.h> 64#include <linux/major.h>
64#include <linux/device.h> 65#include <linux/device.h>
@@ -140,7 +141,7 @@ struct gendisk {
140 int minors; /* maximum number of minors, =1 for 141 int minors; /* maximum number of minors, =1 for
141 * disks that can't be partitioned. */ 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 /* Array of pointers to partitions indexed by partno. 146 /* Array of pointers to partitions indexed by partno.
146 * Protected with matching bdev lock but stat and other 147 * Protected with matching bdev lock but stat and other