aboutsummaryrefslogtreecommitdiffstats
path: root/block/genhd.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-09-03 02:57:12 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:04 -0400
commitdef4e38ddda9bef20b69bfa939195c2f79da7979 (patch)
tree51535a76dee0b21857d2c64da22a0406c0dc7357 /block/genhd.c
parent2ac3cee5298a247b2774f3319b28a05f588c3f0e (diff)
block: use class_dev_iterator instead of class_for_each_device()
Recent block_class iteration updates 5c6f35c5..27f3025 converted all class device iteration to class_for_each_device() and class_find_device(), which are correct but pain in the ass to use. This pach converts them to newly introduced class_dev_iterator so that they can use more natural control structures instead of separate callbacks and struct to pass parameters to them. This results in smaller and easier code. This patch also restores the original behavior of not printing header in /proc/partitions if there's no partition to print. This is trivial but still user-visible behavior. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/genhd.c')
-rw-r--r--block/genhd.c252
1 files changed, 97 insertions, 155 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 9eb8b3e212c1..8b9a9ff1a842 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -226,117 +226,114 @@ struct gendisk *get_gendisk(dev_t devt, int *part)
226} 226}
227 227
228/* 228/*
229 * print a partitions - intended for places where the root filesystem can't be
230 * mounted and thus to give the victim some idea of what went wrong
231 */
232static int printk_partition(struct device *dev, void *data)
233{
234 struct gendisk *sgp;
235 char buf[BDEVNAME_SIZE];
236 int n;
237
238 if (dev->type != &disk_type)
239 return 0;
240
241 sgp = dev_to_disk(dev);
242 /*
243 * Don't show empty devices or things that have been surpressed
244 */
245 if (get_capacity(sgp) == 0 ||
246 (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
247 return 0;
248
249 /*
250 * Note, unlike /proc/partitions, I am showing the numbers in
251 * hex - the same format as the root= option takes.
252 */
253 printk("%02x%02x %10llu %s",
254 sgp->major, sgp->first_minor,
255 (unsigned long long)get_capacity(sgp) >> 1,
256 disk_name(sgp, 0, buf));
257 if (sgp->driverfs_dev != NULL &&
258 sgp->driverfs_dev->driver != NULL)
259 printk(" driver: %s\n",
260 sgp->driverfs_dev->driver->name);
261 else
262 printk(" (driver?)\n");
263
264 /* now show the partitions */
265 for (n = 0; n < sgp->minors - 1; ++n) {
266 if (sgp->part[n] == NULL)
267 continue;
268 if (sgp->part[n]->nr_sects == 0)
269 continue;
270 printk(" %02x%02x %10llu %s\n",
271 sgp->major, n + 1 + sgp->first_minor,
272 (unsigned long long)sgp->part[n]->nr_sects >> 1,
273 disk_name(sgp, n + 1, buf));
274 }
275
276 return 0;
277}
278
279/*
280 * print a full list of all partitions - intended for places where the root 229 * print a full list of all partitions - intended for places where the root
281 * filesystem can't be mounted and thus to give the victim some idea of what 230 * filesystem can't be mounted and thus to give the victim some idea of what
282 * went wrong 231 * went wrong
283 */ 232 */
284void __init printk_all_partitions(void) 233void __init printk_all_partitions(void)
285{ 234{
286 class_for_each_device(&block_class, NULL, NULL, printk_partition); 235 struct class_dev_iter iter;
236 struct device *dev;
237
238 class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
239 while ((dev = class_dev_iter_next(&iter))) {
240 struct gendisk *disk = dev_to_disk(dev);
241 char buf[BDEVNAME_SIZE];
242 int n;
243
244 /*
245 * Don't show empty devices or things that have been
246 * surpressed
247 */
248 if (get_capacity(disk) == 0 ||
249 (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
250 continue;
251
252 /*
253 * Note, unlike /proc/partitions, I am showing the
254 * numbers in hex - the same format as the root=
255 * option takes.
256 */
257 printk("%02x%02x %10llu %s",
258 disk->major, disk->first_minor,
259 (unsigned long long)get_capacity(disk) >> 1,
260 disk_name(disk, 0, buf));
261 if (disk->driverfs_dev != NULL &&
262 disk->driverfs_dev->driver != NULL)
263 printk(" driver: %s\n",
264 disk->driverfs_dev->driver->name);
265 else
266 printk(" (driver?)\n");
267
268 /* now show the partitions */
269 for (n = 0; n < disk->minors - 1; ++n) {
270 if (disk->part[n] == NULL)
271 continue;
272 if (disk->part[n]->nr_sects == 0)
273 continue;
274 printk(" %02x%02x %10llu %s\n",
275 disk->major, n + 1 + disk->first_minor,
276 (unsigned long long)disk->part[n]->nr_sects >> 1,
277 disk_name(disk, n + 1, buf));
278 }
279 }
280 class_dev_iter_exit(&iter);
287} 281}
288 282
289#ifdef CONFIG_PROC_FS 283#ifdef CONFIG_PROC_FS
290/* iterator */ 284/* iterator */
291static int find_start(struct device *dev, void *data) 285static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos)
292{ 286{
293 loff_t *k = data; 287 loff_t skip = *pos;
288 struct class_dev_iter *iter;
289 struct device *dev;
294 290
295 if (dev->type != &disk_type) 291 iter = kmalloc(GFP_KERNEL, sizeof(*iter));
296 return 0; 292 if (!iter)
297 if (!*k) 293 return ERR_PTR(-ENOMEM);
298 return 1; 294
299 (*k)--; 295 seqf->private = iter;
300 return 0; 296 class_dev_iter_init(iter, &block_class, NULL, &disk_type);
297 do {
298 dev = class_dev_iter_next(iter);
299 if (!dev)
300 return NULL;
301 } while (skip--);
302
303 return dev_to_disk(dev);
301} 304}
302 305
303static void *part_start(struct seq_file *part, loff_t *pos) 306static void *disk_seqf_next(struct seq_file *seqf, void *v, loff_t *pos)
304{ 307{
305 struct device *dev; 308 struct device *dev;
306 loff_t n = *pos;
307
308 if (!n)
309 part->private = (void *)1LU; /* tell show to print header */
310 309
311 dev = class_find_device(&block_class, NULL, &n, find_start); 310 (*pos)++;
311 dev = class_dev_iter_next(seqf->private);
312 if (dev) 312 if (dev)
313 return dev_to_disk(dev); 313 return dev_to_disk(dev);
314 314
315 return NULL; 315 return NULL;
316} 316}
317 317
318static int find_next(struct device *dev, void *data) 318static void disk_seqf_stop(struct seq_file *seqf, void *v)
319{ 319{
320 if (dev->type == &disk_type) 320 struct class_dev_iter *iter = seqf->private;
321 return 1;
322 return 0;
323}
324 321
325static void *part_next(struct seq_file *part, void *v, loff_t *pos) 322 /* stop is called even after start failed :-( */
326{ 323 if (iter) {
327 struct gendisk *gp = v; 324 class_dev_iter_exit(iter);
328 struct device *dev; 325 kfree(iter);
329 ++*pos;
330 dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
331 if (dev) {
332 put_device(dev);
333 return dev_to_disk(dev);
334 } 326 }
335 return NULL;
336} 327}
337 328
338static void part_stop(struct seq_file *part, void *v) 329static void *show_partition_start(struct seq_file *seqf, loff_t *pos)
339{ 330{
331 static void *p;
332
333 p = disk_seqf_start(seqf, pos);
334 if (!IS_ERR(p) && p)
335 seq_puts(seqf, "major minor #blocks name\n\n");
336 return p;
340} 337}
341 338
342static int show_partition(struct seq_file *part, void *v) 339static int show_partition(struct seq_file *part, void *v)
@@ -383,9 +380,9 @@ static int show_partition(struct seq_file *part, void *v)
383} 380}
384 381
385const struct seq_operations partitions_op = { 382const struct seq_operations partitions_op = {
386 .start = part_start, 383 .start = show_partition_start,
387 .next = part_next, 384 .next = disk_seqf_next,
388 .stop = part_stop, 385 .stop = disk_seqf_stop,
389 .show = show_partition 386 .show = show_partition
390}; 387};
391#endif 388#endif
@@ -567,44 +564,6 @@ static struct device_type disk_type = {
567}; 564};
568 565
569#ifdef CONFIG_PROC_FS 566#ifdef CONFIG_PROC_FS
570/*
571 * aggregate disk stat collector. Uses the same stats that the sysfs
572 * entries do, above, but makes them available through one seq_file.
573 *
574 * The output looks suspiciously like /proc/partitions with a bunch of
575 * extra fields.
576 */
577
578static void *diskstats_start(struct seq_file *part, loff_t *pos)
579{
580 struct device *dev;
581 loff_t n = *pos;
582
583 dev = class_find_device(&block_class, NULL, &n, find_start);
584 if (dev)
585 return dev_to_disk(dev);
586
587 return NULL;
588}
589
590static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
591{
592 struct gendisk *gp = v;
593 struct device *dev;
594
595 ++*pos;
596 dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
597 if (dev) {
598 put_device(dev);
599 return dev_to_disk(dev);
600 }
601 return NULL;
602}
603
604static void diskstats_stop(struct seq_file *part, void *v)
605{
606}
607
608static int diskstats_show(struct seq_file *s, void *v) 567static int diskstats_show(struct seq_file *s, void *v)
609{ 568{
610 struct gendisk *gp = v; 569 struct gendisk *gp = v;
@@ -666,9 +625,9 @@ static int diskstats_show(struct seq_file *s, void *v)
666} 625}
667 626
668const struct seq_operations diskstats_op = { 627const struct seq_operations diskstats_op = {
669 .start = diskstats_start, 628 .start = disk_seqf_start,
670 .next = diskstats_next, 629 .next = disk_seqf_next,
671 .stop = diskstats_stop, 630 .stop = disk_seqf_stop,
672 .show = diskstats_show 631 .show = diskstats_show
673}; 632};
674#endif /* CONFIG_PROC_FS */ 633#endif /* CONFIG_PROC_FS */
@@ -696,40 +655,23 @@ void genhd_media_change_notify(struct gendisk *disk)
696EXPORT_SYMBOL_GPL(genhd_media_change_notify); 655EXPORT_SYMBOL_GPL(genhd_media_change_notify);
697#endif /* 0 */ 656#endif /* 0 */
698 657
699struct find_block { 658dev_t blk_lookup_devt(const char *name, int part)
700 const char *name;
701 int part;
702};
703
704static int match_id(struct device *dev, void *data)
705{ 659{
706 struct find_block *find = data; 660 dev_t devt = MKDEV(0, 0);
661 struct class_dev_iter iter;
662 struct device *dev;
707 663
708 if (dev->type != &disk_type) 664 class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
709 return 0; 665 while ((dev = class_dev_iter_next(&iter))) {
710 if (strcmp(dev->bus_id, find->name) == 0) {
711 struct gendisk *disk = dev_to_disk(dev); 666 struct gendisk *disk = dev_to_disk(dev);
712 if (find->part < disk->minors)
713 return 1;
714 }
715 return 0;
716}
717 667
718dev_t blk_lookup_devt(const char *name, int part) 668 if (!strcmp(dev->bus_id, name) && part < disk->minors) {
719{ 669 devt = MKDEV(MAJOR(dev->devt),
720 struct device *dev; 670 MINOR(dev->devt) + part);
721 dev_t devt = MKDEV(0, 0); 671 break;
722 struct find_block find; 672 }
723
724 find.name = name;
725 find.part = part;
726 dev = class_find_device(&block_class, NULL, &find, match_id);
727 if (dev) {
728 put_device(dev);
729 devt = MKDEV(MAJOR(dev->devt),
730 MINOR(dev->devt) + part);
731 } 673 }
732 674 class_dev_iter_exit(&iter);
733 return devt; 675 return devt;
734} 676}
735EXPORT_SYMBOL(blk_lookup_devt); 677EXPORT_SYMBOL(blk_lookup_devt);