disk->minors, NULL, exact_match, exact_lock, disk);
register_disk(disk);
blk_register_queue(disk);
- blk_register_filter(disk);
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
void unlink_gendisk(struct gendisk *disk)
{
- blk_unregister_filter(disk);
sysfs_remove_link(&disk->dev.kobj, "bdi");
bdi_unregister(&disk->queue->backing_dev_info);
blk_unregister_queue(disk);
/**
* get_gendisk - get partitioning information for a given device
- * @dev: device to get partitioning information for
+ * @devt: device to get partitioning information for
+ * @part: returned partition index
*
* This function gets the structure containing partitioning
- * information for the given device @dev.
+ * information for the given device @devt.
*/
struct gendisk *get_gendisk(dev_t devt, int *part)
{
*/
void __init printk_all_partitions(void)
{
+ struct class_dev_iter iter;
struct device *dev;
- struct gendisk *sgp;
- char buf[BDEVNAME_SIZE];
- int n;
- mutex_lock(&block_class_lock);
- /* For each block device... */
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- sgp = dev_to_disk(dev);
+ class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
+ while ((dev = class_dev_iter_next(&iter))) {
+ struct gendisk *disk = dev_to_disk(dev);
+ char buf[BDEVNAME_SIZE];
+ int n;
+
/*
- * Don't show empty devices or things that have been surpressed
+ * Don't show empty devices or things that have been
+ * surpressed
*/
- if (get_capacity(sgp) == 0 ||
- (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
+ if (get_capacity(disk) == 0 ||
+ (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
continue;
/*
- * Note, unlike /proc/partitions, I am showing the numbers in
- * hex - the same format as the root= option takes.
+ * Note, unlike /proc/partitions, I am showing the
+ * numbers in hex - the same format as the root=
+ * option takes.
*/
printk("%02x%02x %10llu %s",
- sgp->major, sgp->first_minor,
- (unsigned long long)get_capacity(sgp) >> 1,
- disk_name(sgp, 0, buf));
- if (sgp->driverfs_dev != NULL &&
- sgp->driverfs_dev->driver != NULL)
+ disk->major, disk->first_minor,
+ (unsigned long long)get_capacity(disk) >> 1,
+ disk_name(disk, 0, buf));
+ if (disk->driverfs_dev != NULL &&
+ disk->driverfs_dev->driver != NULL)
printk(" driver: %s\n",
- sgp->driverfs_dev->driver->name);
+ disk->driverfs_dev->driver->name);
else
printk(" (driver?)\n");
/* now show the partitions */
- for (n = 0; n < sgp->minors - 1; ++n) {
- if (sgp->part[n] == NULL)
+ for (n = 0; n < disk->minors - 1; ++n) {
+ if (disk->part[n] == NULL)
continue;
- if (sgp->part[n]->nr_sects == 0)
+ if (disk->part[n]->nr_sects == 0)
continue;
printk(" %02x%02x %10llu %s\n",
- sgp->major, n + 1 + sgp->first_minor,
- (unsigned long long)sgp->part[n]->nr_sects >> 1,
- disk_name(sgp, n + 1, buf));
+ disk->major, n + 1 + disk->first_minor,
+ (unsigned long long)disk->part[n]->nr_sects >> 1,
+ disk_name(disk, n + 1, buf));
}
}
-
- mutex_unlock(&block_class_lock);
+ class_dev_iter_exit(&iter);
}
#ifdef CONFIG_PROC_FS
/* iterator */
-static void *part_start(struct seq_file *part, loff_t *pos)
+static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos)
{
- loff_t k = *pos;
+ loff_t skip = *pos;
+ struct class_dev_iter *iter;
struct device *dev;
- mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (!k--)
- return dev_to_disk(dev);
- }
- return NULL;
+ iter = kmalloc(GFP_KERNEL, sizeof(*iter));
+ if (!iter)
+ return ERR_PTR(-ENOMEM);
+
+ seqf->private = iter;
+ class_dev_iter_init(iter, &block_class, NULL, &disk_type);
+ do {
+ dev = class_dev_iter_next(iter);
+ if (!dev)
+ return NULL;
+ } while (skip--);
+
+ return dev_to_disk(dev);
}
-static void *part_next(struct seq_file *part, void *v, loff_t *pos)
+static void *disk_seqf_next(struct seq_file *seqf, void *v, loff_t *pos)
{
- struct gendisk *gp = v;
struct device *dev;
- ++*pos;
- list_for_each_entry(dev, &gp->dev.node, node) {
- if (&dev->node == &block_class.devices)
- return NULL;
- if (dev->type == &disk_type)
- return dev_to_disk(dev);
- }
+
+ (*pos)++;
+ dev = class_dev_iter_next(seqf->private);
+ if (dev)
+ return dev_to_disk(dev);
+
return NULL;
}
-static void part_stop(struct seq_file *part, void *v)
+static void disk_seqf_stop(struct seq_file *seqf, void *v)
{
- mutex_unlock(&block_class_lock);
+ struct class_dev_iter *iter = seqf->private;
+
+ /* stop is called even after start failed :-( */
+ if (iter) {
+ class_dev_iter_exit(iter);
+ kfree(iter);
+ }
+}
+
+static void *show_partition_start(struct seq_file *seqf, loff_t *pos)
+{
+ static void *p;
+
+ p = disk_seqf_start(seqf, pos);
+ if (!IS_ERR(p) && p)
+ seq_puts(seqf, "major minor #blocks name\n\n");
+ return p;
}
static int show_partition(struct seq_file *part, void *v)
int n;
char buf[BDEVNAME_SIZE];
- if (&sgp->dev.node == block_class.devices.next)
+ /*
+ * Print header if start told us to do. This is to preserve
+ * the original behavior of not printing header if no
+ * partition exists. This hackery will be removed later with
+ * class iteration clean up.
+ */
+ if (part->private) {
seq_puts(part, "major minor #blocks name\n\n");
+ part->private = NULL;
+ }
/* Don't show non-partitionable removeable devices or empty devices */
if (!get_capacity(sgp) ||
}
const struct seq_operations partitions_op = {
- .start = part_start,
- .next = part_next,
- .stop = part_stop,
+ .start = show_partition_start,
+ .next = disk_seqf_next,
+ .stop = disk_seqf_stop,
.show = show_partition
};
#endif
.release = disk_release,
};
-/*
- * aggregate disk stat collector. Uses the same stats that the sysfs
- * entries do, above, but makes them available through one seq_file.
- *
- * The output looks suspiciously like /proc/partitions with a bunch of
- * extra fields.
- */
-
-static void *diskstats_start(struct seq_file *part, loff_t *pos)
-{
- loff_t k = *pos;
- struct device *dev;
-
- mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (!k--)
- return dev_to_disk(dev);
- }
- return NULL;
-}
-
-static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
-{
- struct gendisk *gp = v;
- struct device *dev;
-
- ++*pos;
- list_for_each_entry(dev, &gp->dev.node, node) {
- if (&dev->node == &block_class.devices)
- return NULL;
- if (dev->type == &disk_type)
- return dev_to_disk(dev);
- }
- return NULL;
-}
-
-static void diskstats_stop(struct seq_file *part, void *v)
-{
- mutex_unlock(&block_class_lock);
-}
-
+#ifdef CONFIG_PROC_FS
static int diskstats_show(struct seq_file *s, void *v)
{
struct gendisk *gp = v;
char buf[BDEVNAME_SIZE];
- int n = 0;
+ int n;
/*
if (&gp->dev.kobj.entry == block_class.devices.next)
disk_round_stats(gp);
preempt_enable();
seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
- gp->major, n + gp->first_minor, disk_name(gp, n, buf),
+ gp->major, gp->first_minor, disk_name(gp, 0, buf),
disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
(unsigned long long)disk_stat_read(gp, sectors[0]),
jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
}
const struct seq_operations diskstats_op = {
- .start = diskstats_start,
- .next = diskstats_next,
- .stop = diskstats_stop,
+ .start = disk_seqf_start,
+ .next = disk_seqf_next,
+ .stop = disk_seqf_stop,
.show = diskstats_show
};
+#endif /* CONFIG_PROC_FS */
static void media_change_notify_thread(struct work_struct *work)
{
dev_t blk_lookup_devt(const char *name, int part)
{
- struct device *dev;
dev_t devt = MKDEV(0, 0);
+ struct class_dev_iter iter;
+ struct device *dev;
- mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (strcmp(dev->bus_id, name) == 0) {
- struct gendisk *disk = dev_to_disk(dev);
+ class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
+ while ((dev = class_dev_iter_next(&iter))) {
+ struct gendisk *disk = dev_to_disk(dev);
- if (part < disk->minors)
- devt = MKDEV(MAJOR(dev->devt),
- MINOR(dev->devt) + part);
+ if (!strcmp(dev->bus_id, name) && part < disk->minors) {
+ devt = MKDEV(MAJOR(dev->devt),
+ MINOR(dev->devt) + part);
break;
}
}
- mutex_unlock(&block_class_lock);
-
+ class_dev_iter_exit(&iter);
return devt;
}
EXPORT_SYMBOL(blk_lookup_devt);