|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/time.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/kernel_stat.h>
|
|
|
+#include <linux/fs.h>
|
|
|
#include <linux/tty.h>
|
|
|
#include <linux/string.h>
|
|
|
#include <linux/mman.h>
|
|
@@ -62,7 +63,6 @@
|
|
|
*/
|
|
|
extern int get_hardware_list(char *);
|
|
|
extern int get_stram_list(char *);
|
|
|
-extern int get_chrdev_list(char *);
|
|
|
extern int get_filesystem_list(char *);
|
|
|
extern int get_exec_domain_list(char *);
|
|
|
extern int get_dma_list(char *);
|
|
@@ -248,6 +248,154 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
return seq_open(file, &cpuinfo_op);
|
|
|
}
|
|
|
+
|
|
|
+enum devinfo_states {
|
|
|
+ CHR_HDR,
|
|
|
+ CHR_LIST,
|
|
|
+ BLK_HDR,
|
|
|
+ BLK_LIST,
|
|
|
+ DEVINFO_DONE
|
|
|
+};
|
|
|
+
|
|
|
+struct devinfo_state {
|
|
|
+ void *chrdev;
|
|
|
+ void *blkdev;
|
|
|
+ unsigned int num_records;
|
|
|
+ unsigned int cur_record;
|
|
|
+ enum devinfo_states state;
|
|
|
+};
|
|
|
+
|
|
|
+static void *devinfo_start(struct seq_file *f, loff_t *pos)
|
|
|
+{
|
|
|
+ struct devinfo_state *info = f->private;
|
|
|
+
|
|
|
+ if (*pos) {
|
|
|
+ if ((info) && (*pos <= info->num_records))
|
|
|
+ return info;
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
|
|
|
+ f->private = info;
|
|
|
+ info->chrdev = acquire_chrdev_list();
|
|
|
+ info->blkdev = acquire_blkdev_list();
|
|
|
+ info->state = CHR_HDR;
|
|
|
+ info->num_records = count_chrdev_list();
|
|
|
+ info->num_records += count_blkdev_list();
|
|
|
+ info->num_records += 2; /* Character and Block headers */
|
|
|
+ *pos = 1;
|
|
|
+ info->cur_record = *pos;
|
|
|
+ return info;
|
|
|
+}
|
|
|
+
|
|
|
+static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
|
|
|
+{
|
|
|
+ int idummy;
|
|
|
+ char *ndummy;
|
|
|
+ struct devinfo_state *info = f->private;
|
|
|
+
|
|
|
+ switch (info->state) {
|
|
|
+ case CHR_HDR:
|
|
|
+ info->state = CHR_LIST;
|
|
|
+ (*pos)++;
|
|
|
+ /*fallthrough*/
|
|
|
+ case CHR_LIST:
|
|
|
+ if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
|
|
|
+ /*
|
|
|
+ * The character dev list is complete
|
|
|
+ */
|
|
|
+ info->state = BLK_HDR;
|
|
|
+ } else {
|
|
|
+ info->chrdev = get_next_chrdev(info->chrdev);
|
|
|
+ }
|
|
|
+ (*pos)++;
|
|
|
+ break;
|
|
|
+ case BLK_HDR:
|
|
|
+ info->state = BLK_LIST;
|
|
|
+ (*pos)++;
|
|
|
+ break;
|
|
|
+ case BLK_LIST:
|
|
|
+ if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
|
|
|
+ /*
|
|
|
+ * The block dev list is complete
|
|
|
+ */
|
|
|
+ info->state = DEVINFO_DONE;
|
|
|
+ } else {
|
|
|
+ info->blkdev = get_next_blkdev(info->blkdev);
|
|
|
+ }
|
|
|
+ (*pos)++;
|
|
|
+ break;
|
|
|
+ case DEVINFO_DONE:
|
|
|
+ (*pos)++;
|
|
|
+ info->cur_record = *pos;
|
|
|
+ info = NULL;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (info)
|
|
|
+ info->cur_record = *pos;
|
|
|
+ return info;
|
|
|
+}
|
|
|
+
|
|
|
+static void devinfo_stop(struct seq_file *f, void *v)
|
|
|
+{
|
|
|
+ struct devinfo_state *info = f->private;
|
|
|
+
|
|
|
+ if (info) {
|
|
|
+ release_chrdev_list(info->chrdev);
|
|
|
+ release_blkdev_list(info->blkdev);
|
|
|
+ f->private = NULL;
|
|
|
+ kfree(info);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int devinfo_show(struct seq_file *f, void *arg)
|
|
|
+{
|
|
|
+ int major;
|
|
|
+ char *name;
|
|
|
+ struct devinfo_state *info = f->private;
|
|
|
+
|
|
|
+ switch(info->state) {
|
|
|
+ case CHR_HDR:
|
|
|
+ seq_printf(f,"Character devices:\n");
|
|
|
+ /* fallthrough */
|
|
|
+ case CHR_LIST:
|
|
|
+ if (!get_chrdev_info(info->chrdev,&major,&name))
|
|
|
+ seq_printf(f,"%3d %s\n",major,name);
|
|
|
+ break;
|
|
|
+ case BLK_HDR:
|
|
|
+ seq_printf(f,"\nBlock devices:\n");
|
|
|
+ /* fallthrough */
|
|
|
+ case BLK_LIST:
|
|
|
+ if (!get_blkdev_info(info->blkdev,&major,&name))
|
|
|
+ seq_printf(f,"%3d %s\n",major,name);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct seq_operations devinfo_op = {
|
|
|
+ .start = devinfo_start,
|
|
|
+ .next = devinfo_next,
|
|
|
+ .stop = devinfo_stop,
|
|
|
+ .show = devinfo_show,
|
|
|
+};
|
|
|
+
|
|
|
+static int devinfo_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ return seq_open(file, &devinfo_op);
|
|
|
+}
|
|
|
+
|
|
|
+static struct file_operations proc_devinfo_operations = {
|
|
|
+ .open = devinfo_open,
|
|
|
+ .read = seq_read,
|
|
|
+ .llseek = seq_lseek,
|
|
|
+ .release = seq_release,
|
|
|
+};
|
|
|
+
|
|
|
static struct file_operations proc_cpuinfo_operations = {
|
|
|
.open = cpuinfo_open,
|
|
|
.read = seq_read,
|
|
@@ -450,14 +598,6 @@ static struct file_operations proc_stat_operations = {
|
|
|
.release = single_release,
|
|
|
};
|
|
|
|
|
|
-static int devices_read_proc(char *page, char **start, off_t off,
|
|
|
- int count, int *eof, void *data)
|
|
|
-{
|
|
|
- int len = get_chrdev_list(page);
|
|
|
- len += get_blkdev_list(page+len, len);
|
|
|
- return proc_calc_metrics(page, start, off, count, eof, len);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* /proc/interrupts
|
|
|
*/
|
|
@@ -582,7 +722,6 @@ void __init proc_misc_init(void)
|
|
|
#ifdef CONFIG_STRAM_PROC
|
|
|
{"stram", stram_read_proc},
|
|
|
#endif
|
|
|
- {"devices", devices_read_proc},
|
|
|
{"filesystems", filesystems_read_proc},
|
|
|
{"cmdline", cmdline_read_proc},
|
|
|
{"locks", locks_read_proc},
|
|
@@ -598,6 +737,7 @@ void __init proc_misc_init(void)
|
|
|
entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
|
|
|
if (entry)
|
|
|
entry->proc_fops = &proc_kmsg_operations;
|
|
|
+ create_seq_entry("devices", 0, &proc_devinfo_operations);
|
|
|
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
|
|
|
create_seq_entry("partitions", 0, &proc_partitions_operations);
|
|
|
create_seq_entry("stat", 0, &proc_stat_operations);
|