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>
---
arch/um/drivers/line.c | 2 +-
drivers/char/ip2/ip2main.c | 4 +-
drivers/char/n_tty.c | 12 ++--
drivers/char/tty_io.c | 129 ++++++++++++++++++++++++++-----------------
drivers/char/vt.c | 4 +-
fs/proc/array.c | 2 +-
include/linux/init_task.h | 2 +-
include/linux/sched.h | 2 +-
include/linux/tty.h | 4 +-
kernel/fork.c | 2 +-
kernel/sys.c | 1 -
11 files changed, 95 insertions(+), 69 deletions(-)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83301e1..3c1a1d4 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -737,7 +737,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
line = tty->driver_data;
chan_window_size(&line->chan_list, &tty->winsize.ws_row,
&tty->winsize.ws_col);
- kill_pg(tty->pgrp, SIGWINCH, 1);
+ kill_pgrp(tty->pgrp, SIGWINCH, 1);
}
out:
if(winch->fd != -1)
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 7c70310..83c7258 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -1271,8 +1271,8 @@ static void do_input(struct work_struct *work)
// code duplicated from n_tty (ldisc)
static inline void isig(int sig, struct tty_struct *tty, int flush)
{
- if (tty->pgrp > 0)
- kill_pg(tty->pgrp, sig, 1);
+ if (tty->pgrp)
+ kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
if ( tty->ldisc.flush_buffer )
tty->ldisc.flush_buffer(tty);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 7f1ded8..2b50a50 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -579,8 +579,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
static inline void isig(int sig, struct tty_struct *tty, int flush)
{
- if (tty->pgrp > 0)
- kill_pg(tty->pgrp, sig, 1);
+ if (tty->pgrp)
+ kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer)
@@ -1185,13 +1185,13 @@ static int job_control(struct tty_struct *tty, struct file *file)
/* don't stop on /dev/console */
if (file->f_op->write != redirected_tty_write &&
current->signal->tty == tty) {
- if (tty->pgrp <= 0)
- printk("read_chan: tty->pgrp <= 0!\n");
- else if (process_group(current) != tty->pgrp) {
+ if (!tty->pgrp)
+ printk("read_chan: no tty->pgrp!\n");
+ else if (task_pgrp(current) != tty->pgrp) {
if (is_ignored(SIGTTIN) ||
is_current_pgrp_orphaned())
return -EIO;
- kill_pg(process_group(current), SIGTTIN, 1);
+ kill_pgrp(task_pgrp(current), SIGTTIN, 1);
return -ERESTARTSYS;
}
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index d8fdf45..fe98f8c 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -155,7 +155,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int tty_fasync(int fd, struct file * filp, int on);
static void release_mem(struct tty_struct *tty, int idx);
-static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
/**
* alloc_tty_struct - allocate a tty object
@@ -1110,17 +1110,17 @@ int tty_check_change(struct tty_struct * tty)
{
if (current->signal->tty != tty)
return 0;
- if (tty->pgrp <= 0) {
- printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
+ if (!tty->pgrp) {
+ printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
return 0;
}
- if (process_group(current) == tty->pgrp)
+ if (task_pgrp(current) == tty->pgrp)
return 0;
if (is_ignored(SIGTTOU))
return 0;
if (is_current_pgrp_orphaned())
return -EIO;
- (void) kill_pg(process_group(current), SIGTTOU, 1);
+ (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
return -ERESTARTSYS;
}
@@ -1355,8 +1355,8 @@ static void do_tty_hangup(struct work_struct *work)
tty_release is called */
read_lock(&tasklist_lock);
- if (tty->session > 0) {
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ if (tty->session) {
+ do_each_pid_task(tty->session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty)
p->signal->tty = NULL;
@@ -1366,16 +1366,17 @@ static void do_tty_hangup(struct work_struct *work)
}
__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
- if (tty->pgrp > 0)
- p->signal->tty_old_pgrp = tty->pgrp;
+ put_pid(p->signal->tty_old_pgrp); /* A noop */
+ if (tty->pgrp)
+ p->signal->tty_old_pgrp = get_pid(tty->pgrp);
spin_unlock_irq(&p->sighand->siglock);
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ } while_each_pid_task(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
tty->flags = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ tty->session = NULL;
+ tty->pgrp = NULL;
tty->ctrl_status = 0;
/*
* If one of the devices matches a console pointer, we
@@ -1460,12 +1461,12 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
-static void session_clear_tty(pid_t session)
+static void session_clear_tty(struct pid *session)
{
struct task_struct *p;
- do_each_task_pid(session, PIDTYPE_SID, p) {
+ do_each_pid_task(session, PIDTYPE_SID, p) {
proc_clear_tty(p);
- } while_each_task_pid(session, PIDTYPE_SID, p);
+ } while_each_pid_task(session, PIDTYPE_SID, p);
}
/**
@@ -1495,48 +1496,54 @@ static void session_clear_tty(pid_t session)
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
- int tty_pgrp = -1;
+ struct pid *tty_pgrp = NULL;
lock_kernel();
mutex_lock(&tty_mutex);
tty = get_current_tty();
if (tty) {
- tty_pgrp = tty->pgrp;
+ tty_pgrp = get_pid(tty->pgrp);
mutex_unlock(&tty_mutex);
/* XXX: here we race, there is nothing protecting tty */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
} else if (on_exit) {
- pid_t old_pgrp;
+ struct pid *old_pgrp;
spin_lock_irq(¤t->sighand->siglock);
old_pgrp = current->signal->tty_old_pgrp;
- current->signal->tty_old_pgrp = 0;
+ current->signal->tty_old_pgrp = NULL;
spin_unlock_irq(¤t->sighand->siglock);
if (old_pgrp) {
- kill_pg(old_pgrp, SIGHUP, on_exit);
- kill_pg(old_pgrp, SIGCONT, on_exit);
+ kill_pgrp(old_pgrp, SIGHUP, on_exit);
+ kill_pgrp(old_pgrp, SIGCONT, on_exit);
+ put_pid(old_pgrp);
}
mutex_unlock(&tty_mutex);
unlock_kernel();
return;
}
- if (tty_pgrp > 0) {
- kill_pg(tty_pgrp, SIGHUP, on_exit);
+ if (tty_pgrp) {
+ kill_pgrp(tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
- kill_pg(tty_pgrp, SIGCONT, on_exit);
+ kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+ put_pid(tty_pgrp);
}
spin_lock_irq(¤t->sighand->siglock);
+ tty_pgrp = current->signal->tty_old_pgrp;
current->signal->tty_old_pgrp = 0;
spin_unlock_irq(¤t->sighand->siglock);
+ put_pid(tty_pgrp);
mutex_lock(&tty_mutex);
/* It is possible that do_tty_hangup has free'd this tty */
tty = get_current_tty();
if (tty) {
- tty->session = 0;
- tty->pgrp = 0;
+ put_pid(tty->session);
+ put_pid(tty->pgrp);
+ tty->session = NULL;
+ tty->pgrp = NULL;
} else {
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1547,7 +1554,7 @@ void disassociate_ctty(int on_exit)
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
- session_clear_tty(process_session(current));
+ session_clear_tty(task_session(current));
read_unlock(&tasklist_lock);
unlock_kernel();
}
@@ -2484,6 +2491,7 @@ static int tty_open(struct inode * inode, struct file * filp)
int index;
dev_t device = inode->i_rdev;
unsigned short saved_flags = filp->f_flags;
+ struct pid *old_pgrp;
nonseekable_open(inode, filp);
@@ -2577,15 +2585,17 @@ got_driver:
goto retry_open;
}
+ old_pgrp = NULL;
mutex_lock(&tty_mutex);
spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
- tty->session == 0)
- __proc_set_tty(current, tty);
+ tty->session == NULL)
+ old_pgrp = __proc_set_tty(current, tty);
spin_unlock_irq(¤t->sighand->siglock);
mutex_unlock(&tty_mutex);
+ put_pid(old_pgrp);
return 0;
}
@@ -2724,9 +2734,18 @@ static int tty_fasync(int fd, struct file * filp, int on)
return retval;
if (on) {
+ enum pid_type type;
+ struct pid *pid;
if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = 1;
- retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
+ if (tty->pgrp) {
+ pid = tty->pgrp;
+ type = PIDTYPE_PGID;
+ } else {
+ pid = task_pid(current);
+ type = PIDTYPE_PID;
+ }
+ retval = __f_setown(filp, pid, type, 0);
if (retval)
return retval;
} else {
@@ -2828,10 +2847,10 @@ static int tiocswinsz(struct tty_struct *tty
...