Commit f331c029 authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

block: don't depend on consecutive minor space

* Implement disk_devt() and part_devt() and use them to directly
  access devt instead of computing it from ->major and ->first_minor.

  Note that all references to ->major and ->first_minor outside of
  block layer is used to determine devt of the disk (the part0) and as
  ->major and ->first_minor will continue to represent devt for the
  disk, converting these users aren't strictly necessary.  However,
  convert them for consistency.

* Implement disk_max_parts() to avoid directly deferencing
  genhd->minors.

* Update bdget_disk() such that it doesn't assume consecutive minor
  space.

* Move devt computation from register_disk() to add_disk() and make it
  the only one (all other usages use the initially determined value).

These changes clean up the code and will help disk->part dereference
fix and extended block device numbers.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent cf771cb5
...@@ -186,13 +186,14 @@ void add_disk(struct gendisk *disk) ...@@ -186,13 +186,14 @@ void add_disk(struct gendisk *disk)
int retval; int retval;
disk->flags |= GENHD_FL_UP; disk->flags |= GENHD_FL_UP;
blk_register_region(MKDEV(disk->major, disk->first_minor), disk->dev.devt = MKDEV(disk->major, disk->first_minor);
disk->minors, NULL, exact_match, exact_lock, disk); blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
register_disk(disk); register_disk(disk);
blk_register_queue(disk); blk_register_queue(disk);
bdi = &disk->queue->backing_dev_info; bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); bdi_register_dev(bdi, disk_devt(disk));
retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
WARN_ON(retval); WARN_ON(retval);
} }
...@@ -205,8 +206,7 @@ void unlink_gendisk(struct gendisk *disk) ...@@ -205,8 +206,7 @@ void unlink_gendisk(struct gendisk *disk)
sysfs_remove_link(&disk->dev.kobj, "bdi"); sysfs_remove_link(&disk->dev.kobj, "bdi");
bdi_unregister(&disk->queue->backing_dev_info); bdi_unregister(&disk->queue->backing_dev_info);
blk_unregister_queue(disk); blk_unregister_queue(disk);
blk_unregister_region(MKDEV(disk->major, disk->first_minor), blk_unregister_region(disk_devt(disk), disk->minors);
disk->minors);
} }
/** /**
...@@ -225,6 +225,38 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) ...@@ -225,6 +225,38 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
return kobj ? dev_to_disk(dev) : NULL; return kobj ? dev_to_disk(dev) : NULL;
} }
/**
* bdget_disk - do bdget() by gendisk and partition number
* @disk: gendisk of interest
* @partno: partition number
*
* Find partition @partno from @disk, do bdget() on it.
*
* CONTEXT:
* Don't care.
*
* RETURNS:
* Resulting block_device on success, NULL on failure.
*/
extern struct block_device *bdget_disk(struct gendisk *disk, int partno)
{
dev_t devt = MKDEV(0, 0);
if (partno == 0)
devt = disk_devt(disk);
else {
struct hd_struct *part = disk->part[partno - 1];
if (part && part->nr_sects)
devt = part_devt(part);
}
if (likely(devt != MKDEV(0, 0)))
return bdget(devt);
return NULL;
}
EXPORT_SYMBOL(bdget_disk);
/* /*
* print a full list of all partitions - intended for places where the root * print a full list of all partitions - intended for places where the root
* filesystem can't be mounted and thus to give the victim some idea of what * filesystem can't be mounted and thus to give the victim some idea of what
...@@ -255,7 +287,7 @@ void __init printk_all_partitions(void) ...@@ -255,7 +287,7 @@ void __init printk_all_partitions(void)
* option takes. * option takes.
*/ */
printk("%02x%02x %10llu %s", printk("%02x%02x %10llu %s",
disk->major, disk->first_minor, MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)),
(unsigned long long)get_capacity(disk) >> 1, (unsigned long long)get_capacity(disk) >> 1,
disk_name(disk, 0, buf)); disk_name(disk, 0, buf));
if (disk->driverfs_dev != NULL && if (disk->driverfs_dev != NULL &&
...@@ -266,15 +298,15 @@ void __init printk_all_partitions(void) ...@@ -266,15 +298,15 @@ void __init printk_all_partitions(void)
printk(" (driver?)\n"); printk(" (driver?)\n");
/* now show the partitions */ /* now show the partitions */
for (n = 0; n < disk->minors - 1; ++n) { for (n = 0; n < disk_max_parts(disk); ++n) {
if (disk->part[n] == NULL) struct hd_struct *part = disk->part[n];
continue;
if (disk->part[n]->nr_sects == 0) if (!part || !part->nr_sects)
continue; continue;
printk(" %02x%02x %10llu %s\n", printk(" %02x%02x %10llu %s\n",
disk->major, n + 1 + disk->first_minor, MAJOR(part_devt(part)), MINOR(part_devt(part)),
(unsigned long long)disk->part[n]->nr_sects >> 1, (unsigned long long)part->nr_sects >> 1,
disk_name(disk, n + 1, buf)); disk_name(disk, part->partno, buf));
} }
} }
class_dev_iter_exit(&iter); class_dev_iter_exit(&iter);
...@@ -343,26 +375,27 @@ static int show_partition(struct seq_file *seqf, void *v) ...@@ -343,26 +375,27 @@ static int show_partition(struct seq_file *seqf, void *v)
char buf[BDEVNAME_SIZE]; char buf[BDEVNAME_SIZE];
/* Don't show non-partitionable removeable devices or empty devices */ /* Don't show non-partitionable removeable devices or empty devices */
if (!get_capacity(sgp) || if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) (sgp->flags & GENHD_FL_REMOVABLE)))
return 0; return 0;
if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
return 0; return 0;
/* show the full disk and all non-0 size partitions of it */ /* show the full disk and all non-0 size partitions of it */
seq_printf(seqf, "%4d %4d %10llu %s\n", seq_printf(seqf, "%4d %4d %10llu %s\n",
sgp->major, sgp->first_minor, MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)),
(unsigned long long)get_capacity(sgp) >> 1, (unsigned long long)get_capacity(sgp) >> 1,
disk_name(sgp, 0, buf)); disk_name(sgp, 0, buf));
for (n = 0; n < sgp->minors - 1; n++) { for (n = 0; n < disk_max_parts(sgp); n++) {
if (!sgp->part[n]) struct hd_struct *part = sgp->part[n];
if (!part)
continue; continue;
if (sgp->part[n]->nr_sects == 0) if (part->nr_sects == 0)
continue; continue;
seq_printf(seqf, "%4d %4d %10llu %s\n", seq_printf(seqf, "%4d %4d %10llu %s\n",
sgp->major, n + 1 + sgp->first_minor, MAJOR(part_devt(part)), MINOR(part_devt(part)),
(unsigned long long)sgp->part[n]->nr_sects >> 1 , (unsigned long long)part->nr_sects >> 1,
disk_name(sgp, n + 1, buf)); disk_name(sgp, part->partno, buf));
} }
return 0; return 0;
...@@ -578,7 +611,8 @@ static int diskstats_show(struct seq_file *seqf, void *v) ...@@ -578,7 +611,8 @@ static int diskstats_show(struct seq_file *seqf, void *v)
disk_round_stats(gp); disk_round_stats(gp);
preempt_enable(); preempt_enable();
seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
gp->major, gp->first_minor, disk_name(gp, 0, buf), MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)),
disk_name(gp, 0, buf),
disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
(unsigned long long)disk_stat_read(gp, sectors[0]), (unsigned long long)disk_stat_read(gp, sectors[0]),
jiffies_to_msecs(disk_stat_read(gp, ticks[0])), jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
...@@ -590,7 +624,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) ...@@ -590,7 +624,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
/* now show all non-0 size partitions of it */ /* now show all non-0 size partitions of it */
for (n = 0; n < gp->minors - 1; n++) { for (n = 0; n < disk_max_parts(gp); n++) {
struct hd_struct *hd = gp->part[n]; struct hd_struct *hd = gp->part[n];
if (!hd || !hd->nr_sects) if (!hd || !hd->nr_sects)
...@@ -601,8 +635,8 @@ static int diskstats_show(struct seq_file *seqf, void *v) ...@@ -601,8 +635,8 @@ static int diskstats_show(struct seq_file *seqf, void *v)
preempt_enable(); preempt_enable();
seq_printf(seqf, "%4d %4d %s %lu %lu %llu " seq_printf(seqf, "%4d %4d %s %lu %lu %llu "
"%u %lu %lu %llu %u %u %u %u\n", "%u %lu %lu %llu %u %u %u %u\n",
gp->major, n + gp->first_minor + 1, MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
disk_name(gp, n + 1, buf), disk_name(gp, hd->partno, buf),
part_stat_read(hd, ios[0]), part_stat_read(hd, ios[0]),
part_stat_read(hd, merges[0]), part_stat_read(hd, merges[0]),
(unsigned long long)part_stat_read(hd, sectors[0]), (unsigned long long)part_stat_read(hd, sectors[0]),
...@@ -661,11 +695,22 @@ dev_t blk_lookup_devt(const char *name, int partno) ...@@ -661,11 +695,22 @@ dev_t blk_lookup_devt(const char *name, int partno)
while ((dev = class_dev_iter_next(&iter))) { while ((dev = class_dev_iter_next(&iter))) {
struct gendisk *disk = dev_to_disk(dev); struct gendisk *disk = dev_to_disk(dev);
if (!strcmp(dev->bus_id, name) && partno < disk->minors) { if (strcmp(dev->bus_id, name))
devt = MKDEV(MAJOR(dev->devt), continue;
MINOR(dev->devt) + partno); if (partno < 0 || partno > disk_max_parts(disk))
break; continue;
if (partno == 0)
devt = disk_devt(disk);
else {
struct hd_struct *part = disk->part[partno - 1];
if (!part || !part->nr_sects)
continue;
devt = part_devt(part);
} }
break;
} }
class_dev_iter_exit(&iter); class_dev_iter_exit(&iter);
return devt; return devt;
...@@ -755,7 +800,7 @@ void set_disk_ro(struct gendisk *disk, int flag) ...@@ -755,7 +800,7 @@ void set_disk_ro(struct gendisk *disk, int flag)
{ {
int i; int i;
disk->policy = flag; disk->policy = flag;
for (i = 0; i < disk->minors - 1; i++) for (i = 0; i < disk_max_parts(disk); i++)
if (disk->part[i]) disk->part[i]->policy = flag; if (disk->part[i]) disk->part[i]->policy = flag;
} }
......
...@@ -29,7 +29,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user ...@@ -29,7 +29,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
if (bdev != bdev->bd_contains) if (bdev != bdev->bd_contains)
return -EINVAL; return -EINVAL;
partno = p.pno; partno = p.pno;
if (partno <= 0 || partno >= disk->minors) if (partno <= 0 || partno > disk_max_parts(disk))
return -EINVAL; return -EINVAL;
switch (a.op) { switch (a.op) {
case BLKPG_ADD_PARTITION: case BLKPG_ADD_PARTITION:
...@@ -47,7 +47,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user ...@@ -47,7 +47,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
mutex_lock(&bdev->bd_mutex); mutex_lock(&bdev->bd_mutex);
/* overlap? */ /* overlap? */
for (i = 0; i < disk->minors - 1; i++) { for (i = 0; i < disk_max_parts(disk); i++) {
struct hd_struct *s = disk->part[i]; struct hd_struct *s = disk->part[i];
if (!s) if (!s)
...@@ -96,7 +96,7 @@ static int blkdev_reread_part(struct block_device *bdev) ...@@ -96,7 +96,7 @@ static int blkdev_reread_part(struct block_device *bdev)
struct gendisk *disk = bdev->bd_disk; struct gendisk *disk = bdev->bd_disk;
int res; int res;
if (disk->minors == 1 || bdev != bdev->bd_contains) if (!disk_max_parts(disk) || bdev != bdev->bd_contains)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
......
...@@ -2911,7 +2911,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) ...@@ -2911,7 +2911,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
if (!disk->queue) if (!disk->queue)
goto out_mem2; goto out_mem2;
pd->pkt_dev = MKDEV(disk->major, disk->first_minor); pd->pkt_dev = MKDEV(pktdev_major, idx);
ret = pkt_new_dev(pd, dev); ret = pkt_new_dev(pd, dev);
if (ret) if (ret)
goto out_new_dev; goto out_new_dev;
......
...@@ -541,7 +541,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev) ...@@ -541,7 +541,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev)
struct ps3disk_private *priv = dev->sbd.core.driver_data; struct ps3disk_private *priv = dev->sbd.core.driver_data;
mutex_lock(&ps3disk_mask_mutex); mutex_lock(&ps3disk_mask_mutex);
__clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS, __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
&ps3disk_mask); &ps3disk_mask);
mutex_unlock(&ps3disk_mask_mutex); mutex_unlock(&ps3disk_mask_mutex);
del_gendisk(priv->gendisk); del_gendisk(priv->gendisk);
......
...@@ -661,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk) ...@@ -661,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk)
if (!disk || !disk->random) if (!disk || !disk->random)
return; return;
/* first major is 1, so we get >= 0x200 here */ /* first major is 1, so we get >= 0x200 here */
DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor); DEBUG_ENT("disk event %d:%d\n",
MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
add_timer_randomness(disk->random, add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
0x100 + MKDEV(disk->major, disk->first_minor));
} }
#endif #endif
......
...@@ -426,7 +426,7 @@ static int list_devices(struct dm_ioctl *param, size_t param_size) ...@@ -426,7 +426,7 @@ static int list_devices(struct dm_ioctl *param, size_t param_size)
old_nl->next = (uint32_t) ((void *) nl - old_nl->next = (uint32_t) ((void *) nl -
(void *) old_nl); (void *) old_nl);
disk = dm_disk(hc->md); disk = dm_disk(hc->md);
nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); nl->dev = huge_encode_dev(disk_devt(disk));
nl->next = 0; nl->next = 0;
strcpy(nl->name, hc->name); strcpy(nl->name, hc->name);
...@@ -539,7 +539,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) ...@@ -539,7 +539,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
if (dm_suspended(md)) if (dm_suspended(md))
param->flags |= DM_SUSPEND_FLAG; param->flags |= DM_SUSPEND_FLAG;
param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); param->dev = huge_encode_dev(disk_devt(disk));
/* /*
* Yes, this will be out of date by the time it gets back * Yes, this will be out of date by the time it gets back
......
...@@ -284,8 +284,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, ...@@ -284,8 +284,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio,
memset(major_minor, 0, sizeof(major_minor)); memset(major_minor, 0, sizeof(major_minor));
sprintf(major_minor, "%d:%d", sprintf(major_minor, "%d:%d",
bio->bi_bdev->bd_disk->major, MAJOR(disk_devt(bio->bi_bdev->bd_disk)),
bio->bi_bdev->bd_disk->first_minor); MINOR(disk_devt(bio->bi_bdev->bd_disk)));
/* /*
* Test to see which stripe drive triggered the event * Test to see which stripe drive triggered the event
......
...@@ -1146,7 +1146,7 @@ static void unlock_fs(struct mapped_device *md); ...@@ -1146,7 +1146,7 @@ static void unlock_fs(struct mapped_device *md);
static void free_dev(struct mapped_device *md) static void free_dev(struct mapped_device *md)
{ {
int minor = md->disk->first_minor; int minor = MINOR(disk_devt(md->disk));
if (md->suspended_bdev) { if (md->suspended_bdev) {
unlock_fs(md); unlock_fs(md);
...@@ -1267,7 +1267,7 @@ static struct mapped_device *dm_find_md(dev_t dev) ...@@ -1267,7 +1267,7 @@ static struct mapped_device *dm_find_md(dev_t dev)
md = idr_find(&_minor_idr, minor); md = idr_find(&_minor_idr, minor);
if (md && (md == MINOR_ALLOCED || if (md && (md == MINOR_ALLOCED ||
(dm_disk(md)->first_minor != minor) || (MINOR(disk_devt(dm_disk(md))) != minor) ||
test_bit(DMF_FREEING, &md->flags))) { test_bit(DMF_FREEING, &md->flags))) {
md = NULL; md = NULL;
goto out; goto out;
...@@ -1318,7 +1318,8 @@ void dm_put(struct mapped_device *md) ...@@ -1318,7 +1318,8 @@ void dm_put(struct mapped_device *md)
if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { if (atomic_dec_and_lock(&md->holders, &_minor_lock)) {
map = dm_get_table(md); map = dm_get_table(md);
idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor); idr_replace(&_minor_idr, MINOR_ALLOCED,
MINOR(disk_devt(dm_disk(md))));
set_bit(DMF_FREEING, &md->flags); set_bit(DMF_FREEING, &md->flags);
spin_unlock(&_minor_lock); spin_unlock(&_minor_lock);
if (!dm_suspended(md)) { if (!dm_suspended(md)) {
......
...@@ -197,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) ...@@ -197,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp)
static int mspro_block_disk_release(struct gendisk *disk) static int mspro_block_disk_release(struct gendisk *disk)
{ {
struct mspro_block_data *msb = disk->private_data; struct mspro_block_data *msb = disk->private_data;
int disk_id = disk->first_minor >> MSPRO_BLOCK_PART_SHIFT; int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT;
mutex_lock(&mspro_block_disk_lock); mutex_lock(&mspro_block_disk_lock);
......
...@@ -83,7 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md) ...@@ -83,7 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_lock(&open_lock); mutex_lock(&open_lock);
md->usage--; md->usage--;
if (md->usage == 0) { if (md->usage == 0) {
int devidx = md->disk->first_minor >> MMC_SHIFT; int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
__clear_bit(devidx, dev_use); __clear_bit(devidx, dev_use);
put_disk(md->disk); put_disk(md->disk);
......
...@@ -76,7 +76,8 @@ dasd_devices_show(struct seq_file *m, void *v) ...@@ -76,7 +76,8 @@ dasd_devices_show(struct seq_file *m, void *v)
/* Print kdev. */ /* Print kdev. */
if (block->gdp) if (block->gdp)
seq_printf(m, " at (%3d:%6d)", seq_printf(m, " at (%3d:%6d)",
block->gdp->major, block->gdp->first_minor); MAJOR(disk_devt(block->gdp)),
MINOR(disk_devt(block->gdp)));
else else
seq_printf(m, " at (???:??????)"); seq_printf(m, " at (???:??????)");
/* Print device name. */ /* Print device name. */
......
...@@ -114,7 +114,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) ...@@ -114,7 +114,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
found = 0; found = 0;
// test if minor available // test if minor available
list_for_each_entry(entry, &dcssblk_devices, lh) list_for_each_entry(entry, &dcssblk_devices, lh)
if (minor == entry->gd->first_minor) if (minor == MINOR(disk_devt(entry->gd)))
found++; found++;
if (!found) break; // got unused minor if (!found) break; // got unused minor
} }
...@@ -397,7 +397,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char ...@@ -397,7 +397,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
goto unload_seg; goto unload_seg;
} }
sprintf(dev_info->gd->disk_name, "dcssblk%d", sprintf(dev_info->gd->disk_name, "dcssblk%d",
dev_info->gd->first_minor); MINOR(disk_devt(dev_info->gd)));
list_add_tail(&dev_info->lh, &dcssblk_devices); list_add_tail(&dev_info->lh, &dcssblk_devices);
if (!try_module_get(THIS_MODULE)) { if (!try_module_get(THIS_MODULE)) {
......
...@@ -878,7 +878,7 @@ static void sr_kref_release(struct kref *kref) ...@@ -878,7 +878,7 @@ static void sr_kref_release(struct kref *kref)
struct gendisk *disk = cd->disk; struct gendisk *disk = cd->disk;
spin_lock(&sr_index_lock); spin_lock(&sr_index_lock);
clear_bit(disk->first_minor, sr_index_bits); clear_bit(MINOR(disk_devt(disk)), sr_index_bits);
spin_unlock(&sr_index_lock); spin_unlock(&sr_index_lock);
unregister_cdrom(&cd->cdi); unregister_cdrom(&cd->cdi);
......
...@@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev) ...@@ -892,7 +892,7 @@ int check_disk_change(struct block_device *bdev)
if (bdops->revalidate_disk) if (bdops->revalidate_disk)
bdops->revalidate_disk(bdev->bd_disk); bdops->revalidate_disk(bdev->bd_disk);
if (bdev->bd_disk->minors > 1) if (disk_max_parts(bdev->bd_disk))
bdev->bd_invalidated = 1; bdev->bd_invalidated = 1;
return 1; return 1;
} }
......
...@@ -134,7 +134,11 @@ char *disk_name(struct gendisk *hd, int partno, char *buf) ...@@ -134,7 +134,11 @@ char *disk_name(struct gendisk *hd, int partno, char *buf)
const char *bdevname(struct block_device *bdev, char *buf) const char *bdevname(struct block_device *bdev, char *buf)
{ {
int partno = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor; int partno = 0;
if (bdev->bd_part)
partno = bdev->bd_part->partno;
return disk_name(bdev->bd_disk, partno, buf); return disk_name(bdev->bd_disk, partno, buf);
} }
...@@ -169,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) ...@@ -169,7 +173,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
if (isdigit(state->name[strlen(state->name)-1])) if (isdigit(state->name[strlen(state->name)-1]))
sprintf(state->name, "p"); sprintf(state->name, "p");
state->limit = hd->minors; state->limit = disk_max_parts(hd) + 1;
i = res = err = 0; i = res = err = 0;
while (!res && check_part[i]) { while (!res && check_part[i]) {
memset(&state->parts, 0, sizeof(state->parts)); memset(&state->parts, 0, sizeof(state->parts));
...@@ -416,7 +420,6 @@ void register_disk(struct gendisk *disk) ...@@ -416,7 +420,6 @@ void register_disk(struct gendisk *disk)
int err; int err;
disk->dev.parent = disk->driverfs_dev; disk->dev.parent = disk->driverfs_dev;
disk->dev.devt = MKDEV(disk->major, disk->first_minor);
strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE);
/* ewww... some of these buggers have / in the name... */ /* ewww... some of these buggers have / in the name... */
...@@ -440,7 +443,7 @@ void register_disk(struct gendisk *disk) ...@@ -440,7 +443,7 @@ void register_disk(struct gendisk *disk)
disk_sysfs_add_subdirs(disk); disk_sysfs_add_subdirs(disk);
/* No minors to use for partitions */ /* No minors to use for partitions */
if (disk->minors == 1) if (!disk_max_parts(disk))
goto exit; goto exit;
/* No such device (e.g., media were just removed) */ /* No such device (e.g., media were just removed) */
...@@ -463,8 +466,8 @@ void register_disk(struct gendisk *disk) ...@@ -463,8 +466,8 @@ void register_disk(struct gendisk *disk)
kobject_uevent(&disk->dev.kobj, KOBJ_ADD); kobject_uevent(&disk->dev.kobj, KOBJ_ADD);
/* announce possible partitions */ /* announce possible partitions */
for (i = 1; i < disk->minors; i++) { for (i = 0; i < disk_max_parts(disk); i++) {
p = disk->part[i-1]; p = disk->part[i];
if (!p || !p->nr_sects) if (!p || !p->nr_sects)
continue; continue;
kobject_uevent(&p->dev.kobj, KOBJ_ADD); kobject_uevent(&p->dev.kobj, KOBJ_ADD);
...@@ -482,7 +485,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) ...@@ -482,7 +485,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
if (res) if (res)
return res; return res;
bdev->bd_invalidated = 0; bdev->bd_invalidated = 0;
for (p = 1; p < disk->minors; p++) for (p = 1; p <= disk_max_parts(disk); p++)
delete_partition(disk, p); delete_partition(disk, p);
if (disk->fops->revalidate_disk) if (disk->fops->revalidate_disk)
disk->fops->revalidate_disk(disk); disk->fops->revalidate_disk(disk);
...@@ -545,7 +548,7 @@ void del_gendisk(struct gendisk *disk) ...@@ -545,7 +548,7 @@ void del_gendisk(struct gendisk *disk)
int p; int p;
/* invalidate stuff */ /* invalidate stuff */
for (p = disk->minors - 1; p > 0; p--) { for (p = disk_max_parts(disk); p > 0; p--) {
invalidate_partition(disk, p); invalidate_partition(disk, p);
delete_partition(disk, p); delete_partition(disk, p);
} }
......
...@@ -111,10 +111,14 @@ struct hd_struct { ...@@ -111,10 +111,14 @@ struct hd_struct {
#define GENHD_FL_FAIL 64 #define GENHD_FL_FAIL 64
struct gendisk { struct gendisk {
/* major, first_minor and minors are input parameters only,
* don't use directly. Use disk_devt() and disk_max_parts().
*/
int major; /* major number of driver */ int major; /* major number of driver */
int first_minor; int first_minor;
int minors; /* maximum number of minors, =1 for int minors; /* maximum number of minors, =1 for
* disks that can't be partitioned. */ * disks that can't be partitioned. */
char disk_name[32]; /* name of major driver */ char disk_name[32]; /* name of major driver */
struct hd_struct **part; /* [indexed by minor - 1] */ struct hd_struct **part; /* [indexed by minor - 1] */
struct block_device_operations *fops; struct block_device_operations *fops;
...@@ -152,6 +156,21 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) ...@@ -152,6 +156,21 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part)
return NULL; return NULL;
} }
static inline int disk_max_parts(struct gendisk *disk)
{
return disk->minors - 1;
}
static inline dev_t disk_devt(struct gendisk *disk)
{
return disk->dev.devt;
}
static inline dev_t part_devt(struct hd_struct *part)
{
return part->dev.devt;
}
/* /*
* Macros to operate on percpu disk statistics: * Macros to operate on percpu disk statistics:
* *
...@@ -163,7 +182,7 @@ static inline struct hd_struct *disk_map_sector(struct gendisk *gendiskp, ...@@ -163,7 +182,7 @@ static inline struct hd_struct *disk_map_sector(struct gendisk *gendiskp,
{ {
struct hd_struct *part; struct hd_struct *part;
int i; int i;
for (i = 0; i < gendiskp->minors - 1; i++) { for (i = 0; i < disk_max_parts(gendiskp); i++) {
part = gendiskp->part[i]; part = gendiskp->part[i];
if (part && part->start_sect <= sector if (part && part->start_sect <= sector
&& sector < part->start_sect + part->nr_sects) && sector < part->start_sect + part->nr_sects)
...@@ -366,6 +385,7 @@ extern void add_disk(struct gendisk *disk); ...@@ -366,6 +385,7 @@ extern void add_disk(struct gendisk *disk);
extern void del_gendisk(struct gendisk *gp); extern void del_gendisk(struct gendisk *gp);
extern void unlink_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp);
extern struct gendisk *get_gendisk(dev_t dev, int *partno); extern struct gendisk *get_gendisk(dev_t dev, int *partno);
extern struct block_device *bdget_disk(struct gendisk *disk, int partno);
extern void set_device_ro(struct block_device *bdev, int flag); extern void set_device_ro(struct block_device *bdev, int flag);
extern void set_disk_ro(struct gendisk *disk, int flag); extern void set_disk_ro(struct gendisk *disk, int flag);
...@@ -553,11 +573,6 @@ extern void blk_register_region(dev_t devt, unsigned long range, ...@@ -553,11 +573,6 @@ extern void blk_register_region(dev_t devt, unsigned long range,
void *data); void *data);
extern void blk_unregister_region(dev_t devt, unsigned long range); extern void blk_unregister_region(dev_t devt, unsigned long range);
static inline struct block_device *bdget_disk(struct gendisk *disk, int partno)
{
return bdget(MKDEV(disk->major, disk->first_minor) + partno);
}
#else /* CONFIG_BLOCK */ #else /* CONFIG_BLOCK */
static inline void printk_all_partitions(void) { } static inline void printk_all_partitions(void) { }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment