From 7170be5f586b59bdcdab082778a5d9203ba7b667 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Sat, 14 Jan 2006 13:20:38 -0800 Subject: [PATCH] convert /proc/devices to use seq_file interface A Christoph suggested that the /proc/devices file be converted to use the seq_file interface. This patch does that. I've obxerved one or two installation that had sufficiently large sans that they overran the 4k limit on /proc/devices. Signed-off-by: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/char_dev.c | 96 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 23 deletions(-) (limited to 'fs/char_dev.c') diff --git a/fs/char_dev.c b/fs/char_dev.c index 3b1b1eefdbb..21195c48163 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -35,7 +35,7 @@ static struct char_device_struct { unsigned int major; unsigned int baseminor; int minorct; - const char *name; + char name[64]; struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[MAX_PROBE_HASH]; @@ -46,34 +46,84 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -/* get char device names in somewhat random order */ -int get_chrdev_list(char *page) -{ +struct chrdev_info { + int index; struct char_device_struct *cd; - int i, len; +}; - len = sprintf(page, "Character devices:\n"); +void *get_next_chrdev(void *dev) +{ + struct chrdev_info *info; + if (dev == NULL) { + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out; + info->index=0; + info->cd = chrdevs[info->index]; + if (info->cd) + goto out; + } else { + info = dev; + } + + while (info->index < ARRAY_SIZE(chrdevs)) { + if (info->cd) + info->cd = info->cd->next; + if (info->cd) + goto out; + /* + * No devices on this chain, move to the next + */ + info->index++; + info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? + chrdevs[info->index] : NULL; + if (info->cd) + goto out; + } + +out: + return info; +} + +void *acquire_chrdev_list(void) +{ down(&chrdevs_lock); + return get_next_chrdev(NULL); +} + +void release_chrdev_list(void *dev) +{ + up(&chrdevs_lock); + kfree(dev); +} + + +int count_chrdev_list(void) +{ + struct char_device_struct *cd; + int i, count; + + count = 0; + for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { - for (cd = chrdevs[i]; cd; cd = cd->next) { - /* - * if the current name, plus the 5 extra characters - * in the device line for this entry - * would run us off the page, we're done - */ - if ((len+strlen(cd->name) + 5) >= PAGE_SIZE) - goto page_full; - - - len += sprintf(page+len, "%3d %s\n", - cd->major, cd->name); - } + for (cd = chrdevs[i]; cd; cd = cd->next) + count++; } -page_full: - up(&chrdevs_lock); - return len; + return count; +} + +int get_chrdev_info(void *dev, int *major, char **name) +{ + struct chrdev_info *info = dev; + + if (info->cd == NULL) + return 1; + + *major = info->cd->major; + *name = info->cd->name; + return 0; } /* @@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, cd->major = major; cd->baseminor = baseminor; cd->minorct = minorct; - cd->name = name; + strncpy(cd->name,name, 64); i = major_to_index(major); -- cgit v1.2.3