summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-04-25 23:04:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-04-26 18:47:32 -0400
commit8ead9dd54716d1e05e129959f702fcc1786f82b4 (patch)
treea31bb92dab97a482390b515e91fd29e80b3a3004
parentbcc981e9ed84c678533299d7eff17d2c81e4d5de (diff)
devpts: more pty driver interface cleanups
This is more prep-work for the upcoming pty changes. Still just code cleanup with no actual semantic changes. This removes a bunch pointless complexity by just having the slave pty side remember the dentry associated with the devpts slave rather than the inode. That allows us to remove all the "look up the dentry" code for when we want to remove it again. Together with moving the tty pointer from "inode->i_private" to "dentry->d_fsdata" and getting rid of pointless inode locking, this removes about 30 lines of code. Not only is the end result smaller, it's simpler and easier to understand. The old code, for example, depended on the d_find_alias() to not just find the dentry, but also to check that it is still hashed, which in turn validated the tty pointer in the inode. That is a _very_ roundabout way to say "invalidate the cached tty pointer when the dentry is removed". The new code just does dentry->d_fsdata = NULL; in devpts_pty_kill() instead, invalidating the tty pointer rather more directly and obviously. Don't do something complex and subtle when the obvious straightforward approach will do. The rest of the patch (ie apart from code deletion and the above tty pointer clearing) is just switching the calling convention to pass the dentry or file pointer around instead of the inode. Cc: Eric Biederman <ebiederm@xmission.com> Cc: Peter Anvin <hpa@zytor.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Peter Hurley <peter@hurleysoftware.com> Cc: Serge Hallyn <serge.hallyn@ubuntu.com> Cc: Willy Tarreau <w@1wt.eu> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk> Cc: Jann Horn <jann@thejh.net> Cc: Greg KH <greg@kroah.com> Cc: Jiri Slaby <jslaby@suse.com> Cc: Florian Weimer <fw@deneb.enyo.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/tty/pty.c18
-rw-r--r--drivers/tty/tty_io.c6
-rw-r--r--fs/devpts/inode.c53
-rw-r--r--include/linux/devpts_fs.h6
-rw-r--r--include/linux/tty_driver.h4
5 files changed, 28 insertions, 59 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 0058d9fbf931..cf0dc51a2690 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -626,7 +626,7 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
626 */ 626 */
627 627
628static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, 628static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
629 struct inode *ptm_inode, int idx) 629 struct file *file, int idx)
630{ 630{
631 /* Master must be open via /dev/ptmx */ 631 /* Master must be open via /dev/ptmx */
632 return ERR_PTR(-EIO); 632 return ERR_PTR(-EIO);
@@ -642,12 +642,12 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
642 */ 642 */
643 643
644static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, 644static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
645 struct inode *pts_inode, int idx) 645 struct file *file, int idx)
646{ 646{
647 struct tty_struct *tty; 647 struct tty_struct *tty;
648 648
649 mutex_lock(&devpts_mutex); 649 mutex_lock(&devpts_mutex);
650 tty = devpts_get_priv(pts_inode); 650 tty = devpts_get_priv(file->f_path.dentry);
651 mutex_unlock(&devpts_mutex); 651 mutex_unlock(&devpts_mutex);
652 /* Master must be open before slave */ 652 /* Master must be open before slave */
653 if (!tty) 653 if (!tty)
@@ -722,7 +722,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
722{ 722{
723 struct pts_fs_info *fsi; 723 struct pts_fs_info *fsi;
724 struct tty_struct *tty; 724 struct tty_struct *tty;
725 struct inode *slave_inode; 725 struct dentry *dentry;
726 int retval; 726 int retval;
727 int index; 727 int index;
728 728
@@ -769,14 +769,12 @@ static int ptmx_open(struct inode *inode, struct file *filp)
769 769
770 tty_add_file(tty, filp); 770 tty_add_file(tty, filp);
771 771
772 slave_inode = devpts_pty_new(fsi, 772 dentry = devpts_pty_new(fsi, index, tty->link);
773 MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index, 773 if (IS_ERR(dentry)) {
774 tty->link); 774 retval = PTR_ERR(dentry);
775 if (IS_ERR(slave_inode)) {
776 retval = PTR_ERR(slave_inode);
777 goto err_release; 775 goto err_release;
778 } 776 }
779 tty->link->driver_data = slave_inode; 777 tty->link->driver_data = dentry;
780 778
781 retval = ptm_driver->ops->open(tty, filp); 779 retval = ptm_driver->ops->open(tty, filp);
782 if (retval) 780 if (retval)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 9b04d72e752e..24d5491ef0da 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1367,12 +1367,12 @@ static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
1367 * Locking: tty_mutex must be held. If the tty is found, bump the tty kref. 1367 * Locking: tty_mutex must be held. If the tty is found, bump the tty kref.
1368 */ 1368 */
1369static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, 1369static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
1370 struct inode *inode, int idx) 1370 struct file *file, int idx)
1371{ 1371{
1372 struct tty_struct *tty; 1372 struct tty_struct *tty;
1373 1373
1374 if (driver->ops->lookup) 1374 if (driver->ops->lookup)
1375 tty = driver->ops->lookup(driver, inode, idx); 1375 tty = driver->ops->lookup(driver, file, idx);
1376 else 1376 else
1377 tty = driver->ttys[idx]; 1377 tty = driver->ttys[idx];
1378 1378
@@ -2040,7 +2040,7 @@ static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
2040 } 2040 }
2041 2041
2042 /* check whether we're reopening an existing tty */ 2042 /* check whether we're reopening an existing tty */
2043 tty = tty_driver_lookup_tty(driver, inode, index); 2043 tty = tty_driver_lookup_tty(driver, filp, index);
2044 if (IS_ERR(tty)) { 2044 if (IS_ERR(tty)) {
2045 mutex_unlock(&tty_mutex); 2045 mutex_unlock(&tty_mutex);
2046 goto out; 2046 goto out;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 0af8e7d70d27..0b2954d7172d 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -604,8 +604,7 @@ void devpts_put_ref(struct pts_fs_info *fsi)
604 * 604 *
605 * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill. 605 * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
606 */ 606 */
607struct inode *devpts_pty_new(struct pts_fs_info *fsi, dev_t device, int index, 607struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
608 void *priv)
609{ 608{
610 struct dentry *dentry; 609 struct dentry *dentry;
611 struct super_block *sb; 610 struct super_block *sb;
@@ -629,25 +628,21 @@ struct inode *devpts_pty_new(struct pts_fs_info *fsi, dev_t device, int index,
629 inode->i_uid = opts->setuid ? opts->uid : current_fsuid(); 628 inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
630 inode->i_gid = opts->setgid ? opts->gid : current_fsgid(); 629 inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
631 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 630 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
632 init_special_inode(inode, S_IFCHR|opts->mode, device); 631 init_special_inode(inode, S_IFCHR|opts->mode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index));
633 inode->i_private = priv;
634 632
635 sprintf(s, "%d", index); 633 sprintf(s, "%d", index);
636 634
637 inode_lock(d_inode(root));
638
639 dentry = d_alloc_name(root, s); 635 dentry = d_alloc_name(root, s);
640 if (dentry) { 636 if (dentry) {
637 dentry->d_fsdata = priv;
641 d_add(dentry, inode); 638 d_add(dentry, inode);
642 fsnotify_create(d_inode(root), dentry); 639 fsnotify_create(d_inode(root), dentry);
643 } else { 640 } else {
644 iput(inode); 641 iput(inode);
645 inode = ERR_PTR(-ENOMEM); 642 dentry = ERR_PTR(-ENOMEM);
646 } 643 }
647 644
648 inode_unlock(d_inode(root)); 645 return dentry;
649
650 return inode;
651} 646}
652 647
653/** 648/**
@@ -656,24 +651,10 @@ struct inode *devpts_pty_new(struct pts_fs_info *fsi, dev_t device, int index,
656 * 651 *
657 * Returns whatever was passed as priv in devpts_pty_new for a given inode. 652 * Returns whatever was passed as priv in devpts_pty_new for a given inode.
658 */ 653 */
659void *devpts_get_priv(struct inode *pts_inode) 654void *devpts_get_priv(struct dentry *dentry)
660{ 655{
661 struct dentry *dentry; 656 WARN_ON_ONCE(dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC);
662 void *priv = NULL; 657 return dentry->d_fsdata;
663
664 BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
665
666 /* Ensure dentry has not been deleted by devpts_pty_kill() */
667 dentry = d_find_alias(pts_inode);
668 if (!dentry)
669 return NULL;
670
671 if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
672 priv = pts_inode->i_private;
673
674 dput(dentry);
675
676 return priv;
677} 658}
678 659
679/** 660/**
@@ -682,24 +663,14 @@ void *devpts_get_priv(struct inode *pts_inode)
682 * 663 *
683 * This is an inverse operation of devpts_pty_new. 664 * This is an inverse operation of devpts_pty_new.
684 */ 665 */
685void devpts_pty_kill(struct inode *inode) 666void devpts_pty_kill(struct dentry *dentry)
686{ 667{
687 struct super_block *sb = pts_sb_from_inode(inode); 668 WARN_ON_ONCE(dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC);
688 struct dentry *root = sb->s_root;
689 struct dentry *dentry;
690 669
691 BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); 670 dentry->d_fsdata = NULL;
692 671 drop_nlink(dentry->d_inode);
693 inode_lock(d_inode(root));
694
695 dentry = d_find_alias(inode);
696
697 drop_nlink(inode);
698 d_delete(dentry); 672 d_delete(dentry);
699 dput(dentry); /* d_alloc_name() in devpts_pty_new() */ 673 dput(dentry); /* d_alloc_name() in devpts_pty_new() */
700 dput(dentry); /* d_find_alias above */
701
702 inode_unlock(d_inode(root));
703} 674}
704 675
705static int __init init_devpts_fs(void) 676static int __init init_devpts_fs(void)
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index 358a4db72a27..5871f292b596 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -27,11 +27,11 @@ int devpts_new_index(struct pts_fs_info *);
27void devpts_kill_index(struct pts_fs_info *, int); 27void devpts_kill_index(struct pts_fs_info *, int);
28 28
29/* mknod in devpts */ 29/* mknod in devpts */
30struct inode *devpts_pty_new(struct pts_fs_info *, dev_t, int, void *); 30struct dentry *devpts_pty_new(struct pts_fs_info *, int, void *);
31/* get private structure */ 31/* get private structure */
32void *devpts_get_priv(struct inode *pts_inode); 32void *devpts_get_priv(struct dentry *);
33/* unlink */ 33/* unlink */
34void devpts_pty_kill(struct inode *inode); 34void devpts_pty_kill(struct dentry *);
35 35
36#endif 36#endif
37 37
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 161052477f77..b742b5e47cc2 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -7,7 +7,7 @@
7 * defined; unless noted otherwise, they are optional, and can be 7 * defined; unless noted otherwise, they are optional, and can be
8 * filled in with a null pointer. 8 * filled in with a null pointer.
9 * 9 *
10 * struct tty_struct * (*lookup)(struct tty_driver *self, int idx) 10 * struct tty_struct * (*lookup)(struct tty_driver *self, struct file *, int idx)
11 * 11 *
12 * Return the tty device corresponding to idx, NULL if there is not 12 * Return the tty device corresponding to idx, NULL if there is not
13 * one currently in use and an ERR_PTR value on error. Called under 13 * one currently in use and an ERR_PTR value on error. Called under
@@ -250,7 +250,7 @@ struct serial_icounter_struct;
250 250
251struct tty_operations { 251struct tty_operations {
252 struct tty_struct * (*lookup)(struct tty_driver *driver, 252 struct tty_struct * (*lookup)(struct tty_driver *driver,
253 struct inode *inode, int idx); 253 struct file *filp, int idx);
254 int (*install)(struct tty_driver *driver, struct tty_struct *tty); 254 int (*install)(struct tty_driver *driver, struct tty_struct *tty);
255 void (*remove)(struct tty_driver *driver, struct tty_struct *tty); 255 void (*remove)(struct tty_driver *driver, struct tty_struct *tty);
256 int (*open)(struct tty_struct * tty, struct file * filp); 256 int (*open)(struct tty_struct * tty, struct file * filp);