]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] large dev_t - second series (6/15)
authorAlexander Viro <viro@www.linux.org.uk>
Fri, 5 Sep 2003 03:53:56 +0000 (20:53 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Fri, 5 Sep 2003 03:53:56 +0000 (20:53 -0700)
tty redirect handling sanitized.  Such ttys (/dev/tty and
/dev/console) get a different file_operations; its ->write() handles
redirects; checks for file->f_op == &tty_fops updated, checks for
major:minor being that of a redirector replaced with check for
->f_op->write value.  Piece of code in tty_io.c that had been #if 0
since 0.99<something> had been finally put out of its misery. kdev_val()
is gone.

drivers/char/n_tty.c
drivers/char/tty_io.c
include/linux/kdev_t.h

index 883066efbd729bf088262398a82dc3f213c9376c..6cc938bbbf30ea08e31b7031cf22fce24c877577 100644 (file)
@@ -50,9 +50,6 @@
 #include <asm/system.h>
 #include <asm/bitops.h>
 
-#define IS_CONSOLE_DEV(dev)    (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
-#define IS_SYSCONS_DEV(dev)    (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
-
 /* number of characters left in xmit buffer before select has we have room */
 #define WAKEUP_CHARS 256
 
@@ -951,6 +948,8 @@ static inline int copy_from_read_buf(struct tty_struct *tty,
        return retval;
 }
 
+extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
+
 static ssize_t read_chan(struct tty_struct *tty, struct file *file,
                         unsigned char *buf, size_t nr)
 {
@@ -975,9 +974,7 @@ do_it_again:
        /* NOTE: not yet done after every sleep pending a thorough
           check of the logic of this change. -- jlc */
        /* don't stop on /dev/console */
-       if (!IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
-           !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev) &&
-           current->tty == tty) {
+       if (file->f_op->write != redirected_tty_write && current->tty == tty) {
                if (tty->pgrp <= 0)
                        printk("read_chan: tty->pgrp <= 0!\n");
                else if (current->pgrp != tty->pgrp) {
@@ -1168,9 +1165,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
        ssize_t retval = 0;
 
        /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
-       if (L_TOSTOP(tty) && 
-           !IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
-           !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev)) {
+       if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) {
                retval = tty_check_change(tty);
                if (retval)
                        return retval;
index 83640a923209b905666cc0c613917f84b9ac59c5..a1888c4dc0d9f0562de5654a4aa4b3a72d40d576 100644 (file)
 
 #include <linux/kmod.h>
 
-#define IS_CONSOLE_DEV(dev)    (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
-#define IS_TTY_DEV(dev)                (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0))
-#define IS_SYSCONS_DEV(dev)    (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
-#define IS_PTMX_DEV(dev)       (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2))
-
 #undef TTY_DEBUG_HANGUP
 
 #define TTY_PARANOIA_CHECK 1
@@ -136,6 +131,7 @@ static void initialize_tty_struct(struct tty_struct *tty);
 
 static ssize_t tty_read(struct file *, char *, size_t, loff_t *);
 static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);
+ssize_t redirected_tty_write(struct file *, const char *, size_t, loff_t *);
 static unsigned int tty_poll(struct file *, poll_table *);
 static int tty_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
@@ -382,6 +378,17 @@ static struct file_operations tty_fops = {
        .fasync         = tty_fasync,
 };
 
+static struct file_operations console_fops = {
+       .llseek         = no_llseek,
+       .read           = tty_read,
+       .write          = redirected_tty_write,
+       .poll           = tty_poll,
+       .ioctl          = tty_ioctl,
+       .open           = tty_open,
+       .release        = tty_release,
+       .fasync         = tty_fasync,
+};
+
 static struct file_operations hung_up_tty_fops = {
        .llseek         = no_llseek,
        .read           = hung_up_tty_read,
@@ -425,12 +432,9 @@ void do_tty_hangup(void *data)
        check_tty_count(tty, "do_tty_hangup");
        file_list_lock();
        list_for_each_entry(filp, &tty->tty_files, f_list) {
-               if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) ||
-                   IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) {
+               if (filp->f_op->write == redirected_tty_write)
                        cons_filp = filp;
-                       continue;
-               }
-               if (filp->f_op != &tty_fops)
+               if (filp->f_op->write != tty_write)
                        continue;
                closecount++;
                tty_fasync(-1, filp, 0);        /* can't block */
@@ -650,22 +654,6 @@ static ssize_t tty_read(struct file * file, char * buf, size_t count,
        if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
                return -EIO;
 
-       /* This check not only needs to be done before reading, but also
-          whenever read_chan() gets woken up after sleeping, so I've
-          moved it to there.  This should only be done for the N_TTY
-          line discipline, anyway.  Same goes for write_chan(). -- jlc. */
-#if 0
-       if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */
-           (tty->pgrp > 0) &&
-           (current->tty == tty) &&
-           (tty->pgrp != current->pgrp))
-               if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
-                       return -EIO;
-               else {
-                       (void) kill_pg(current->pgrp, SIGTTIN, 1);
-                       return -ERESTARTSYS;
-               }
-#endif
        lock_kernel();
        if (tty->ldisc.read)
                i = (tty->ldisc.read)(tty,file,buf,count);
@@ -730,37 +718,13 @@ static inline ssize_t do_tty_write(
 static ssize_t tty_write(struct file * file, const char * buf, size_t count,
                         loff_t *ppos)
 {
-       int is_console;
        struct tty_struct * tty;
        struct inode *inode = file->f_dentry->d_inode;
-       /*
-        *      For now, we redirect writes from /dev/console as
-        *      well as /dev/tty0.
-        */
-       is_console = IS_SYSCONS_DEV(inode->i_rdev) ||
-                    IS_CONSOLE_DEV(inode->i_rdev);
 
        /* Can't seek (pwrite) on ttys.  */
        if (ppos != &file->f_pos)
                return -ESPIPE;
 
-       if (is_console) {
-               struct file *p = NULL;
-
-               spin_lock(&redirect_lock);
-               if (redirect) {
-                       get_file(redirect);
-                       p = redirect;
-               }
-               spin_unlock(&redirect_lock);
-
-               if (p) {
-                       ssize_t res = vfs_write(p, buf, count, &p->f_pos);
-                       fput(p);
-                       return res;
-               }
-       }
-
        tty = (struct tty_struct *)file->private_data;
        if (tty_paranoia_check(tty, inode, "tty_write"))
                return -EIO;
@@ -772,6 +736,31 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count,
                            (const unsigned char *)buf, count);
 }
 
+ssize_t redirected_tty_write(struct file * file, const char * buf, size_t count,
+                        loff_t *ppos)
+{
+       struct file *p = NULL;
+
+       spin_lock(&redirect_lock);
+       if (redirect) {
+               get_file(redirect);
+               p = redirect;
+       }
+       spin_unlock(&redirect_lock);
+
+       if (p) {
+               ssize_t res;
+               /* Can't seek (pwrite) on ttys.  */
+               if (ppos != &file->f_pos)
+                       return -ESPIPE;
+               res = vfs_write(p, buf, count, &p->f_pos);
+               fput(p);
+               return res;
+       }
+
+       return tty_write(file, buf, count, ppos);
+}
+
 /* Semaphore to protect creating and releasing a tty */
 static DECLARE_MUTEX(tty_sem);
 
@@ -1306,14 +1295,11 @@ static int tty_open(struct inode * inode, struct file * filp)
        int noctty, retval;
        struct tty_driver *driver;
        int index;
-       kdev_t device;
-       unsigned short saved_flags;
-
-       saved_flags = filp->f_flags;
+       dev_t device = kdev_t_to_nr(inode->i_rdev);
+       unsigned short saved_flags = filp->f_flags;
 retry_open:
        noctty = filp->f_flags & O_NOCTTY;
-       device = inode->i_rdev;
-       if (IS_TTY_DEV(device)) {
+       if (device == MKDEV(TTYAUX_MAJOR,0)) {
                if (!current->tty)
                        return -ENXIO;
                driver = current->tty->driver;
@@ -1323,7 +1309,7 @@ retry_open:
                goto got_driver;
        }
 #ifdef CONFIG_VT
-       if (IS_CONSOLE_DEV(device)) {
+       if (device == MKDEV(TTY_MAJOR,0)) {
                extern int fg_console;
                extern struct tty_driver *console_driver;
                driver = console_driver;
@@ -1332,7 +1318,7 @@ retry_open:
                goto got_driver;
        }
 #endif
-       if (IS_SYSCONS_DEV(device)) {
+       if (device == MKDEV(TTYAUX_MAJOR,1)) {
                struct console *c = console_drivers;
                for (c = console_drivers; c; c = c->next) {
                        if (!c->device)
@@ -1348,7 +1334,7 @@ retry_open:
                return -ENODEV;
        }
 
-       if (IS_PTMX_DEV(device)) {
+       if (device == MKDEV(TTYAUX_MAJOR,2)) {
 #ifdef CONFIG_UNIX98_PTYS
                /* find a device that is not in use. */
                retval = -1;
@@ -1365,7 +1351,7 @@ retry_open:
                return -ENODEV;
 #endif  /* CONFIG_UNIX_98_PTYS */
        } else {
-               driver = get_tty_driver(kdev_t_to_nr(device), &index);
+               driver = get_tty_driver(device, &index);
                if (!driver)
                        return -ENODEV;
 got_driver:
@@ -1407,7 +1393,8 @@ got_driver:
                /*
                 * Need to reset f_op in case a hangup happened.
                 */
-               filp->f_op = &tty_fops;
+               if (filp->f_op == &hung_up_tty_fops)
+                       filp->f_op = &tty_fops;
                goto retry_open;
        }
        if (!noctty &&
@@ -1516,10 +1503,9 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
        return 0;
 }
 
-static int tioccons(struct inode *inode, struct file *file)
+static int tioccons(struct file *file)
 {
-       if (IS_SYSCONS_DEV(inode->i_rdev) ||
-           IS_CONSOLE_DEV(inode->i_rdev)) {
+       if (file->f_op->write == redirected_tty_write) {
                struct file *f;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
@@ -1786,7 +1772,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
                case TIOCSWINSZ:
                        return tiocswinsz(tty, real_tty, (struct winsize *) arg);
                case TIOCCONS:
-                       return real_tty!=tty ? -EINVAL : tioccons(inode, file);
+                       return real_tty!=tty ? -EINVAL : tioccons(file);
                case FIONBIO:
                        return fionbio(file, (int *) arg);
                case TIOCEXCL:
@@ -1917,8 +1903,10 @@ static void __do_SAK(void *arg)
                        spin_lock(&p->files->file_lock);
                        for (i=0; i < p->files->max_fds; i++) {
                                filp = fcheck_files(p->files, i);
-                               if (filp && (filp->f_op == &tty_fops) &&
-                                   (filp->private_data == tty)) {
+                               if (!filp)
+                                       continue;
+                               if (filp->f_op->read == tty_read &&
+                                   filp->private_data == tty) {
                                        printk(KERN_NOTICE "SAK: killed process %d"
                                            " (%s): fd#%d opened to the tty\n",
                                            p->pid, p->comm, i);
@@ -2446,7 +2434,7 @@ void __init tty_init(void)
        tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
 
        strcpy(console_cdev.kobj.name, "dev.console");
-       cdev_init(&console_cdev, &tty_fops);
+       cdev_init(&console_cdev, &console_fops);
        if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
                panic("Couldn't register /dev/console driver\n");
@@ -2468,7 +2456,7 @@ void __init tty_init(void)
        
 #ifdef CONFIG_VT
        strcpy(vc0_cdev.kobj.name, "dev.vc0");
-       cdev_init(&vc0_cdev, &tty_fops);
+       cdev_init(&vc0_cdev, &console_fops);
        if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
            register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
                panic("Couldn't register /dev/tty0 driver\n");
index 900a4a1e1282aa52287c80ff8354eec5f82e1ba5..64a88b3b194a92e7604fab4f0c9127843ae69397 100644 (file)
@@ -80,16 +80,6 @@ typedef struct {
 
 #define mk_kdev(major, minor)  ((kdev_t) { __mkdev(major,minor) } )
 
-/*
- * The "values" are just _cookies_, usable for 
- * internal equality comparisons and for things
- * like NFS filehandle conversion.
- */
-static inline unsigned int kdev_val(kdev_t dev)
-{
-       return dev.value;
-}
-
 #define NODEV          (mk_kdev(0,0))
 
 /* Mask off the high bits for now.. */