Skip to content

Commit

Permalink
tty: cumulate and document tty_struct::ctrl* members
Browse files Browse the repository at this point in the history
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 c545b66 (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: Jiri 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.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jiri Slaby authored and gregkh committed May 13, 2021
1 parent 6e94dbc commit 64d608d
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 122 deletions.
2 changes: 1 addition & 1 deletion drivers/net/caif/caif_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static inline void update_tty_status(struct ser_device *ser)
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)
{
Expand Down
30 changes: 15 additions & 15 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,10 @@ static void n_tty_packet_mode_flush(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);
}
}
Expand All @@ -361,7 +361,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
* 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)
Expand Down Expand Up @@ -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
* 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)
Expand Down Expand Up @@ -2025,7 +2025,7 @@ static bool canon_copy_from_read_buf(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)
Expand Down Expand Up @@ -2072,7 +2072,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
int minimum, time;
ssize_t retval = 0;
long timeout;
int packet;
bool packet;
size_t tail;

/*
Expand Down Expand Up @@ -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;

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;
Expand Down Expand Up @@ -2368,7 +2368,7 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file,
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;
Expand Down
62 changes: 31 additions & 31 deletions drivers/tty/pty.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
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;
Expand Down Expand Up @@ -185,24 +185,24 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
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);
}
Expand Down Expand Up @@ -232,11 +232,11 @@ static void pty_flush_buffer(struct tty_struct *tty)
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);
}
}

Expand Down Expand Up @@ -266,7 +266,7 @@ static void pty_set_termios(struct tty_struct *tty,
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') &&
Expand All @@ -275,17 +275,17 @@ static void pty_set_termios(struct tty_struct *tty,
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);
}
}
Expand Down Expand Up @@ -346,11 +346,11 @@ static void pty_start(struct tty_struct *tty)
{
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);
}
}
Expand All @@ -359,11 +359,11 @@ static void pty_stop(struct tty_struct *tty)
{
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);
}
}
Expand Down
44 changes: 22 additions & 22 deletions drivers/tty/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,15 +638,15 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)

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
Expand Down Expand Up @@ -1559,8 +1559,8 @@ static void release_one_tty(struct work_struct *work)
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);
}

Expand Down Expand Up @@ -1861,9 +1861,9 @@ int tty_release(struct inode *inode, struct file *filp)
*/
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);
}

Expand Down Expand Up @@ -2250,16 +2250,16 @@ static int __tty_fasync(int fd, struct file *filp, int on)
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;
Expand Down Expand Up @@ -2381,7 +2381,7 @@ EXPORT_SYMBOL(tty_do_resize);
*
* 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.
*/

Expand Down Expand Up @@ -3039,9 +3039,9 @@ void __do_SAK(struct tty_struct *tty)
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);

Expand Down Expand Up @@ -3129,8 +3129,8 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
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);
Expand All @@ -3140,7 +3140,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
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);
Expand Down
Loading

0 comments on commit 64d608d

Please sign in to comment.