aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-09-03 03:01:48 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:05 -0400
commitf331c0296f2a9fee0d396a70598b954062603015 (patch)
treef74c467d58940131d97d90c4ea549843185e6ef0 /block
parentcf771cb5a7b716f3f9e532fd42a1e3a0a75adec5 (diff)
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: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c107
-rw-r--r--block/ioctl.c6
2 files changed, 79 insertions, 34 deletions
diff --git a/block/genhd.c b/block/genhd.c
index dc9ad4c171e2..fa32d09fda24 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -186,13 +186,14 @@ void add_disk(struct gendisk *disk)
186 int retval; 186 int retval;
187 187
188 disk->flags |= GENHD_FL_UP; 188 disk->flags |= GENHD_FL_UP;
189 blk_register_region(MKDEV(disk->major, disk->first_minor), 189 disk->dev.devt = MKDEV(disk->major, disk->first_minor);
190 disk->minors, NULL, exact_match, exact_lock, disk); 190 blk_register_region(disk_devt(disk), disk->minors, NULL,
191 exact_match, exact_lock, disk);
191 register_disk(disk); 192 register_disk(disk);
192 blk_register_queue(disk); 193 blk_register_queue(disk);
193 194
194 bdi = &disk->queue->backing_dev_info; 195 bdi = &disk->queue->backing_dev_info;
195 bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); 196 bdi_register_dev(bdi, disk_devt(disk));
196 retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); 197 retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
197 WARN_ON(retval); 198 WARN_ON(retval);
198} 199}
@@ -205,8 +206,7 @@ void unlink_gendisk(struct gendisk *disk)
205 sysfs_remove_link(&disk->dev.kobj, "bdi"); 206 sysfs_remove_link(&disk->dev.kobj, "bdi");
206 bdi_unregister(&disk->queue->backing_dev_info); 207 bdi_unregister(&disk->queue->backing_dev_info);
207 blk_unregister_queue(disk); 208 blk_unregister_queue(disk);
208 blk_unregister_region(MKDEV(disk->major, disk->first_minor), 209 blk_unregister_region(disk_devt(disk), disk->minors);
209 disk->minors);
210} 210}
211 211
212/** 212/**
@@ -225,6 +225,38 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
225 return kobj ? dev_to_disk(dev) : NULL; 225 return kobj ? dev_to_disk(dev) : NULL;
226} 226}
227 227
228/**
229 * bdget_disk - do bdget() by gendisk and partition number
230 * @disk: gendisk of interest
231 * @partno: partition number
232 *
233 * Find partition @partno from @disk, do bdget() on it.
234 *
235 * CONTEXT:
236 * Don't care.
237 *
238 * RETURNS:
239 * Resulting block_device on success, NULL on failure.
240 */
241extern struct block_device *bdget_disk(struct gendisk *disk, int partno)
242{
243 dev_t devt = MKDEV(0, 0);
244
245 if (partno == 0)
246 devt = disk_devt(disk);
247 else {
248 struct hd_struct *part = disk->part[partno - 1];
249
250 if (part && part->nr_sects)
251 devt = part_devt(part);
252 }
253
254 if (likely(devt != MKDEV(0, 0)))
255 return bdget(devt);
256 return NULL;
257}
258EXPORT_SYMBOL(bdget_disk);
259
228/* 260/*
229 * print a full list of all partitions - intended for places where the root 261 * print a full list of all partitions - intended for places where the root
230 * filesystem can't be mounted and thus to give the victim some idea of what 262 * 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 * option takes. 287 * option takes.
256 */ 288 */
257 printk("%02x%02x %10llu %s", 289 printk("%02x%02x %10llu %s",
258 disk->major, disk->first_minor, 290 MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)),
259 (unsigned long long)get_capacity(disk) >> 1, 291 (unsigned long long)get_capacity(disk) >> 1,
260 disk_name(disk, 0, buf)); 292 disk_name(disk, 0, buf));
261 if (disk->driverfs_dev != NULL && 293 if (disk->driverfs_dev != NULL &&
@@ -266,15 +298,15 @@ void __init printk_all_partitions(void)
266 printk(" (driver?)\n"); 298 printk(" (driver?)\n");
267 299
268 /* now show the partitions */ 300 /* now show the partitions */
269 for (n = 0; n < disk->minors - 1; ++n) { 301 for (n = 0; n < disk_max_parts(disk); ++n) {
270 if (disk->part[n] == NULL) 302 struct hd_struct *part = disk->part[n];
271 continue; 303
272 if (disk->part[n]->nr_sects == 0) 304 if (!part || !part->nr_sects)
273 continue; 305 continue;
274 printk(" %02x%02x %10llu %s\n", 306 printk(" %02x%02x %10llu %s\n",
275 disk->major, n + 1 + disk->first_minor, 307 MAJOR(part_devt(part)), MINOR(part_devt(part)),
276 (unsigned long long)disk->part[n]->nr_sects >> 1, 308 (unsigned long long)part->nr_sects >> 1,
277 disk_name(disk, n + 1, buf)); 309 disk_name(disk, part->partno, buf));
278 } 310 }
279 } 311 }
280 class_dev_iter_exit(&iter); 312 class_dev_iter_exit(&iter);
@@ -343,26 +375,27 @@ static int show_partition(struct seq_file *seqf, void *v)
343 char buf[BDEVNAME_SIZE]; 375 char buf[BDEVNAME_SIZE];
344 376
345 /* Don't show non-partitionable removeable devices or empty devices */ 377 /* Don't show non-partitionable removeable devices or empty devices */
346 if (!get_capacity(sgp) || 378 if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
347 (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) 379 (sgp->flags & GENHD_FL_REMOVABLE)))
348 return 0; 380 return 0;
349 if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) 381 if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
350 return 0; 382 return 0;
351 383
352 /* show the full disk and all non-0 size partitions of it */ 384 /* show the full disk and all non-0 size partitions of it */
353 seq_printf(seqf, "%4d %4d %10llu %s\n", 385 seq_printf(seqf, "%4d %4d %10llu %s\n",
354 sgp->major, sgp->first_minor, 386 MAJOR(disk_devt(sgp)), MINOR(disk_devt(sgp)),
355 (unsigned long long)get_capacity(sgp) >> 1, 387 (unsigned long long)get_capacity(sgp) >> 1,
356 disk_name(sgp, 0, buf)); 388 disk_name(sgp, 0, buf));
357 for (n = 0; n < sgp->minors - 1; n++) { 389 for (n = 0; n < disk_max_parts(sgp); n++) {
358 if (!sgp->part[n]) 390 struct hd_struct *part = sgp->part[n];
391 if (!part)
359 continue; 392 continue;
360 if (sgp->part[n]->nr_sects == 0) 393 if (part->nr_sects == 0)
361 continue; 394 continue;
362 seq_printf(seqf, "%4d %4d %10llu %s\n", 395 seq_printf(seqf, "%4d %4d %10llu %s\n",
363 sgp->major, n + 1 + sgp->first_minor, 396 MAJOR(part_devt(part)), MINOR(part_devt(part)),
364 (unsigned long long)sgp->part[n]->nr_sects >> 1 , 397 (unsigned long long)part->nr_sects >> 1,
365 disk_name(sgp, n + 1, buf)); 398 disk_name(sgp, part->partno, buf));
366 } 399 }
367 400
368 return 0; 401 return 0;
@@ -578,7 +611,8 @@ static int diskstats_show(struct seq_file *seqf, void *v)
578 disk_round_stats(gp); 611 disk_round_stats(gp);
579 preempt_enable(); 612 preempt_enable();
580 seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", 613 seq_printf(seqf, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
581 gp->major, gp->first_minor, disk_name(gp, 0, buf), 614 MAJOR(disk_devt(gp)), MINOR(disk_devt(gp)),
615 disk_name(gp, 0, buf),
582 disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), 616 disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
583 (unsigned long long)disk_stat_read(gp, sectors[0]), 617 (unsigned long long)disk_stat_read(gp, sectors[0]),
584 jiffies_to_msecs(disk_stat_read(gp, ticks[0])), 618 jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
@@ -590,7 +624,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
590 jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); 624 jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
591 625
592 /* now show all non-0 size partitions of it */ 626 /* now show all non-0 size partitions of it */
593 for (n = 0; n < gp->minors - 1; n++) { 627 for (n = 0; n < disk_max_parts(gp); n++) {
594 struct hd_struct *hd = gp->part[n]; 628 struct hd_struct *hd = gp->part[n];
595 629
596 if (!hd || !hd->nr_sects) 630 if (!hd || !hd->nr_sects)
@@ -601,8 +635,8 @@ static int diskstats_show(struct seq_file *seqf, void *v)
601 preempt_enable(); 635 preempt_enable();
602 seq_printf(seqf, "%4d %4d %s %lu %lu %llu " 636 seq_printf(seqf, "%4d %4d %s %lu %lu %llu "
603 "%u %lu %lu %llu %u %u %u %u\n", 637 "%u %lu %lu %llu %u %u %u %u\n",
604 gp->major, n + gp->first_minor + 1, 638 MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
605 disk_name(gp, n + 1, buf), 639 disk_name(gp, hd->partno, buf),
606 part_stat_read(hd, ios[0]), 640 part_stat_read(hd, ios[0]),
607 part_stat_read(hd, merges[0]), 641 part_stat_read(hd, merges[0]),
608 (unsigned long long)part_stat_read(hd, sectors[0]), 642 (unsigned long long)part_stat_read(hd, sectors[0]),
@@ -661,11 +695,22 @@ dev_t blk_lookup_devt(const char *name, int partno)
661 while ((dev = class_dev_iter_next(&iter))) { 695 while ((dev = class_dev_iter_next(&iter))) {
662 struct gendisk *disk = dev_to_disk(dev); 696 struct gendisk *disk = dev_to_disk(dev);
663 697
664 if (!strcmp(dev->bus_id, name) && partno < disk->minors) { 698 if (strcmp(dev->bus_id, name))
665 devt = MKDEV(MAJOR(dev->devt), 699 continue;
666 MINOR(dev->devt) + partno); 700 if (partno < 0 || partno > disk_max_parts(disk))
667 break; 701 continue;
702
703 if (partno == 0)
704 devt = disk_devt(disk);
705 else {
706 struct hd_struct *part = disk->part[partno - 1];
707
708 if (!part || !part->nr_sects)
709 continue;
710
711 devt = part_devt(part);
668 } 712 }
713 break;
669 } 714 }
670 class_dev_iter_exit(&iter); 715 class_dev_iter_exit(&iter);
671 return devt; 716 return devt;
@@ -755,7 +800,7 @@ void set_disk_ro(struct gendisk *disk, int flag)
755{ 800{
756 int i; 801 int i;
757 disk->policy = flag; 802 disk->policy = flag;
758 for (i = 0; i < disk->minors - 1; i++) 803 for (i = 0; i < disk_max_parts(disk); i++)
759 if (disk->part[i]) disk->part[i]->policy = flag; 804 if (disk->part[i]) disk->part[i]->policy = flag;
760} 805}
761 806
diff --git a/block/ioctl.c b/block/ioctl.c
index d77f5e280a6e..403f7d7e0c28 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -29,7 +29,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
29 if (bdev != bdev->bd_contains) 29 if (bdev != bdev->bd_contains)
30 return -EINVAL; 30 return -EINVAL;
31 partno = p.pno; 31 partno = p.pno;
32 if (partno <= 0 || partno >= disk->minors) 32 if (partno <= 0 || partno > disk_max_parts(disk))
33 return -EINVAL; 33 return -EINVAL;
34 switch (a.op) { 34 switch (a.op) {
35 case BLKPG_ADD_PARTITION: 35 case BLKPG_ADD_PARTITION:
@@ -47,7 +47,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
47 mutex_lock(&bdev->bd_mutex); 47 mutex_lock(&bdev->bd_mutex);
48 48
49 /* overlap? */ 49 /* overlap? */
50 for (i = 0; i < disk->minors - 1; i++) { 50 for (i = 0; i < disk_max_parts(disk); i++) {
51 struct hd_struct *s = disk->part[i]; 51 struct hd_struct *s = disk->part[i];
52 52
53 if (!s) 53 if (!s)
@@ -96,7 +96,7 @@ static int blkdev_reread_part(struct block_device *bdev)
96 struct gendisk *disk = bdev->bd_disk; 96 struct gendisk *disk = bdev->bd_disk;
97 int res; 97 int res;
98 98
99 if (disk->minors == 1 || bdev != bdev->bd_contains) 99 if (!disk_max_parts(disk) || bdev != bdev->bd_contains)
100 return -EINVAL; 100 return -EINVAL;
101 if (!capable(CAP_SYS_ADMIN)) 101 if (!capable(CAP_SYS_ADMIN))
102 return -EACCES; 102 return -EACCES;