aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-02-12 03:53:00 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:32 -0500
commitab521dc0f8e117fd808d3e425216864d60390500 (patch)
treef9d6449c4d8c9508fd43edfe845108043e1536b2 /drivers/char/tty_io.c
parent3e7cd6c413c9e6fbb5e1ee2acdadb4ababd2d474 (diff)
[PATCH] tty: update the tty layer to work with struct pid
Of kernel subsystems that work with pids the tty layer is probably the largest consumer. But it has the nice virtue that the assiation with a session only lasts until the session leader exits. Which means that no reference counting is required. So using struct pid winds up being a simple optimization to avoid hash table lookups. In the long term the use of pid_nr also ensures that when we have multiple pid spaces mixed everything will work correctly. Signed-off-by: Eric W. Biederman <eric@maxwell.lnxi.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c130
1 files changed, 79 insertions, 51 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 94070f7bf38..65672c57470 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -155,7 +155,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
155 unsigned int cmd, unsigned long arg); 155 unsigned int cmd, unsigned long arg);
156static int tty_fasync(int fd, struct file * filp, int on); 156static int tty_fasync(int fd, struct file * filp, int on);
157static void release_tty(struct tty_struct *tty, int idx); 157static void release_tty(struct tty_struct *tty, int idx);
158static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); 158static struct pid *__proc_set_tty(struct task_struct *tsk,
159 struct tty_struct *tty);
159 160
160/** 161/**
161 * alloc_tty_struct - allocate a tty object 162 * alloc_tty_struct - allocate a tty object
@@ -1110,17 +1111,17 @@ int tty_check_change(struct tty_struct * tty)
1110{ 1111{
1111 if (current->signal->tty != tty) 1112 if (current->signal->tty != tty)
1112 return 0; 1113 return 0;
1113 if (tty->pgrp <= 0) { 1114 if (!tty->pgrp) {
1114 printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); 1115 printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
1115 return 0; 1116 return 0;
1116 } 1117 }
1117 if (process_group(current) == tty->pgrp) 1118 if (task_pgrp(current) == tty->pgrp)
1118 return 0; 1119 return 0;
1119 if (is_ignored(SIGTTOU)) 1120 if (is_ignored(SIGTTOU))
1120 return 0; 1121 return 0;
1121 if (is_current_pgrp_orphaned()) 1122 if (is_current_pgrp_orphaned())
1122 return -EIO; 1123 return -EIO;
1123 (void) kill_pg(process_group(current), SIGTTOU, 1); 1124 (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
1124 return -ERESTARTSYS; 1125 return -ERESTARTSYS;
1125} 1126}
1126 1127
@@ -1355,8 +1356,8 @@ static void do_tty_hangup(struct work_struct *work)
1355 tty_release is called */ 1356 tty_release is called */
1356 1357
1357 read_lock(&tasklist_lock); 1358 read_lock(&tasklist_lock);
1358 if (tty->session > 0) { 1359 if (tty->session) {
1359 do_each_task_pid(tty->session, PIDTYPE_SID, p) { 1360 do_each_pid_task(tty->session, PIDTYPE_SID, p) {
1360 spin_lock_irq(&p->sighand->siglock); 1361 spin_lock_irq(&p->sighand->siglock);
1361 if (p->signal->tty == tty) 1362 if (p->signal->tty == tty)
1362 p->signal->tty = NULL; 1363 p->signal->tty = NULL;
@@ -1366,16 +1367,17 @@ static void do_tty_hangup(struct work_struct *work)
1366 } 1367 }
1367 __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); 1368 __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
1368 __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); 1369 __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
1369 if (tty->pgrp > 0) 1370 put_pid(p->signal->tty_old_pgrp); /* A noop */
1370 p->signal->tty_old_pgrp = tty->pgrp; 1371 if (tty->pgrp)
1372 p->signal->tty_old_pgrp = get_pid(tty->pgrp);
1371 spin_unlock_irq(&p->sighand->siglock); 1373 spin_unlock_irq(&p->sighand->siglock);
1372 } while_each_task_pid(tty->session, PIDTYPE_SID, p); 1374 } while_each_pid_task(tty->session, PIDTYPE_SID, p);
1373 } 1375 }
1374 read_unlock(&tasklist_lock); 1376 read_unlock(&tasklist_lock);
1375 1377
1376 tty->flags = 0; 1378 tty->flags = 0;
1377 tty->session = 0; 1379 tty->session = NULL;
1378 tty->pgrp = -1; 1380 tty->pgrp = NULL;
1379 tty->ctrl_status = 0; 1381 tty->ctrl_status = 0;
1380 /* 1382 /*
1381 * If one of the devices matches a console pointer, we 1383 * If one of the devices matches a console pointer, we
@@ -1460,12 +1462,12 @@ int tty_hung_up_p(struct file * filp)
1460 1462
1461EXPORT_SYMBOL(tty_hung_up_p); 1463EXPORT_SYMBOL(tty_hung_up_p);
1462 1464
1463static void session_clear_tty(pid_t session) 1465static void session_clear_tty(struct pid *session)
1464{ 1466{
1465 struct task_struct *p; 1467 struct task_struct *p;
1466 do_each_task_pid(session, PIDTYPE_SID, p) { 1468 do_each_pid_task(session, PIDTYPE_SID, p) {
1467 proc_clear_tty(p); 1469 proc_clear_tty(p);
1468 } while_each_task_pid(session, PIDTYPE_SID, p); 1470 } while_each_pid_task(session, PIDTYPE_SID, p);
1469} 1471}
1470 1472
1471/** 1473/**
@@ -1495,48 +1497,54 @@ static void session_clear_tty(pid_t session)
1495void disassociate_ctty(int on_exit) 1497void disassociate_ctty(int on_exit)
1496{ 1498{
1497 struct tty_struct *tty; 1499 struct tty_struct *tty;
1498 int tty_pgrp = -1; 1500 struct pid *tty_pgrp = NULL;
1499 1501
1500 lock_kernel(); 1502 lock_kernel();
1501 1503
1502 mutex_lock(&tty_mutex); 1504 mutex_lock(&tty_mutex);
1503 tty = get_current_tty(); 1505 tty = get_current_tty();
1504 if (tty) { 1506 if (tty) {
1505 tty_pgrp = tty->pgrp; 1507 tty_pgrp = get_pid(tty->pgrp);
1506 mutex_unlock(&tty_mutex); 1508 mutex_unlock(&tty_mutex);
1507 /* XXX: here we race, there is nothing protecting tty */ 1509 /* XXX: here we race, there is nothing protecting tty */
1508 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) 1510 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
1509 tty_vhangup(tty); 1511 tty_vhangup(tty);
1510 } else if (on_exit) { 1512 } else if (on_exit) {
1511 pid_t old_pgrp; 1513 struct pid *old_pgrp;
1512 spin_lock_irq(&current->sighand->siglock); 1514 spin_lock_irq(&current->sighand->siglock);
1513 old_pgrp = current->signal->tty_old_pgrp; 1515 old_pgrp = current->signal->tty_old_pgrp;
1514 current->signal->tty_old_pgrp = 0; 1516 current->signal->tty_old_pgrp = NULL;
1515 spin_unlock_irq(&current->sighand->siglock); 1517 spin_unlock_irq(&current->sighand->siglock);
1516 if (old_pgrp) { 1518 if (old_pgrp) {
1517 kill_pg(old_pgrp, SIGHUP, on_exit); 1519 kill_pgrp(old_pgrp, SIGHUP, on_exit);
1518 kill_pg(old_pgrp, SIGCONT, on_exit); 1520 kill_pgrp(old_pgrp, SIGCONT, on_exit);
1521 put_pid(old_pgrp);
1519 } 1522 }
1520 mutex_unlock(&tty_mutex); 1523 mutex_unlock(&tty_mutex);
1521 unlock_kernel(); 1524 unlock_kernel();
1522 return; 1525 return;
1523 } 1526 }
1524 if (tty_pgrp > 0) { 1527 if (tty_pgrp) {
1525 kill_pg(tty_pgrp, SIGHUP, on_exit); 1528 kill_pgrp(tty_pgrp, SIGHUP, on_exit);
1526 if (!on_exit) 1529 if (!on_exit)
1527 kill_pg(tty_pgrp, SIGCONT, on_exit); 1530 kill_pgrp(tty_pgrp, SIGCONT, on_exit);
1531 put_pid(tty_pgrp);
1528 } 1532 }
1529 1533
1530 spin_lock_irq(&current->sighand->siglock); 1534 spin_lock_irq(&current->sighand->siglock);
1535 tty_pgrp = current->signal->tty_old_pgrp;
1531 current->signal->tty_old_pgrp = 0; 1536 current->signal->tty_old_pgrp = 0;
1532 spin_unlock_irq(&current->sighand->siglock); 1537 spin_unlock_irq(&current->sighand->siglock);
1538 put_pid(tty_pgrp);
1533 1539
1534 mutex_lock(&tty_mutex); 1540 mutex_lock(&tty_mutex);
1535 /* It is possible that do_tty_hangup has free'd this tty */ 1541 /* It is possible that do_tty_hangup has free'd this tty */
1536 tty = get_current_tty(); 1542 tty = get_current_tty();
1537 if (tty) { 1543 if (tty) {
1538 tty->session = 0; 1544 put_pid(tty->session);
1539 tty->pgrp = 0; 1545 put_pid(tty->pgrp);
1546 tty->session = NULL;
1547 tty->pgrp = NULL;
1540 } else { 1548 } else {
1541#ifdef TTY_DEBUG_HANGUP 1549#ifdef TTY_DEBUG_HANGUP
1542 printk(KERN_DEBUG "error attempted to write to tty [0x%p]" 1550 printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1547,7 +1555,7 @@ void disassociate_ctty(int on_exit)
1547 1555
1548 /* Now clear signal->tty under the lock */ 1556 /* Now clear signal->tty under the lock */
1549 read_lock(&tasklist_lock); 1557 read_lock(&tasklist_lock);
1550 session_clear_tty(process_session(current)); 1558 session_clear_tty(task_session(current));
1551 read_unlock(&tasklist_lock); 1559 read_unlock(&tasklist_lock);
1552 unlock_kernel(); 1560 unlock_kernel();
1553} 1561}
@@ -2484,6 +2492,7 @@ static int tty_open(struct inode * inode, struct file * filp)
2484 int index; 2492 int index;
2485 dev_t device = inode->i_rdev; 2493 dev_t device = inode->i_rdev;
2486 unsigned short saved_flags = filp->f_flags; 2494 unsigned short saved_flags = filp->f_flags;
2495 struct pid *old_pgrp;
2487 2496
2488 nonseekable_open(inode, filp); 2497 nonseekable_open(inode, filp);
2489 2498
@@ -2577,15 +2586,17 @@ got_driver:
2577 goto retry_open; 2586 goto retry_open;
2578 } 2587 }
2579 2588
2589 old_pgrp = NULL;
2580 mutex_lock(&tty_mutex); 2590 mutex_lock(&tty_mutex);
2581 spin_lock_irq(&current->sighand->siglock); 2591 spin_lock_irq(&current->sighand->siglock);
2582 if (!noctty && 2592 if (!noctty &&
2583 current->signal->leader && 2593 current->signal->leader &&
2584 !current->signal->tty && 2594 !current->signal->tty &&
2585 tty->session == 0) 2595 tty->session == NULL)
2586 __proc_set_tty(current, tty); 2596 old_pgrp = __proc_set_tty(current, tty);
2587 spin_unlock_irq(&current->sighand->siglock); 2597 spin_unlock_irq(&current->sighand->siglock);
2588 mutex_unlock(&tty_mutex); 2598 mutex_unlock(&tty_mutex);
2599 put_pid(old_pgrp);
2589 return 0; 2600 return 0;
2590} 2601}
2591 2602
@@ -2724,9 +2735,18 @@ static int tty_fasync(int fd, struct file * filp, int on)
2724 return retval; 2735 return retval;
2725 2736
2726 if (on) { 2737 if (on) {
2738 enum pid_type type;
2739 struct pid *pid;
2727 if (!waitqueue_active(&tty->read_wait)) 2740 if (!waitqueue_active(&tty->read_wait))
2728 tty->minimum_to_wake = 1; 2741 tty->minimum_to_wake = 1;
2729 retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0); 2742 if (tty->pgrp) {
2743 pid = tty->pgrp;
2744 type = PIDTYPE_PGID;
2745 } else {
2746 pid = task_pid(current);
2747 type = PIDTYPE_PID;
2748 }
2749 retval = __f_setown(filp, pid, type, 0);
2730 if (retval) 2750 if (retval)
2731 return retval; 2751 return retval;
2732 } else { 2752 } else {
@@ -2828,10 +2848,10 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
2828 } 2848 }
2829 } 2849 }
2830#endif 2850#endif
2831 if (tty->pgrp > 0) 2851 if (tty->pgrp)
2832 kill_pg(tty->pgrp, SIGWINCH, 1); 2852 kill_pgrp(tty->pgrp, SIGWINCH, 1);
2833 if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) 2853 if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
2834 kill_pg(real_tty->pgrp, SIGWINCH, 1); 2854 kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
2835 tty->winsize = tmp_ws; 2855 tty->winsize = tmp_ws;
2836 real_tty->winsize = tmp_ws; 2856 real_tty->winsize = tmp_ws;
2837done: 2857done:
@@ -2916,8 +2936,7 @@ static int fionbio(struct file *file, int __user *p)
2916static int tiocsctty(struct tty_struct *tty, int arg) 2936static int tiocsctty(struct tty_struct *tty, int arg)
2917{ 2937{
2918 int ret = 0; 2938 int ret = 0;
2919 if (current->signal->leader && 2939 if (current->signal->leader && (task_session(current) == tty->session))
2920 (process_session(current) == tty->session))
2921 return ret; 2940 return ret;
2922 2941
2923 mutex_lock(&tty_mutex); 2942 mutex_lock(&tty_mutex);
@@ -2930,7 +2949,7 @@ static int tiocsctty(struct tty_struct *tty, int arg)
2930 goto unlock; 2949 goto unlock;
2931 } 2950 }
2932 2951
2933 if (tty->session > 0) { 2952 if (tty->session) {
2934 /* 2953 /*
2935 * This tty is already the controlling 2954 * This tty is already the controlling
2936 * tty for another session group! 2955 * tty for another session group!
@@ -2973,7 +2992,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
2973 */ 2992 */
2974 if (tty == real_tty && current->signal->tty != real_tty) 2993 if (tty == real_tty && current->signal->tty != real_tty)
2975 return -ENOTTY; 2994 return -ENOTTY;
2976 return put_user(real_tty->pgrp, p); 2995 return put_user(pid_nr(real_tty->pgrp), p);
2977} 2996}
2978 2997
2979/** 2998/**
@@ -3000,7 +3019,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
3000 return retval; 3019 return retval;
3001 if (!current->signal->tty || 3020 if (!current->signal->tty ||
3002 (current->signal->tty != real_tty) || 3021 (current->signal->tty != real_tty) ||
3003 (real_tty->session != process_session(current))) 3022 (real_tty->session != task_session(current)))
3004 return -ENOTTY; 3023 return -ENOTTY;
3005 if (get_user(pgrp_nr, p)) 3024 if (get_user(pgrp_nr, p))
3006 return -EFAULT; 3025 return -EFAULT;
@@ -3015,7 +3034,8 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
3015 if (session_of_pgrp(pgrp) != task_session(current)) 3034 if (session_of_pgrp(pgrp) != task_session(current))
3016 goto out_unlock; 3035 goto out_unlock;
3017 retval = 0; 3036 retval = 0;
3018 real_tty->pgrp = pgrp_nr; 3037 put_pid(real_tty->pgrp);
3038 real_tty->pgrp = get_pid(pgrp);
3019out_unlock: 3039out_unlock:
3020 rcu_read_unlock(); 3040 rcu_read_unlock();
3021 return retval; 3041 return retval;
@@ -3041,9 +3061,9 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
3041 */ 3061 */
3042 if (tty == real_tty && current->signal->tty != real_tty) 3062 if (tty == real_tty && current->signal->tty != real_tty)
3043 return -ENOTTY; 3063 return -ENOTTY;
3044 if (real_tty->session <= 0) 3064 if (!real_tty->session)
3045 return -ENOTTY; 3065 return -ENOTTY;
3046 return put_user(real_tty->session, p); 3066 return put_user(pid_nr(real_tty->session), p);
3047} 3067}
3048 3068
3049/** 3069/**
@@ -3343,7 +3363,7 @@ void __do_SAK(struct tty_struct *tty)
3343 tty_hangup(tty); 3363 tty_hangup(tty);
3344#else 3364#else
3345 struct task_struct *g, *p; 3365 struct task_struct *g, *p;
3346 int session; 3366 struct pid *session;
3347 int i; 3367 int i;
3348 struct file *filp; 3368 struct file *filp;
3349 struct fdtable *fdt; 3369 struct fdtable *fdt;
@@ -3359,12 +3379,12 @@ void __do_SAK(struct tty_struct *tty)
3359 3379
3360 read_lock(&tasklist_lock); 3380 read_lock(&tasklist_lock);
3361 /* Kill the entire session */ 3381 /* Kill the entire session */
3362 do_each_task_pid(session, PIDTYPE_SID, p) { 3382 do_each_pid_task(session, PIDTYPE_SID, p) {
3363 printk(KERN_NOTICE "SAK: killed process %d" 3383 printk(KERN_NOTICE "SAK: killed process %d"
3364 " (%s): process_session(p)==tty->session\n", 3384 " (%s): process_session(p)==tty->session\n",
3365 p->pid, p->comm); 3385 p->pid, p->comm);
3366 send_sig(SIGKILL, p, 1); 3386 send_sig(SIGKILL, p, 1);
3367 } while_each_task_pid(session, PIDTYPE_SID, p); 3387 } while_each_pid_task(session, PIDTYPE_SID, p);
3368 /* Now kill any processes that happen to have the 3388 /* Now kill any processes that happen to have the
3369 * tty open. 3389 * tty open.
3370 */ 3390 */
@@ -3533,7 +3553,8 @@ static void initialize_tty_struct(struct tty_struct *tty)
3533 memset(tty, 0, sizeof(struct tty_struct)); 3553 memset(tty, 0, sizeof(struct tty_struct));
3534 tty->magic = TTY_MAGIC; 3554 tty->magic = TTY_MAGIC;
3535 tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); 3555 tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
3536 tty->pgrp = -1; 3556 tty->session = NULL;
3557 tty->pgrp = NULL;
3537 tty->overrun_time = jiffies; 3558 tty->overrun_time = jiffies;
3538 tty->buf.head = tty->buf.tail = NULL; 3559 tty->buf.head = tty->buf.tail = NULL;
3539 tty_buffer_init(tty); 3560 tty_buffer_init(tty);
@@ -3804,21 +3825,28 @@ void proc_clear_tty(struct task_struct *p)
3804} 3825}
3805EXPORT_SYMBOL(proc_clear_tty); 3826EXPORT_SYMBOL(proc_clear_tty);
3806 3827
3807static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) 3828static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
3808{ 3829{
3830 struct pid *old_pgrp;
3809 if (tty) { 3831 if (tty) {
3810 tty->session = process_session(tsk); 3832 tty->session = get_pid(task_session(tsk));
3811 tty->pgrp = process_group(tsk); 3833 tty->pgrp = get_pid(task_pgrp(tsk));
3812 } 3834 }
3835 old_pgrp = tsk->signal->tty_old_pgrp;
3813 tsk->signal->tty = tty; 3836 tsk->signal->tty = tty;
3814 tsk->signal->tty_old_pgrp = 0; 3837 tsk->signal->tty_old_pgrp = NULL;
3838 return old_pgrp;
3815} 3839}
3816 3840
3817void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) 3841void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
3818{ 3842{
3843 struct pid *old_pgrp;
3844
3819 spin_lock_irq(&tsk->sighand->siglock); 3845 spin_lock_irq(&tsk->sighand->siglock);
3820 __proc_set_tty(tsk, tty); 3846 old_pgrp = __proc_set_tty(tsk, tty);
3821 spin_unlock_irq(&tsk->sighand->siglock); 3847 spin_unlock_irq(&tsk->sighand->siglock);
3848
3849 put_pid(old_pgrp);
3822} 3850}
3823 3851
3824struct tty_struct *get_current_tty(void) 3852struct tty_struct *get_current_tty(void)