diff options
author | Tejun Heo <tj@kernel.org> | 2008-09-03 03:01:48 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:05 -0400 |
commit | f331c0296f2a9fee0d396a70598b954062603015 (patch) | |
tree | f74c467d58940131d97d90c4ea549843185e6ef0 /block/genhd.c | |
parent | cf771cb5a7b716f3f9e532fd42a1e3a0a75adec5 (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/genhd.c')
-rw-r--r-- | block/genhd.c | 107 |
1 files changed, 76 insertions, 31 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 | */ | ||
241 | extern 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 | } | ||
258 | EXPORT_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 | ||