Commit 64d608db authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman

tty: cumulate and document tty_struct::ctrl* members

Group the ctrl members under a single struct called ctrl. The new struct
contains 'pgrp', 'session', 'pktstatus', and 'packet'. 'pktstatus' and
'packet' used to be bits in a bitfield. The struct also contains the
lock protecting them to share the same cache line.

Note that commit c545b66c (tty: Serialize tcflow() with other tty
flow control changes) added a padding to the original bitfield. It was
for the bitfield to occupy a whole 64b word to avoid interferring stores
on Alpha (cannot we evaporate this arch with weird implications to C
code yet?). But it doesn't work as expected as the padding
(tty_struct::ctrl_unused) is aligned to a 8B boundary too and occupies
some bytes from the next word.

So make it reliable by:
1) setting __aligned of the struct -- that aligns the start, and
2) making 'unsigned long unused[0]' as the last member of the struct --
   pads the end.

Add a kerneldoc comment for this grouped members.
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
Link: https://lore.kernel.org/r/20210505091928.22010-14-jslaby@suse.czSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6e94dbc7
...@@ -89,7 +89,7 @@ static inline void update_tty_status(struct ser_device *ser) ...@@ -89,7 +89,7 @@ static inline void update_tty_status(struct ser_device *ser)
ser->tty_status = ser->tty_status =
ser->tty->flow.stopped << 5 | ser->tty->flow.stopped << 5 |
ser->tty->flow.tco_stopped << 3 | ser->tty->flow.tco_stopped << 3 |
ser->tty->packet << 2; ser->tty->ctrl.packet << 2;
} }
static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty)
{ {
......
...@@ -342,10 +342,10 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) ...@@ -342,10 +342,10 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
if (tty->link->packet) { if (tty->link->ctrl.packet) {
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
tty->ctrl_status |= TIOCPKT_FLUSHREAD; tty->ctrl.pktstatus |= TIOCPKT_FLUSHREAD;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
} }
} }
...@@ -361,7 +361,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) ...@@ -361,7 +361,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
* Holds termios_rwsem to exclude producer/consumer while * Holds termios_rwsem to exclude producer/consumer while
* buffer indices are reset. * buffer indices are reset.
* *
* Locking: ctrl_lock, exclusive termios_rwsem * Locking: ctrl.lock, exclusive termios_rwsem
*/ */
static void n_tty_flush_buffer(struct tty_struct *tty) static void n_tty_flush_buffer(struct tty_struct *tty)
...@@ -1103,7 +1103,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) ...@@ -1103,7 +1103,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
* buffer is 'output'. The signal is processed first to alert any current * buffer is 'output'. The signal is processed first to alert any current
* readers or writers to discontinue and exit their i/o loops. * readers or writers to discontinue and exit their i/o loops.
* *
* Locking: ctrl_lock * Locking: ctrl.lock
*/ */
static void __isig(int sig, struct tty_struct *tty) static void __isig(int sig, struct tty_struct *tty)
...@@ -2025,7 +2025,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, ...@@ -2025,7 +2025,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
* *
* Locking: redirected write test is safe * Locking: redirected write test is safe
* current->signal->tty check is safe * current->signal->tty check is safe
* ctrl_lock to safely reference tty->pgrp * ctrl.lock to safely reference tty->ctrl.pgrp
*/ */
static int job_control(struct tty_struct *tty, struct file *file) static int job_control(struct tty_struct *tty, struct file *file)
...@@ -2072,7 +2072,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ...@@ -2072,7 +2072,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
int minimum, time; int minimum, time;
ssize_t retval = 0; ssize_t retval = 0;
long timeout; long timeout;
int packet; bool packet;
size_t tail; size_t tail;
/* /*
...@@ -2128,20 +2128,20 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ...@@ -2128,20 +2128,20 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
} }
} }
packet = tty->packet; packet = tty->ctrl.packet;
tail = ldata->read_tail; tail = ldata->read_tail;
add_wait_queue(&tty->read_wait, &wait); add_wait_queue(&tty->read_wait, &wait);
while (nr) { while (nr) {
/* First test for status change. */ /* First test for status change. */
if (packet && tty->link->ctrl_status) { if (packet && tty->link->ctrl.pktstatus) {
unsigned char cs; unsigned char cs;
if (kb != kbuf) if (kb != kbuf)
break; break;
spin_lock_irq(&tty->link->ctrl_lock); spin_lock_irq(&tty->link->ctrl.lock);
cs = tty->link->ctrl_status; cs = tty->link->ctrl.pktstatus;
tty->link->ctrl_status = 0; tty->link->ctrl.pktstatus = 0;
spin_unlock_irq(&tty->link->ctrl_lock); spin_unlock_irq(&tty->link->ctrl.lock);
*kb++ = cs; *kb++ = cs;
nr--; nr--;
break; break;
...@@ -2368,7 +2368,7 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, ...@@ -2368,7 +2368,7 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file,
if (input_available_p(tty, 1)) if (input_available_p(tty, 1))
mask |= EPOLLIN | EPOLLRDNORM; mask |= EPOLLIN | EPOLLRDNORM;
} }
if (tty->packet && tty->link->ctrl_status) if (tty->ctrl.packet && tty->link->ctrl.pktstatus)
mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM; mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM;
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= EPOLLHUP; mask |= EPOLLHUP;
......
...@@ -57,9 +57,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) ...@@ -57,9 +57,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
set_bit(TTY_IO_ERROR, &tty->flags); set_bit(TTY_IO_ERROR, &tty->flags);
wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl.lock);
tty->packet = 0; tty->ctrl.packet = false;
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl.lock);
/* Review - krefs on tty_link ?? */ /* Review - krefs on tty_link ?? */
if (!tty->link) if (!tty->link)
return; return;
...@@ -185,16 +185,16 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) ...@@ -185,16 +185,16 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
if (get_user(pktmode, arg)) if (get_user(pktmode, arg))
return -EFAULT; return -EFAULT;
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl.lock);
if (pktmode) { if (pktmode) {
if (!tty->packet) { if (!tty->ctrl.packet) {
tty->link->ctrl_status = 0; tty->link->ctrl.pktstatus = 0;
smp_mb(); smp_mb();
tty->packet = 1; tty->ctrl.packet = true;
} }
} else } else
tty->packet = 0; tty->ctrl.packet = false;
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl.lock);
return 0; return 0;
} }
...@@ -202,7 +202,7 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) ...@@ -202,7 +202,7 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
/* Get the packet mode of a pty */ /* Get the packet mode of a pty */
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg) static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{ {
int pktmode = tty->packet; int pktmode = tty->ctrl.packet;
return put_user(pktmode, arg); return put_user(pktmode, arg);
} }
...@@ -232,11 +232,11 @@ static void pty_flush_buffer(struct tty_struct *tty) ...@@ -232,11 +232,11 @@ static void pty_flush_buffer(struct tty_struct *tty)
return; return;
tty_buffer_flush(to, NULL); tty_buffer_flush(to, NULL);
if (to->packet) { if (to->ctrl.packet) {
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl.lock);
tty->ctrl_status |= TIOCPKT_FLUSHWRITE; tty->ctrl.pktstatus |= TIOCPKT_FLUSHWRITE;
wake_up_interruptible(&to->read_wait); wake_up_interruptible(&to->read_wait);
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl.lock);
} }
} }
...@@ -266,7 +266,7 @@ static void pty_set_termios(struct tty_struct *tty, ...@@ -266,7 +266,7 @@ static void pty_set_termios(struct tty_struct *tty,
struct ktermios *old_termios) struct ktermios *old_termios)
{ {
/* See if packet mode change of state. */ /* See if packet mode change of state. */
if (tty->link && tty->link->packet) { if (tty->link && tty->link->ctrl.packet) {
int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty);
int old_flow = ((old_termios->c_iflag & IXON) && int old_flow = ((old_termios->c_iflag & IXON) &&
(old_termios->c_cc[VSTOP] == '\023') && (old_termios->c_cc[VSTOP] == '\023') &&
...@@ -275,17 +275,17 @@ static void pty_set_termios(struct tty_struct *tty, ...@@ -275,17 +275,17 @@ static void pty_set_termios(struct tty_struct *tty,
STOP_CHAR(tty) == '\023' && STOP_CHAR(tty) == '\023' &&
START_CHAR(tty) == '\021'); START_CHAR(tty) == '\021');
if ((old_flow != new_flow) || extproc) { if ((old_flow != new_flow) || extproc) {
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl.lock);
if (old_flow != new_flow) { if (old_flow != new_flow) {
tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); tty->ctrl.pktstatus &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
if (new_flow) if (new_flow)
tty->ctrl_status |= TIOCPKT_DOSTOP; tty->ctrl.pktstatus |= TIOCPKT_DOSTOP;
else else
tty->ctrl_status |= TIOCPKT_NOSTOP; tty->ctrl.pktstatus |= TIOCPKT_NOSTOP;
} }
if (extproc) if (extproc)
tty->ctrl_status |= TIOCPKT_IOCTL; tty->ctrl.pktstatus |= TIOCPKT_IOCTL;
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl.lock);
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
} }
} }
...@@ -346,11 +346,11 @@ static void pty_start(struct tty_struct *tty) ...@@ -346,11 +346,11 @@ static void pty_start(struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
if (tty->link && tty->link->packet) { if (tty->link && tty->link->ctrl.packet) {
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
tty->ctrl_status &= ~TIOCPKT_STOP; tty->ctrl.pktstatus &= ~TIOCPKT_STOP;
tty->ctrl_status |= TIOCPKT_START; tty->ctrl.pktstatus |= TIOCPKT_START;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);
} }
} }
...@@ -359,11 +359,11 @@ static void pty_stop(struct tty_struct *tty) ...@@ -359,11 +359,11 @@ static void pty_stop(struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
if (tty->link && tty->link->packet) { if (tty->link && tty->link->ctrl.packet) {
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
tty->ctrl_status &= ~TIOCPKT_START; tty->ctrl.pktstatus &= ~TIOCPKT_START;
tty->ctrl_status |= TIOCPKT_STOP; tty->ctrl.pktstatus |= TIOCPKT_STOP;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);
} }
} }
......
...@@ -638,15 +638,15 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) ...@@ -638,15 +638,15 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
tty_ldisc_hangup(tty, cons_filp != NULL); tty_ldisc_hangup(tty, cons_filp != NULL);
spin_lock_irq(&tty->ctrl_lock); spin_lock_irq(&tty->ctrl.lock);
clear_bit(TTY_THROTTLED, &tty->flags); clear_bit(TTY_THROTTLED, &tty->flags);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
put_pid(tty->session); put_pid(tty->ctrl.session);
put_pid(tty->pgrp); put_pid(tty->ctrl.pgrp);
tty->session = NULL; tty->ctrl.session = NULL;
tty->pgrp = NULL; tty->ctrl.pgrp = NULL;
tty->ctrl_status = 0; tty->ctrl.pktstatus = 0;
spin_unlock_irq(&tty->ctrl_lock); spin_unlock_irq(&tty->ctrl.lock);
/* /*
* If one of the devices matches a console pointer, we * If one of the devices matches a console pointer, we
...@@ -1559,8 +1559,8 @@ static void release_one_tty(struct work_struct *work) ...@@ -1559,8 +1559,8 @@ static void release_one_tty(struct work_struct *work)
list_del_init(&tty->tty_files); list_del_init(&tty->tty_files);
spin_unlock(&tty->files_lock); spin_unlock(&tty->files_lock);
put_pid(tty->pgrp); put_pid(tty->ctrl.pgrp);
put_pid(tty->session); put_pid(tty->ctrl.session);
free_tty_struct(tty); free_tty_struct(tty);
} }
...@@ -1861,9 +1861,9 @@ int tty_release(struct inode *inode, struct file *filp) ...@@ -1861,9 +1861,9 @@ int tty_release(struct inode *inode, struct file *filp)
*/ */
if (!tty->count) { if (!tty->count) {
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
session_clear_tty(tty->session); session_clear_tty(tty->ctrl.session);
if (o_tty) if (o_tty)
session_clear_tty(o_tty->session); session_clear_tty(o_tty->ctrl.session);
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
} }
...@@ -2250,16 +2250,16 @@ static int __tty_fasync(int fd, struct file *filp, int on) ...@@ -2250,16 +2250,16 @@ static int __tty_fasync(int fd, struct file *filp, int on)
enum pid_type type; enum pid_type type;
struct pid *pid; struct pid *pid;
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
if (tty->pgrp) { if (tty->ctrl.pgrp) {
pid = tty->pgrp; pid = tty->ctrl.pgrp;
type = PIDTYPE_PGID; type = PIDTYPE_PGID;
} else { } else {
pid = task_pid(current); pid = task_pid(current);
type = PIDTYPE_TGID; type = PIDTYPE_TGID;
} }
get_pid(pid); get_pid(pid);
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
__f_setown(filp, pid, type, 0); __f_setown(filp, pid, type, 0);
put_pid(pid); put_pid(pid);
retval = 0; retval = 0;
...@@ -2381,7 +2381,7 @@ EXPORT_SYMBOL(tty_do_resize); ...@@ -2381,7 +2381,7 @@ EXPORT_SYMBOL(tty_do_resize);
* *
* Locking: * Locking:
* Driver dependent. The default do_resize method takes the * Driver dependent. The default do_resize method takes the
* tty termios mutex and ctrl_lock. The console takes its own lock * tty termios mutex and ctrl.lock. The console takes its own lock
* then calls into the default method. * then calls into the default method.
*/ */
...@@ -3039,9 +3039,9 @@ void __do_SAK(struct tty_struct *tty) ...@@ -3039,9 +3039,9 @@ void __do_SAK(struct tty_struct *tty)
if (!tty) if (!tty)
return; return;
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
session = get_pid(tty->session); session = get_pid(tty->ctrl.session);
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
...@@ -3129,8 +3129,8 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) ...@@ -3129,8 +3129,8 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
kfree(tty); kfree(tty);
return NULL; return NULL;
} }
tty->session = NULL; tty->ctrl.session = NULL;
tty->pgrp = NULL; tty->ctrl.pgrp = NULL;
mutex_init(&tty->legacy_mutex); mutex_init(&tty->legacy_mutex);
mutex_init(&tty->throttle_mutex); mutex_init(&tty->throttle_mutex);
init_rwsem(&tty->termios_rwsem); init_rwsem(&tty->termios_rwsem);
...@@ -3140,7 +3140,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) ...@@ -3140,7 +3140,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
init_waitqueue_head(&tty->read_wait); init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup); INIT_WORK(&tty->hangup_work, do_tty_hangup);
mutex_init(&tty->atomic_write_lock); mutex_init(&tty->atomic_write_lock);
spin_lock_init(&tty->ctrl_lock); spin_lock_init(&tty->ctrl.lock);
spin_lock_init(&tty->flow.lock); spin_lock_init(&tty->flow.lock);
spin_lock_init(&tty->files_lock); spin_lock_init(&tty->files_lock);
INIT_LIST_HEAD(&tty->tty_files); INIT_LIST_HEAD(&tty->tty_files);
......
...@@ -28,7 +28,7 @@ static int is_ignored(int sig) ...@@ -28,7 +28,7 @@ static int is_ignored(int sig)
* not in the foreground, send a SIGTTOU. If the signal is blocked or * not in the foreground, send a SIGTTOU. If the signal is blocked or
* ignored, go ahead and perform the operation. (POSIX 7.2) * ignored, go ahead and perform the operation. (POSIX 7.2)
* *
* Locking: ctrl_lock * Locking: ctrl.lock
*/ */
int __tty_check_change(struct tty_struct *tty, int sig) int __tty_check_change(struct tty_struct *tty, int sig)
{ {
...@@ -42,9 +42,9 @@ int __tty_check_change(struct tty_struct *tty, int sig) ...@@ -42,9 +42,9 @@ int __tty_check_change(struct tty_struct *tty, int sig)
rcu_read_lock(); rcu_read_lock();
pgrp = task_pgrp(current); pgrp = task_pgrp(current);
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
tty_pgrp = tty->pgrp; tty_pgrp = tty->ctrl.pgrp;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
if (tty_pgrp && pgrp != tty_pgrp) { if (tty_pgrp && pgrp != tty_pgrp) {
if (is_ignored(sig)) { if (is_ignored(sig)) {
...@@ -99,16 +99,16 @@ static void __proc_set_tty(struct tty_struct *tty) ...@@ -99,16 +99,16 @@ static void __proc_set_tty(struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
/* /*
* The session and fg pgrp references will be non-NULL if * The session and fg pgrp references will be non-NULL if
* tiocsctty() is stealing the controlling tty * tiocsctty() is stealing the controlling tty
*/ */
put_pid(tty->session); put_pid(tty->ctrl.session);
put_pid(tty->pgrp); put_pid(tty->ctrl.pgrp);
tty->pgrp = get_pid(task_pgrp(current)); tty->ctrl.pgrp = get_pid(task_pgrp(current));
tty->session = get_pid(task_session(current)); tty->ctrl.session = get_pid(task_session(current));
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
if (current->signal->tty) { if (current->signal->tty) {
tty_debug(tty, "current tty %s not NULL!!\n", tty_debug(tty, "current tty %s not NULL!!\n",
current->signal->tty->name); current->signal->tty->name);
...@@ -135,7 +135,7 @@ void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty) ...@@ -135,7 +135,7 @@ void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty)
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
if (current->signal->leader && if (current->signal->leader &&
!current->signal->tty && !current->signal->tty &&
tty->session == NULL) { tty->ctrl.session == NULL) {
/* /*
* Don't let a process that only has write access to the tty * Don't let a process that only has write access to the tty
* obtain the privileges associated with having a tty as * obtain the privileges associated with having a tty as
...@@ -200,8 +200,8 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) ...@@ -200,8 +200,8 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
struct pid *tty_pgrp = NULL; struct pid *tty_pgrp = NULL;
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
if (tty->session) { if (tty->ctrl.session) {
do_each_pid_task(tty->session, PIDTYPE_SID, p) { do_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock); spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty) { if (p->signal->tty == tty) {
p->signal->tty = NULL; p->signal->tty = NULL;
...@@ -218,13 +218,14 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) ...@@ -218,13 +218,14 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
put_pid(p->signal->tty_old_pgrp); /* A noop */ put_pid(p->signal->tty_old_pgrp); /* A noop */
spin_lock(&tty->ctrl_lock); spin_lock(&tty->ctrl.lock);
tty_pgrp = get_pid(tty->pgrp); tty_pgrp = get_pid(tty->ctrl.pgrp);
if (tty->pgrp) if (tty->ctrl.pgrp)
p->signal->tty_old_pgrp = get_pid(tty->pgrp); p->signal->tty_old_pgrp =
spin_unlock(&tty->ctrl_lock); get_pid(tty->ctrl.pgrp);
spin_unlock(&tty->ctrl.lock);
spin_unlock_irq(&p->sighand->siglock); spin_unlock_irq(&p->sighand->siglock);
} while_each_pid_task(tty->session, PIDTYPE_SID, p); } while_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p);
} }
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
...@@ -309,12 +310,12 @@ void disassociate_ctty(int on_exit) ...@@ -309,12 +310,12 @@ void disassociate_ctty(int on_exit)
unsigned long flags; unsigned long flags;
tty_lock(tty); tty_lock(tty);
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
put_pid(tty->session); put_pid(tty->ctrl.session);
put_pid(tty->pgrp); put_pid(tty->ctrl.pgrp);
tty->session = NULL; tty->ctrl.session = NULL;
tty->pgrp = NULL; tty->ctrl.pgrp = NULL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
tty_unlock(tty); tty_unlock(tty);
tty_kref_put(tty); tty_kref_put(tty);
} }
...@@ -363,7 +364,8 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) ...@@ -363,7 +364,8 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
tty_lock(tty); tty_lock(tty);
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
if (current->signal->leader && (task_session(current) == tty->session)) if (current->signal->leader &&
task_session(current) == tty->ctrl.session)
goto unlock; goto unlock;
/* /*
...@@ -375,7 +377,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) ...@@ -375,7 +377,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
goto unlock; goto unlock;
} }
if (tty->session) { if (tty->ctrl.session) {
/* /*
* This tty is already the controlling * This tty is already the controlling
* tty for another session group! * tty for another session group!
...@@ -384,7 +386,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) ...@@ -384,7 +386,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
/* /*
* Steal it away * Steal it away
*/ */
session_clear_tty(tty->session); session_clear_tty(tty->ctrl.session);
} else { } else {
ret = -EPERM; ret = -EPERM;
goto unlock; goto unlock;
...@@ -416,9 +418,9 @@ struct pid *tty_get_pgrp(struct tty_struct *tty) ...@@ -416,9 +418,9 @@ struct pid *tty_get_pgrp(struct tty_struct *tty)
unsigned long flags; unsigned long flags;
struct pid *pgrp; struct pid *pgrp;
spin_lock_irqsave(&tty->ctrl_lock, flags); spin_lock_irqsave(&tty->ctrl.lock, flags);
pgrp = get_pid(tty->pgrp); pgrp = get_pid(tty->ctrl.pgrp);
spin_unlock_irqrestore(&tty->ctrl_lock, flags); spin_unlock_irqrestore(&tty->ctrl.lock, flags);
return pgrp; return pgrp;
} }
...@@ -499,10 +501,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t ...@@ -499,10 +501,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
if (pgrp_nr < 0) if (pgrp_nr < 0)
return -EINVAL; return -EINVAL;
spin_lock_irq(&real_tty->ctrl_lock); spin_lock_irq(&real_tty->ctrl.lock);
if (!current->signal->tty || if (!current->signal->tty ||
(current->signal->tty != real_tty) || (current->signal->tty != real_tty) ||
(real_tty->session != task_session(current))) { (real_tty->ctrl.session != task_session(current))) {
retval = -ENOTTY; retval = -ENOTTY;
goto out_unlock_ctrl; goto out_unlock_ctrl;
} }
...@@ -515,12 +517,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t ...@@ -515,12 +517,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
if (session_of_pgrp(pgrp) != task_session(current)) if (session_of_pgrp(pgrp) != task_session(current))
goto out_unlock; goto out_unlock;
retval = 0; retval = 0;
put_pid(real_tty->pgrp); put_pid(real_tty->ctrl.pgrp);
real_tty->pgrp = get_pid(pgrp); real_tty->ctrl.pgrp = get_pid(pgrp);
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
out_unlock_ctrl: out_unlock_ctrl:
spin_unlock_irq(&real_tty->ctrl_lock); spin_unlock_irq(&real_tty->ctrl.lock);
return retval; return retval;
} }
...@@ -545,16 +547,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ ...@@ -545,16 +547,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
if (tty == real_tty && current->signal->tty != real_tty) if (tty == real_tty && current->signal->tty != real_tty)
return -ENOTTY; return -ENOTTY;
spin_lock_irqsave(&real_tty->ctrl_lock, flags); spin_lock_irqsave(&real_tty->ctrl.lock, flags);
if (!real_tty->session) if (!real_tty->ctrl.session)
goto err; goto err;
sid = pid_vnr(real_tty->session); sid = pid_vnr(real_tty->ctrl.session);
spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
return put_user(sid, p); return put_user(sid, p);
err: err:
spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
return -ENOTTY; return -ENOTTY;
} }
......
...@@ -1189,7 +1189,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, ...@@ -1189,7 +1189,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
* information and perform any necessary signal handling. * information and perform any necessary signal handling.
* *
* Caller must hold the console semaphore. Takes the termios rwsem and * Caller must hold the console semaphore. Takes the termios rwsem and
* ctrl_lock of the tty IFF a tty is passed. * ctrl.lock of the tty IFF a tty is passed.
*/ */
static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
...@@ -1355,7 +1355,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) ...@@ -1355,7 +1355,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
* the actual work. * the actual work.
* *
* Takes the console sem and the called methods then take the tty * Takes the console sem and the called methods then take the tty
* termios_rwsem and the tty ctrl_lock in that order. * termios_rwsem and the tty ctrl.lock in that order.
*/ */
static int vt_resize(struct tty_struct *tty, struct winsize *ws) static int vt_resize(struct tty_struct *tty, struct winsize *ws)
{ {
......
...@@ -255,6 +255,13 @@ struct tty_operations; ...@@ -255,6 +255,13 @@ struct tty_operations;
* @flow.unused: alignment for Alpha, so that no members other than @flow.* are * @flow.unused: alignment for Alpha, so that no members other than @flow.* are
* modified by the same 64b word store. The @flow's __aligned is * modified by the same 64b word store. The @flow's __aligned is
* there for the very same reason. * there for the very same reason.
* @ctrl.lock: lock for ctrl members
* @ctrl.pgrp: process group of this tty (setpgrp(2))
* @ctrl.session: session of this tty (setsid(2)). Writes are protected by both
* @ctrl.lock and legacy mutex, readers must use at least one of
* them.
* @ctrl.pktstatus: packet mode status (bitwise OR of TIOCPKT_* constants)
* @ctrl.packet: packet mode enabled
* *
* All of the state associated with a tty while the tty is open. Persistent * All of the state associated with a tty while the tty is open. Persistent
* storage for tty devices is referenced here as @port in struct tty_port. * storage for tty devices is referenced here as @port in struct tty_port.
...@@ -276,16 +283,9 @@ struct tty_struct { ...@@ -276,16 +283,9 @@ struct tty_struct {
struct mutex throttle_mutex; struct mutex throttle_mutex;
struct rw_semaphore termios_rwsem; struct rw_semaphore termios_rwsem;
struct mutex winsize_mutex; struct mutex winsize_mutex;
spinlock_t ctrl_lock;
/* Termios values are protected by the termios rwsem */ /* Termios values are protected by the termios rwsem */
struct ktermios termios, termios_locked; struct ktermios termios, termios_locked;
char name[64]; char name[64];
struct pid *pgrp; /* Protected by ctrl lock */
/*
* Writes protected by both ctrl lock and legacy mutex, readers must use
* at least one of them.
*/
struct pid *session;
unsigned long flags; unsigned long flags;
int count; int count;
struct winsize winsize; /* winsize_mutex */ struct winsize winsize; /* winsize_mutex */
...@@ -297,10 +297,16 @@ struct tty_struct { ...@@ -297,10 +297,16 @@ struct tty_struct {
unsigned long unused[0]; unsigned long unused[0];
} __aligned(sizeof(unsigned long)) flow; } __aligned(sizeof(unsigned long)) flow;
struct {
spinlock_t lock;
struct pid *pgrp;
struct pid *session;
unsigned char pktstatus;
bool packet;
unsigned long unused[0];
} __aligned(sizeof(unsigned long)) ctrl;
int hw_stopped; int hw_stopped;
unsigned long ctrl_status:8, /* ctrl_lock */
packet:1,
unused_ctrl:BITS_PER_LONG - 9;
unsigned int receive_room; /* Bytes free for queue */ unsigned int receive_room; /* Bytes free for queue */
int flow_change; int flow_change;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment