From 68eef3b4791572ecb70249c7fb145bb3742dd899 Mon Sep 17 00:00:00 2001 From: Joe Korty Date: Fri, 31 Mar 2006 02:30:32 -0800 Subject: [PATCH] Simplify proc/devices and fix early termination regression Make baby-simple the code for /proc/devices. Based on the proven design for /proc/interrupts. This also fixes the early-termination regression 2.6.16 introduced, as demonstrated by: # dd if=/proc/devices bs=1 Character devices: 1 mem 27+0 records in 27+0 records out This should also work (but is untested) when /proc/devices >4096 bytes, which I believe is what the original 2.6.16 rewrite fixed. [akpm@osdl.org: cleanups, simplifications] Signed-off-by: Joe Korty Cc: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/genhd.c | 103 +++++++--------------------------------------------------- 1 file changed, 11 insertions(+), 92 deletions(-) (limited to 'block/genhd.c') diff --git a/block/genhd.c b/block/genhd.c index db4c60c802d6..5a8d3bf02f17 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -17,8 +17,6 @@ #include #include -#define MAX_PROBE_HASH 255 /* random */ - static struct subsystem block_subsys; static DEFINE_MUTEX(block_subsys_lock); @@ -31,108 +29,29 @@ static struct blk_major_name { struct blk_major_name *next; int major; char name[16]; -} *major_names[MAX_PROBE_HASH]; +} *major_names[BLKDEV_MAJOR_HASH_SIZE]; /* index in the above - for now: assume no multimajor ranges */ static inline int major_to_index(int major) { - return major % MAX_PROBE_HASH; -} - -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); + return major % BLKDEV_MAJOR_HASH_SIZE; } +#ifdef CONFIG_PROC_FS -/* - * Count the number of records in the blkdev_list. - * must be called with the block_subsys_lock held - */ -int count_blkdev_list(void) +void blkdev_show(struct seq_file *f, off_t offset) { - struct blk_major_name *n; - int i, count; + struct blk_major_name *dp; - count = 0; - - for (i = 0; i < ARRAY_SIZE(major_names); i++) { - for (n = major_names[i]; n; n = n->next) - count++; + if (offset < BLKDEV_MAJOR_HASH_SIZE) { + mutex_lock(&block_subsys_lock); + for (dp = major_names[offset]; dp; dp = dp->next) + seq_printf(f, "%3d %s\n", dp->major, dp->name); + mutex_unlock(&block_subsys_lock); } - - return count; -} - -/* - * 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; } +#endif /* CONFIG_PROC_FS */ int register_blkdev(unsigned int major, const char *name) { -- cgit v1.2.3-59-g8ed1b