X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=block%2Fgenhd.c;h=db4c60c802d6da5bc00a2bf7c3be5e1179250e64;hb=837c7878771c15ed8d85ecf814ece7fcb4551b46;hp=f1ed83f3f083761cd80d04d65a83f8da40afd484;hpb=123656d4cc8c946f578ebd18c2050f5251720428;p=linux-2.6-omap-h63xx.git diff --git a/block/genhd.c b/block/genhd.c index f1ed83f3f08..db4c60c802d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -15,12 +15,13 @@ #include #include #include +#include #define MAX_PROBE_HASH 255 /* random */ static struct subsystem block_subsys; -static DECLARE_MUTEX(block_subsys_sem); +static DEFINE_MUTEX(block_subsys_lock); /* * Can be deleted altogether. Later. @@ -38,41 +39,107 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -#ifdef CONFIG_PROC_FS -/* get block device names in somewhat random order */ -int get_blkdev_list(char *p, int used) +struct blkdev_info { + int index; + struct blk_major_name *bd; +}; + +/* + * iterate over a list of blkdev_info structures. allows + * the major_names array to be iterated over from outside this file + * must be called with the block_subsys_lock held + */ +void *get_next_blkdev(void *dev) +{ + struct blkdev_info *info; + + if (dev == NULL) { + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out; + info->index=0; + info->bd = major_names[info->index]; + if (info->bd) + goto out; + } else { + info = dev; + } + + while (info->index < ARRAY_SIZE(major_names)) { + if (info->bd) + info->bd = info->bd->next; + if (info->bd) + goto out; + /* + * No devices on this chain, move to the next + */ + info->index++; + info->bd = (info->index < ARRAY_SIZE(major_names)) ? + major_names[info->index] : NULL; + if (info->bd) + goto out; + } + +out: + return info; +} + +void *acquire_blkdev_list(void) +{ + mutex_lock(&block_subsys_lock); + return get_next_blkdev(NULL); +} + +void release_blkdev_list(void *dev) +{ + mutex_unlock(&block_subsys_lock); + kfree(dev); +} + + +/* + * Count the number of records in the blkdev_list. + * must be called with the block_subsys_lock held + */ +int count_blkdev_list(void) { struct blk_major_name *n; - int i, len; + int i, count; - len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); + count = 0; - down(&block_subsys_sem); for (i = 0; i < ARRAY_SIZE(major_names); i++) { - for (n = major_names[i]; n; n = n->next) { - /* - * If the curent string plus the 5 extra characters - * in the line would run us off the page, then we're done - */ - if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) - goto page_full; - len += sprintf(p+len, "%3d %s\n", - n->major, n->name); - } + for (n = major_names[i]; n; n = n->next) + count++; } -page_full: - up(&block_subsys_sem); - return len; + return count; } -#endif + +/* + * extract the major and name values from a blkdev_info struct + * passed in as a void to *dev. Must be called with + * block_subsys_lock held + */ +int get_blkdev_info(void *dev, int *major, char **name) +{ + struct blkdev_info *info = dev; + + if (info->bd == NULL) + return 1; + + *major = info->bd->major; + *name = info->bd->name; + return 0; +} + int register_blkdev(unsigned int major, const char *name) { struct blk_major_name **n, *p; int index, ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); /* temporary */ if (major == 0) { @@ -117,7 +184,7 @@ int register_blkdev(unsigned int major, const char *name) kfree(p); } out: - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); return ret; } @@ -131,7 +198,7 @@ int unregister_blkdev(unsigned int major, const char *name) int index = major_to_index(major); int ret = 0; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); for (n = &major_names[index]; *n; n = &(*n)->next) if ((*n)->major == major) break; @@ -141,7 +208,7 @@ int unregister_blkdev(unsigned int major, const char *name) p = *n; *n = p->next; } - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); kfree(p); return ret; @@ -235,7 +302,7 @@ static void *part_start(struct seq_file *part, loff_t *pos) struct list_head *p; loff_t l = *pos; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!l--) return list_entry(p, struct gendisk, kobj.entry); @@ -252,7 +319,7 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos) static void part_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int show_partition(struct seq_file *part, void *v) @@ -311,7 +378,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data) static int __init genhd_device_init(void) { - bdev_map = kobj_map_init(base_probe, &block_subsys_sem); + bdev_map = kobj_map_init(base_probe, &block_subsys_lock); blk_dev_init(); subsystem_register(&block_subsys); return 0; @@ -387,8 +454,8 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) disk_round_stats(disk); preempt_enable(); return sprintf(page, - "%8u %8u %8llu %8u " - "%8u %8u %8llu %8u " + "%8lu %8lu %8llu %8u " + "%8lu %8lu %8llu %8u " "%8u %8u %8u" "\n", disk_stat_read(disk, ios[READ]), @@ -545,7 +612,7 @@ static void *diskstats_start(struct seq_file *part, loff_t *pos) loff_t k = *pos; struct list_head *p; - down(&block_subsys_sem); + mutex_lock(&block_subsys_lock); list_for_each(p, &block_subsys.kset.list) if (!k--) return list_entry(p, struct gendisk, kobj.entry); @@ -562,7 +629,7 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) static void diskstats_stop(struct seq_file *part, void *v) { - up(&block_subsys_sem); + mutex_unlock(&block_subsys_lock); } static int diskstats_show(struct seq_file *s, void *v) @@ -582,7 +649,7 @@ static int diskstats_show(struct seq_file *s, void *v) preempt_disable(); disk_round_stats(gp); preempt_enable(); - seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n", + 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), disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), (unsigned long long)disk_stat_read(gp, sectors[0]),