diff options
author | Neil Horman <nhorman@redhat.com> | 2006-01-14 16:20:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-14 21:25:19 -0500 |
commit | 7170be5f586b59bdcdab082778a5d9203ba7b667 (patch) | |
tree | 00d34a062c5bbab83315232078296567037bd3f4 /fs/char_dev.c | |
parent | faf3a98918aa5f14a29e0d246e194be58b9357f0 (diff) |
[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 <nhorman@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/char_dev.c')
-rw-r--r-- | fs/char_dev.c | 96 |
1 files changed, 73 insertions, 23 deletions
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 { | |||
35 | unsigned int major; | 35 | unsigned int major; |
36 | unsigned int baseminor; | 36 | unsigned int baseminor; |
37 | int minorct; | 37 | int minorct; |
38 | const char *name; | 38 | char name[64]; |
39 | struct file_operations *fops; | 39 | struct file_operations *fops; |
40 | struct cdev *cdev; /* will die */ | 40 | struct cdev *cdev; /* will die */ |
41 | } *chrdevs[MAX_PROBE_HASH]; | 41 | } *chrdevs[MAX_PROBE_HASH]; |
@@ -46,34 +46,84 @@ static inline int major_to_index(int major) | |||
46 | return major % MAX_PROBE_HASH; | 46 | return major % MAX_PROBE_HASH; |
47 | } | 47 | } |
48 | 48 | ||
49 | /* get char device names in somewhat random order */ | 49 | struct chrdev_info { |
50 | int get_chrdev_list(char *page) | 50 | int index; |
51 | { | ||
52 | struct char_device_struct *cd; | 51 | struct char_device_struct *cd; |
53 | int i, len; | 52 | }; |
54 | 53 | ||
55 | len = sprintf(page, "Character devices:\n"); | 54 | void *get_next_chrdev(void *dev) |
55 | { | ||
56 | struct chrdev_info *info; | ||
56 | 57 | ||
58 | if (dev == NULL) { | ||
59 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
60 | if (!info) | ||
61 | goto out; | ||
62 | info->index=0; | ||
63 | info->cd = chrdevs[info->index]; | ||
64 | if (info->cd) | ||
65 | goto out; | ||
66 | } else { | ||
67 | info = dev; | ||
68 | } | ||
69 | |||
70 | while (info->index < ARRAY_SIZE(chrdevs)) { | ||
71 | if (info->cd) | ||
72 | info->cd = info->cd->next; | ||
73 | if (info->cd) | ||
74 | goto out; | ||
75 | /* | ||
76 | * No devices on this chain, move to the next | ||
77 | */ | ||
78 | info->index++; | ||
79 | info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? | ||
80 | chrdevs[info->index] : NULL; | ||
81 | if (info->cd) | ||
82 | goto out; | ||
83 | } | ||
84 | |||
85 | out: | ||
86 | return info; | ||
87 | } | ||
88 | |||
89 | void *acquire_chrdev_list(void) | ||
90 | { | ||
57 | down(&chrdevs_lock); | 91 | down(&chrdevs_lock); |
92 | return get_next_chrdev(NULL); | ||
93 | } | ||
94 | |||
95 | void release_chrdev_list(void *dev) | ||
96 | { | ||
97 | up(&chrdevs_lock); | ||
98 | kfree(dev); | ||
99 | } | ||
100 | |||
101 | |||
102 | int count_chrdev_list(void) | ||
103 | { | ||
104 | struct char_device_struct *cd; | ||
105 | int i, count; | ||
106 | |||
107 | count = 0; | ||
108 | |||
58 | for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { | 109 | for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { |
59 | for (cd = chrdevs[i]; cd; cd = cd->next) { | 110 | for (cd = chrdevs[i]; cd; cd = cd->next) |
60 | /* | 111 | count++; |
61 | * if the current name, plus the 5 extra characters | ||
62 | * in the device line for this entry | ||
63 | * would run us off the page, we're done | ||
64 | */ | ||
65 | if ((len+strlen(cd->name) + 5) >= PAGE_SIZE) | ||
66 | goto page_full; | ||
67 | |||
68 | |||
69 | len += sprintf(page+len, "%3d %s\n", | ||
70 | cd->major, cd->name); | ||
71 | } | ||
72 | } | 112 | } |
73 | page_full: | ||
74 | up(&chrdevs_lock); | ||
75 | 113 | ||
76 | return len; | 114 | return count; |
115 | } | ||
116 | |||
117 | int get_chrdev_info(void *dev, int *major, char **name) | ||
118 | { | ||
119 | struct chrdev_info *info = dev; | ||
120 | |||
121 | if (info->cd == NULL) | ||
122 | return 1; | ||
123 | |||
124 | *major = info->cd->major; | ||
125 | *name = info->cd->name; | ||
126 | return 0; | ||
77 | } | 127 | } |
78 | 128 | ||
79 | /* | 129 | /* |
@@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
121 | cd->major = major; | 171 | cd->major = major; |
122 | cd->baseminor = baseminor; | 172 | cd->baseminor = baseminor; |
123 | cd->minorct = minorct; | 173 | cd->minorct = minorct; |
124 | cd->name = name; | 174 | strncpy(cd->name,name, 64); |
125 | 175 | ||
126 | i = major_to_index(major); | 176 | i = major_to_index(major); |
127 | 177 | ||