1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/fs.h> 3 #include <linux/init.h> 4 #include <linux/proc_fs.h> 5 #include <linux/seq_file.h> 6 #include <linux/blkdev.h> 7 8 static int devinfo_show(struct seq_file *f, void *v) 9 { 10 int i = *(loff_t *) v; 11 12 if (i < CHRDEV_MAJOR_MAX) { 13 if (i == 0) 14 seq_puts(f, "Character devices:\n"); 15 chrdev_show(f, i); 16 } 17 #ifdef CONFIG_BLOCK 18 else { 19 i -= CHRDEV_MAJOR_MAX; 20 if (i == 0) 21 seq_puts(f, "\nBlock devices:\n"); 22 blkdev_show(f, i); 23 } 24 #endif 25 return 0; 26 } 27 28 static void *devinfo_start(struct seq_file *f, loff_t *pos) 29 { 30 if (*pos < (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX)) 31 return pos; 32 return NULL; 33 } 34 35 static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) 36 { 37 (*pos)++; 38 if (*pos >= (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX)) 39 return NULL; 40 return pos; 41 } 42 43 static void devinfo_stop(struct seq_file *f, void *v) 44 { 45 /* Nothing to do */ 46 } 47 48 static const struct seq_operations devinfo_ops = { 49 .start = devinfo_start, 50 .next = devinfo_next, 51 .stop = devinfo_stop, 52 .show = devinfo_show 53 }; 54 55 static int __init proc_devices_init(void) 56 { 57 proc_create_seq("devices", 0, NULL, &devinfo_ops); 58 return 0; 59 } 60 fs_initcall(proc_devices_init); 61