diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/proc_misc.c | 160 |
1 files changed, 150 insertions, 10 deletions
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 63bf6c00fa0c..8f8014285a34 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/kernel_stat.h> | 22 | #include <linux/kernel_stat.h> |
23 | #include <linux/fs.h> | ||
23 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
24 | #include <linux/string.h> | 25 | #include <linux/string.h> |
25 | #include <linux/mman.h> | 26 | #include <linux/mman.h> |
@@ -62,7 +63,6 @@ | |||
62 | */ | 63 | */ |
63 | extern int get_hardware_list(char *); | 64 | extern int get_hardware_list(char *); |
64 | extern int get_stram_list(char *); | 65 | extern int get_stram_list(char *); |
65 | extern int get_chrdev_list(char *); | ||
66 | extern int get_filesystem_list(char *); | 66 | extern int get_filesystem_list(char *); |
67 | extern int get_exec_domain_list(char *); | 67 | extern int get_exec_domain_list(char *); |
68 | extern int get_dma_list(char *); | 68 | extern int get_dma_list(char *); |
@@ -248,6 +248,154 @@ static int cpuinfo_open(struct inode *inode, struct file *file) | |||
248 | { | 248 | { |
249 | return seq_open(file, &cpuinfo_op); | 249 | return seq_open(file, &cpuinfo_op); |
250 | } | 250 | } |
251 | |||
252 | enum devinfo_states { | ||
253 | CHR_HDR, | ||
254 | CHR_LIST, | ||
255 | BLK_HDR, | ||
256 | BLK_LIST, | ||
257 | DEVINFO_DONE | ||
258 | }; | ||
259 | |||
260 | struct devinfo_state { | ||
261 | void *chrdev; | ||
262 | void *blkdev; | ||
263 | unsigned int num_records; | ||
264 | unsigned int cur_record; | ||
265 | enum devinfo_states state; | ||
266 | }; | ||
267 | |||
268 | static void *devinfo_start(struct seq_file *f, loff_t *pos) | ||
269 | { | ||
270 | struct devinfo_state *info = f->private; | ||
271 | |||
272 | if (*pos) { | ||
273 | if ((info) && (*pos <= info->num_records)) | ||
274 | return info; | ||
275 | return NULL; | ||
276 | } | ||
277 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
278 | f->private = info; | ||
279 | info->chrdev = acquire_chrdev_list(); | ||
280 | info->blkdev = acquire_blkdev_list(); | ||
281 | info->state = CHR_HDR; | ||
282 | info->num_records = count_chrdev_list(); | ||
283 | info->num_records += count_blkdev_list(); | ||
284 | info->num_records += 2; /* Character and Block headers */ | ||
285 | *pos = 1; | ||
286 | info->cur_record = *pos; | ||
287 | return info; | ||
288 | } | ||
289 | |||
290 | static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) | ||
291 | { | ||
292 | int idummy; | ||
293 | char *ndummy; | ||
294 | struct devinfo_state *info = f->private; | ||
295 | |||
296 | switch (info->state) { | ||
297 | case CHR_HDR: | ||
298 | info->state = CHR_LIST; | ||
299 | (*pos)++; | ||
300 | /*fallthrough*/ | ||
301 | case CHR_LIST: | ||
302 | if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) { | ||
303 | /* | ||
304 | * The character dev list is complete | ||
305 | */ | ||
306 | info->state = BLK_HDR; | ||
307 | } else { | ||
308 | info->chrdev = get_next_chrdev(info->chrdev); | ||
309 | } | ||
310 | (*pos)++; | ||
311 | break; | ||
312 | case BLK_HDR: | ||
313 | info->state = BLK_LIST; | ||
314 | (*pos)++; | ||
315 | break; | ||
316 | case BLK_LIST: | ||
317 | if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) { | ||
318 | /* | ||
319 | * The block dev list is complete | ||
320 | */ | ||
321 | info->state = DEVINFO_DONE; | ||
322 | } else { | ||
323 | info->blkdev = get_next_blkdev(info->blkdev); | ||
324 | } | ||
325 | (*pos)++; | ||
326 | break; | ||
327 | case DEVINFO_DONE: | ||
328 | (*pos)++; | ||
329 | info->cur_record = *pos; | ||
330 | info = NULL; | ||
331 | break; | ||
332 | default: | ||
333 | break; | ||
334 | } | ||
335 | if (info) | ||
336 | info->cur_record = *pos; | ||
337 | return info; | ||
338 | } | ||
339 | |||
340 | static void devinfo_stop(struct seq_file *f, void *v) | ||
341 | { | ||
342 | struct devinfo_state *info = f->private; | ||
343 | |||
344 | if (info) { | ||
345 | release_chrdev_list(info->chrdev); | ||
346 | release_blkdev_list(info->blkdev); | ||
347 | f->private = NULL; | ||
348 | kfree(info); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static int devinfo_show(struct seq_file *f, void *arg) | ||
353 | { | ||
354 | int major; | ||
355 | char *name; | ||
356 | struct devinfo_state *info = f->private; | ||
357 | |||
358 | switch(info->state) { | ||
359 | case CHR_HDR: | ||
360 | seq_printf(f,"Character devices:\n"); | ||
361 | /* fallthrough */ | ||
362 | case CHR_LIST: | ||
363 | if (!get_chrdev_info(info->chrdev,&major,&name)) | ||
364 | seq_printf(f,"%3d %s\n",major,name); | ||
365 | break; | ||
366 | case BLK_HDR: | ||
367 | seq_printf(f,"\nBlock devices:\n"); | ||
368 | /* fallthrough */ | ||
369 | case BLK_LIST: | ||
370 | if (!get_blkdev_info(info->blkdev,&major,&name)) | ||
371 | seq_printf(f,"%3d %s\n",major,name); | ||
372 | break; | ||
373 | default: | ||
374 | break; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static struct seq_operations devinfo_op = { | ||
381 | .start = devinfo_start, | ||
382 | .next = devinfo_next, | ||
383 | .stop = devinfo_stop, | ||
384 | .show = devinfo_show, | ||
385 | }; | ||
386 | |||
387 | static int devinfo_open(struct inode *inode, struct file *file) | ||
388 | { | ||
389 | return seq_open(file, &devinfo_op); | ||
390 | } | ||
391 | |||
392 | static struct file_operations proc_devinfo_operations = { | ||
393 | .open = devinfo_open, | ||
394 | .read = seq_read, | ||
395 | .llseek = seq_lseek, | ||
396 | .release = seq_release, | ||
397 | }; | ||
398 | |||
251 | static struct file_operations proc_cpuinfo_operations = { | 399 | static struct file_operations proc_cpuinfo_operations = { |
252 | .open = cpuinfo_open, | 400 | .open = cpuinfo_open, |
253 | .read = seq_read, | 401 | .read = seq_read, |
@@ -450,14 +598,6 @@ static struct file_operations proc_stat_operations = { | |||
450 | .release = single_release, | 598 | .release = single_release, |
451 | }; | 599 | }; |
452 | 600 | ||
453 | static int devices_read_proc(char *page, char **start, off_t off, | ||
454 | int count, int *eof, void *data) | ||
455 | { | ||
456 | int len = get_chrdev_list(page); | ||
457 | len += get_blkdev_list(page+len, len); | ||
458 | return proc_calc_metrics(page, start, off, count, eof, len); | ||
459 | } | ||
460 | |||
461 | /* | 601 | /* |
462 | * /proc/interrupts | 602 | * /proc/interrupts |
463 | */ | 603 | */ |
@@ -582,7 +722,6 @@ void __init proc_misc_init(void) | |||
582 | #ifdef CONFIG_STRAM_PROC | 722 | #ifdef CONFIG_STRAM_PROC |
583 | {"stram", stram_read_proc}, | 723 | {"stram", stram_read_proc}, |
584 | #endif | 724 | #endif |
585 | {"devices", devices_read_proc}, | ||
586 | {"filesystems", filesystems_read_proc}, | 725 | {"filesystems", filesystems_read_proc}, |
587 | {"cmdline", cmdline_read_proc}, | 726 | {"cmdline", cmdline_read_proc}, |
588 | {"locks", locks_read_proc}, | 727 | {"locks", locks_read_proc}, |
@@ -598,6 +737,7 @@ void __init proc_misc_init(void) | |||
598 | entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); | 737 | entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); |
599 | if (entry) | 738 | if (entry) |
600 | entry->proc_fops = &proc_kmsg_operations; | 739 | entry->proc_fops = &proc_kmsg_operations; |
740 | create_seq_entry("devices", 0, &proc_devinfo_operations); | ||
601 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); | 741 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); |
602 | create_seq_entry("partitions", 0, &proc_partitions_operations); | 742 | create_seq_entry("partitions", 0, &proc_partitions_operations); |
603 | create_seq_entry("stat", 0, &proc_stat_operations); | 743 | create_seq_entry("stat", 0, &proc_stat_operations); |