ser->tty_status =
ser->tty->flow.stopped << 5 |
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)
{
{
unsigned long flags;
- if (tty->link->packet) {
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- tty->ctrl_status |= TIOCPKT_FLUSHREAD;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ if (tty->link->ctrl.packet) {
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ tty->ctrl.pktstatus |= TIOCPKT_FLUSHREAD;
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible(&tty->link->read_wait);
}
}
* Holds termios_rwsem to exclude producer/consumer while
* 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)
* buffer is 'output'. The signal is processed first to alert any current
* 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)
*
* Locking: redirected write test 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)
int minimum, time;
ssize_t retval = 0;
long timeout;
- int packet;
+ bool packet;
size_t tail;
/*
}
}
- packet = tty->packet;
+ packet = tty->ctrl.packet;
tail = ldata->read_tail;
add_wait_queue(&tty->read_wait, &wait);
while (nr) {
/* First test for status change. */
- if (packet && tty->link->ctrl_status) {
+ if (packet && tty->link->ctrl.pktstatus) {
unsigned char cs;
if (kb != kbuf)
break;
- spin_lock_irq(&tty->link->ctrl_lock);
- cs = tty->link->ctrl_status;
- tty->link->ctrl_status = 0;
- spin_unlock_irq(&tty->link->ctrl_lock);
+ spin_lock_irq(&tty->link->ctrl.lock);
+ cs = tty->link->ctrl.pktstatus;
+ tty->link->ctrl.pktstatus = 0;
+ spin_unlock_irq(&tty->link->ctrl.lock);
*kb++ = cs;
nr--;
break;
if (input_available_p(tty, 1))
mask |= EPOLLIN | EPOLLRDNORM;
}
- if (tty->packet && tty->link->ctrl_status)
+ if (tty->ctrl.packet && tty->link->ctrl.pktstatus)
mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM;
if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= EPOLLHUP;
set_bit(TTY_IO_ERROR, &tty->flags);
wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait);
- spin_lock_irq(&tty->ctrl_lock);
- tty->packet = 0;
- spin_unlock_irq(&tty->ctrl_lock);
+ spin_lock_irq(&tty->ctrl.lock);
+ tty->ctrl.packet = false;
+ spin_unlock_irq(&tty->ctrl.lock);
/* Review - krefs on tty_link ?? */
if (!tty->link)
return;
if (get_user(pktmode, arg))
return -EFAULT;
- spin_lock_irq(&tty->ctrl_lock);
+ spin_lock_irq(&tty->ctrl.lock);
if (pktmode) {
- if (!tty->packet) {
- tty->link->ctrl_status = 0;
+ if (!tty->ctrl.packet) {
+ tty->link->ctrl.pktstatus = 0;
smp_mb();
- tty->packet = 1;
+ tty->ctrl.packet = true;
}
} else
- tty->packet = 0;
- spin_unlock_irq(&tty->ctrl_lock);
+ tty->ctrl.packet = false;
+ spin_unlock_irq(&tty->ctrl.lock);
return 0;
}
/* Get the packet mode of a pty */
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;
tty_buffer_flush(to, NULL);
- if (to->packet) {
- spin_lock_irq(&tty->ctrl_lock);
- tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
+ if (to->ctrl.packet) {
+ spin_lock_irq(&tty->ctrl.lock);
+ tty->ctrl.pktstatus |= TIOCPKT_FLUSHWRITE;
wake_up_interruptible(&to->read_wait);
- spin_unlock_irq(&tty->ctrl_lock);
+ spin_unlock_irq(&tty->ctrl.lock);
}
}
struct ktermios *old_termios)
{
/* 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 old_flow = ((old_termios->c_iflag & IXON) &&
(old_termios->c_cc[VSTOP] == '\023') &&
STOP_CHAR(tty) == '\023' &&
START_CHAR(tty) == '\021');
if ((old_flow != new_flow) || extproc) {
- spin_lock_irq(&tty->ctrl_lock);
+ spin_lock_irq(&tty->ctrl.lock);
if (old_flow != new_flow) {
- tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
+ tty->ctrl.pktstatus &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
if (new_flow)
- tty->ctrl_status |= TIOCPKT_DOSTOP;
+ tty->ctrl.pktstatus |= TIOCPKT_DOSTOP;
else
- tty->ctrl_status |= TIOCPKT_NOSTOP;
+ tty->ctrl.pktstatus |= TIOCPKT_NOSTOP;
}
if (extproc)
- tty->ctrl_status |= TIOCPKT_IOCTL;
- spin_unlock_irq(&tty->ctrl_lock);
+ tty->ctrl.pktstatus |= TIOCPKT_IOCTL;
+ spin_unlock_irq(&tty->ctrl.lock);
wake_up_interruptible(&tty->link->read_wait);
}
}
{
unsigned long flags;
- if (tty->link && tty->link->packet) {
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- tty->ctrl_status &= ~TIOCPKT_STOP;
- tty->ctrl_status |= TIOCPKT_START;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ if (tty->link && tty->link->ctrl.packet) {
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ tty->ctrl.pktstatus &= ~TIOCPKT_STOP;
+ tty->ctrl.pktstatus |= TIOCPKT_START;
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);
}
}
{
unsigned long flags;
- if (tty->link && tty->link->packet) {
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- tty->ctrl_status &= ~TIOCPKT_START;
- tty->ctrl_status |= TIOCPKT_STOP;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ if (tty->link && tty->link->ctrl.packet) {
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ tty->ctrl.pktstatus &= ~TIOCPKT_START;
+ tty->ctrl.pktstatus |= TIOCPKT_STOP;
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN);
}
}
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_DO_WRITE_WAKEUP, &tty->flags);
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->session = NULL;
- tty->pgrp = NULL;
- tty->ctrl_status = 0;
- spin_unlock_irq(&tty->ctrl_lock);
+ put_pid(tty->ctrl.session);
+ put_pid(tty->ctrl.pgrp);
+ tty->ctrl.session = NULL;
+ tty->ctrl.pgrp = NULL;
+ tty->ctrl.pktstatus = 0;
+ spin_unlock_irq(&tty->ctrl.lock);
/*
* If one of the devices matches a console pointer, we
list_del_init(&tty->tty_files);
spin_unlock(&tty->files_lock);
- put_pid(tty->pgrp);
- put_pid(tty->session);
+ put_pid(tty->ctrl.pgrp);
+ put_pid(tty->ctrl.session);
free_tty_struct(tty);
}
*/
if (!tty->count) {
read_lock(&tasklist_lock);
- session_clear_tty(tty->session);
+ session_clear_tty(tty->ctrl.session);
if (o_tty)
- session_clear_tty(o_tty->session);
+ session_clear_tty(o_tty->ctrl.session);
read_unlock(&tasklist_lock);
}
enum pid_type type;
struct pid *pid;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- if (tty->pgrp) {
- pid = tty->pgrp;
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ if (tty->ctrl.pgrp) {
+ pid = tty->ctrl.pgrp;
type = PIDTYPE_PGID;
} else {
pid = task_pid(current);
type = PIDTYPE_TGID;
}
get_pid(pid);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
__f_setown(filp, pid, type, 0);
put_pid(pid);
retval = 0;
*
* Locking:
* 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.
*/
if (!tty)
return;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- session = get_pid(tty->session);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ session = get_pid(tty->ctrl.session);
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
tty_ldisc_flush(tty);
kfree(tty);
return NULL;
}
- tty->session = NULL;
- tty->pgrp = NULL;
+ tty->ctrl.session = NULL;
+ tty->ctrl.pgrp = NULL;
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->throttle_mutex);
init_rwsem(&tty->termios_rwsem);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup);
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->files_lock);
INIT_LIST_HEAD(&tty->tty_files);
* not in the foreground, send a SIGTTOU. If the signal is blocked or
* 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)
{
rcu_read_lock();
pgrp = task_pgrp(current);
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- tty_pgrp = tty->pgrp;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ tty_pgrp = tty->ctrl.pgrp;
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
if (tty_pgrp && pgrp != tty_pgrp) {
if (is_ignored(sig)) {
{
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
* tiocsctty() is stealing the controlling tty
*/
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->pgrp = get_pid(task_pgrp(current));
- tty->session = get_pid(task_session(current));
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ put_pid(tty->ctrl.session);
+ put_pid(tty->ctrl.pgrp);
+ tty->ctrl.pgrp = get_pid(task_pgrp(current));
+ tty->ctrl.session = get_pid(task_session(current));
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
if (current->signal->tty) {
tty_debug(tty, "current tty %s not NULL!!\n",
current->signal->tty->name);
spin_lock_irq(¤t->sighand->siglock);
if (current->signal->leader &&
!current->signal->tty &&
- tty->session == NULL) {
+ tty->ctrl.session == NULL) {
/*
* Don't let a process that only has write access to the tty
* obtain the privileges associated with having a tty as
struct pid *tty_pgrp = NULL;
read_lock(&tasklist_lock);
- if (tty->session) {
- do_each_pid_task(tty->session, PIDTYPE_SID, p) {
+ if (tty->ctrl.session) {
+ do_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty) {
p->signal->tty = NULL;
__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
put_pid(p->signal->tty_old_pgrp); /* A noop */
- spin_lock(&tty->ctrl_lock);
- tty_pgrp = get_pid(tty->pgrp);
- if (tty->pgrp)
- p->signal->tty_old_pgrp = get_pid(tty->pgrp);
- spin_unlock(&tty->ctrl_lock);
+ spin_lock(&tty->ctrl.lock);
+ tty_pgrp = get_pid(tty->ctrl.pgrp);
+ if (tty->ctrl.pgrp)
+ p->signal->tty_old_pgrp =
+ get_pid(tty->ctrl.pgrp);
+ spin_unlock(&tty->ctrl.lock);
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);
unsigned long flags;
tty_lock(tty);
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->session = NULL;
- tty->pgrp = NULL;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ put_pid(tty->ctrl.session);
+ put_pid(tty->ctrl.pgrp);
+ tty->ctrl.session = NULL;
+ tty->ctrl.pgrp = NULL;
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
tty_unlock(tty);
tty_kref_put(tty);
}
tty_lock(tty);
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;
}
- if (tty->session) {
+ if (tty->ctrl.session) {
/*
* This tty is already the controlling
* tty for another session group!
/*
* Steal it away
*/
- session_clear_tty(tty->session);
+ session_clear_tty(tty->ctrl.session);
} else {
ret = -EPERM;
goto unlock;
unsigned long flags;
struct pid *pgrp;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- pgrp = get_pid(tty->pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+ spin_lock_irqsave(&tty->ctrl.lock, flags);
+ pgrp = get_pid(tty->ctrl.pgrp);
+ spin_unlock_irqrestore(&tty->ctrl.lock, flags);
return pgrp;
}
if (pgrp_nr < 0)
return -EINVAL;
- spin_lock_irq(&real_tty->ctrl_lock);
+ spin_lock_irq(&real_tty->ctrl.lock);
if (!current->signal->tty ||
(current->signal->tty != real_tty) ||
- (real_tty->session != task_session(current))) {
+ (real_tty->ctrl.session != task_session(current))) {
retval = -ENOTTY;
goto out_unlock_ctrl;
}
if (session_of_pgrp(pgrp) != task_session(current))
goto out_unlock;
retval = 0;
- put_pid(real_tty->pgrp);
- real_tty->pgrp = get_pid(pgrp);
+ put_pid(real_tty->ctrl.pgrp);
+ real_tty->ctrl.pgrp = get_pid(pgrp);
out_unlock:
rcu_read_unlock();
out_unlock_ctrl:
- spin_unlock_irq(&real_tty->ctrl_lock);
+ spin_unlock_irq(&real_tty->ctrl.lock);
return retval;
}
if (tty == real_tty && current->signal->tty != real_tty)
return -ENOTTY;
- spin_lock_irqsave(&real_tty->ctrl_lock, flags);
- if (!real_tty->session)
+ spin_lock_irqsave(&real_tty->ctrl.lock, flags);
+ if (!real_tty->ctrl.session)
goto err;
- sid = pid_vnr(real_tty->session);
- spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
+ sid = pid_vnr(real_tty->ctrl.session);
+ spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
return put_user(sid, p);
err:
- spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
+ spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
return -ENOTTY;
}
* information and perform any necessary signal handling.
*
* 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,
* the actual work.
*
* 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)
{
* @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
* 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
* storage for tty devices is referenced here as @port in struct tty_port.
struct mutex throttle_mutex;
struct rw_semaphore termios_rwsem;
struct mutex winsize_mutex;
- spinlock_t ctrl_lock;
/* Termios values are protected by the termios rwsem */
struct ktermios termios, termios_locked;
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;
int count;
struct winsize winsize; /* winsize_mutex */
unsigned long unused[0];
} __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;
- unsigned long ctrl_status:8, /* ctrl_lock */
- packet:1,
- unused_ctrl:BITS_PER_LONG - 9;
unsigned int receive_room; /* Bytes free for queue */
int flow_change;