Commit f4a3e0bceb57466c31757f25e4e0ed108d1299ec

Authored by Dr. Werner Fink
Committed by Greg Kroah-Hartman
1 parent a9e2e06015

tty: Add a new file /proc/tty/consoles

Add a new file /proc/tty/consoles to be able to determine the registered
system console lines.  If the reading process holds /dev/console open at
the regular standard input stream the active device will be marked by an
asterisk.  Show possible operations and also decode the used flags of
the listed console lines.

Signed-off-by: Werner Fink <werner@suse.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 190 additions and 0 deletions Side-by-side Diff

Documentation/filesystems/proc.txt
... ... @@ -1075,6 +1075,7 @@
1075 1075 drivers list of drivers and their usage
1076 1076 ldiscs registered line disciplines
1077 1077 driver/serial usage statistic and status of single tty lines
  1078 + consoles registered system console lines
1078 1079 ..............................................................................
1079 1080  
1080 1081 To see which tty's are currently in use, you can simply look into the file
... ... @@ -1092,6 +1093,37 @@
1092 1093 /dev/console /dev/console 5 1 system:console
1093 1094 /dev/tty /dev/tty 5 0 system:/dev/tty
1094 1095 unknown /dev/tty 4 1-63 console
  1096 +
  1097 +To see which character device lines are currently used for the system console
  1098 +/dev/console, you may simply look into the file /proc/tty/consoles:
  1099 +
  1100 + > cat /proc/tty/consoles
  1101 + tty0 -WU (ECp) 4:7
  1102 + ttyS0 -W- (Ep) 4:64
  1103 +
  1104 +The columns are:
  1105 +
  1106 + device name of the device
  1107 + operations R = can do read operations
  1108 + W = can do write operations
  1109 + U = can do unblank
  1110 + flags E = it is enabled
  1111 + C = it is prefered console
  1112 + B = it is primary boot console
  1113 + p = it is used for printk buffer
  1114 + b = it is not a TTY but a Braille device
  1115 + a = it is safe to use when cpu is offline
  1116 + * = it is standard input of the reading process
  1117 + major:minor major and minor number of the device separated by a colon
  1118 +
  1119 +If the reading process holds /dev/console open at the regular standard input
  1120 +stream the active device will be marked by an asterisk:
  1121 +
  1122 + > cat /proc/tty/consoles < /dev/console
  1123 + tty0 -WU (ECp*) 4:7
  1124 + ttyS0 -W- (Ep) 4:64
  1125 + > tty
  1126 + /dev/pts/3
1095 1127  
1096 1128  
1097 1129 1.8 Miscellaneous kernel statistics in /proc/stat
... ... @@ -12,7 +12,10 @@
12 12 #include <linux/proc_fs.h>
13 13 #include <linux/stat.h>
14 14 #include <linux/tty.h>
  15 +#include <linux/tty_driver.h>
  16 +#include <linux/console.h>
15 17 #include <linux/seq_file.h>
  18 +#include <linux/fdtable.h>
16 19 #include <linux/bitops.h>
17 20  
18 21 /*
... ... @@ -137,6 +140,160 @@
137 140 };
138 141  
139 142 /*
  143 + * The device ID of file descriptor 0 of the current reading
  144 + * task if a character device...
  145 + */
  146 +static dev_t current_dev;
  147 +
  148 +/*
  149 + * This is the handler for /proc/tty/consoles
  150 + */
  151 +static int show_console_dev(struct seq_file *m, void *v)
  152 +{
  153 + const struct tty_driver *driver;
  154 + struct console *con;
  155 + int index, len;
  156 + char flags[10];
  157 + dev_t dev;
  158 +
  159 + if (v == SEQ_START_TOKEN)
  160 + return 0;
  161 + con = (struct console *)v;
  162 + if (!con)
  163 + return 0;
  164 + driver = con->device(con, &index);
  165 + if (!driver)
  166 + return 0;
  167 + dev = MKDEV(driver->major, driver->minor_start) + index;
  168 +
  169 + index = 0;
  170 + if (con->flags & CON_ENABLED)
  171 + flags[index++] = 'E';
  172 + if (con->flags & CON_CONSDEV)
  173 + flags[index++] = 'C';
  174 + if (con->flags & CON_BOOT)
  175 + flags[index++] = 'B';
  176 + if (con->flags & CON_PRINTBUFFER)
  177 + flags[index++] = 'p';
  178 + if (con->flags & CON_BRL)
  179 + flags[index++] = 'b';
  180 + if (con->flags & CON_ANYTIME)
  181 + flags[index++] = 'a';
  182 + if (current_dev == dev)
  183 + flags[index++] = '*';
  184 + flags[index] = 0;
  185 +
  186 + seq_printf(m, "%s%d%n", con->name, con->index, &len);
  187 + len = 21 - len;
  188 + if (len < 1)
  189 + len = 1;
  190 + seq_printf(m, "%*c", len, ' ');
  191 + seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-',
  192 + con->write ? 'W' : '-', con->unblank ? 'U' : '-',
  193 + flags, &len);
  194 + len = 13 - len;
  195 + if (len < 1)
  196 + len = 1;
  197 + seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev));
  198 +
  199 + return 0;
  200 +}
  201 +
  202 +/* iterator for consoles */
  203 +static void *c_start(struct seq_file *m, loff_t *pos)
  204 +{
  205 + struct console *con;
  206 + loff_t off = 0;
  207 +
  208 + if (*pos == 0)
  209 + return SEQ_START_TOKEN;
  210 +
  211 + acquire_console_sem();
  212 + for (con = console_drivers; con; con = con->next) {
  213 + if (!con->device)
  214 + continue;
  215 + if (++off == *pos)
  216 + break;
  217 + }
  218 + release_console_sem();
  219 +
  220 + return con;
  221 +}
  222 +
  223 +static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  224 +{
  225 + struct console *con;
  226 +
  227 + acquire_console_sem();
  228 + if (v == SEQ_START_TOKEN)
  229 + con = console_drivers;
  230 + else
  231 + con = ((struct console *)v)->next;
  232 + for (; con; con = con->next) {
  233 + if (!con->device)
  234 + continue;
  235 + ++*pos;
  236 + break;
  237 + }
  238 + release_console_sem();
  239 +
  240 + return con;
  241 +}
  242 +
  243 +static void c_stop(struct seq_file *m, void *v)
  244 +{
  245 +}
  246 +
  247 +static const struct seq_operations tty_consoles_op = {
  248 + .start = c_start,
  249 + .next = c_next,
  250 + .stop = c_stop,
  251 + .show = show_console_dev
  252 +};
  253 +
  254 +/*
  255 + * Used for open /proc/tty/consoles. Before this detect
  256 + * the device ID of file descriptor 0 of the current
  257 + * reading task if a character device...
  258 + */
  259 +static int tty_consoles_open(struct inode *inode, struct file *file)
  260 +{
  261 + struct files_struct *curfiles;
  262 +
  263 + current_dev = 0;
  264 + curfiles = get_files_struct(current);
  265 + if (curfiles) {
  266 + const struct file *curfp;
  267 + spin_lock(&curfiles->file_lock);
  268 + curfp = fcheck_files(curfiles, 0);
  269 + if (curfp && curfp->private_data) {
  270 + const struct inode *inode;
  271 + dget(curfp->f_dentry);
  272 + inode = curfp->f_dentry->d_inode;
  273 + if (S_ISCHR(inode->i_mode)) {
  274 + struct tty_struct *tty;
  275 + tty = (struct tty_struct *)curfp->private_data;
  276 + if (tty && tty->magic == TTY_MAGIC) {
  277 + tty = tty_pair_get_tty(tty);
  278 + current_dev = tty_devnum(tty);
  279 + }
  280 + }
  281 + dput(curfp->f_dentry);
  282 + }
  283 + spin_unlock(&curfiles->file_lock);
  284 + put_files_struct(curfiles);
  285 + }
  286 + return seq_open(file, &tty_consoles_op);
  287 +}
  288 +
  289 +static const struct file_operations proc_tty_consoles_operations = {
  290 + .open = tty_consoles_open,
  291 + .read = seq_read,
  292 + .llseek = seq_lseek,
  293 + .release = seq_release,
  294 +};
  295 +
  296 +/*
140 297 * This function is called by tty_register_driver() to handle
141 298 * registering the driver's /proc handler into /proc/tty/driver/<foo>
142 299 */
... ... @@ -186,5 +343,6 @@
186 343 proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
187 344 proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
188 345 proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
  346 + proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations);
189 347 }