Skip to content

Commit d945cb9

Browse files
Alan Coxtorvalds
authored andcommitted
pty: Rework the pty layer to use the normal buffering logic
This fixes the ppp problems and various other issues with call locking caused by one side of a pty called in one locking context trying to match another with differing rules on the other side. We also get a big slack space to work with that means we can bury the flow control deadlock case for any conceivable real world situation. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b4b21ca commit d945cb9

File tree

1 file changed

+59
-95
lines changed

1 file changed

+59
-95
lines changed

drivers/char/pty.c

Lines changed: 59 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -75,114 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
7575
*/
7676
static void pty_unthrottle(struct tty_struct *tty)
7777
{
78-
struct tty_struct *o_tty = tty->link;
79-
80-
if (!o_tty)
81-
return;
82-
83-
tty_wakeup(o_tty);
78+
tty_wakeup(tty->link);
8479
set_bit(TTY_THROTTLED, &tty->flags);
8580
}
8681

87-
/*
88-
* WSH 05/24/97: modified to
89-
* (1) use space in tty->flip instead of a shared temp buffer
90-
* The flip buffers aren't being used for a pty, so there's lots
91-
* of space available. The buffer is protected by a per-pty
92-
* semaphore that should almost never come under contention.
93-
* (2) avoid redundant copying for cases where count >> receive_room
94-
* N.B. Calls from user space may now return an error code instead of
95-
* a count.
82+
/**
83+
* pty_space - report space left for writing
84+
* @to: tty we are writing into
9685
*
97-
* FIXME: Our pty_write method is called with our ldisc lock held but
98-
* not our partners. We can't just wait on the other one blindly without
99-
* risking deadlocks. At some point when everything has settled down we need
100-
* to look into making pty_write at least able to sleep over an ldisc change.
86+
* The tty buffers allow 64K but we sneak a peak and clip at 8K this
87+
* allows a lot of overspill room for echo and other fun messes to
88+
* be handled properly
89+
*/
90+
91+
static int pty_space(struct tty_struct *to)
92+
{
93+
int n = 8192 - to->buf.memory_used;
94+
if (n < 0)
95+
return 0;
96+
return n;
97+
}
98+
99+
/**
100+
* pty_write - write to a pty
101+
* @tty: the tty we write from
102+
* @buf: kernel buffer of data
103+
* @count: bytes to write
101104
*
102-
* The return on no ldisc is a bit counter intuitive but the logic works
103-
* like this. During an ldisc change the other end will flush its buffers. We
104-
* thus return the full length which is identical to the case where we had
105-
* proper locking and happened to queue the bytes just before the flush during
106-
* the ldisc change.
105+
* Our "hardware" write method. Data is coming from the ldisc which
106+
* may be in a non sleeping state. We simply throw this at the other
107+
* end of the link as if we were an IRQ handler receiving stuff for
108+
* the other side of the pty/tty pair.
107109
*/
110+
108111
static int pty_write(struct tty_struct *tty, const unsigned char *buf,
109112
int count)
110113
{
111114
struct tty_struct *to = tty->link;
112-
struct tty_ldisc *ld;
113-
int c = count;
115+
int c;
114116

115-
if (!to || tty->stopped)
117+
if (tty->stopped)
116118
return 0;
117-
ld = tty_ldisc_ref(to);
118-
119-
if (ld) {
120-
c = to->receive_room;
121-
if (c > count)
122-
c = count;
123-
ld->ops->receive_buf(to, buf, NULL, c);
124-
tty_ldisc_deref(ld);
119+
120+
/* This isn't locked but our 8K is quite sloppy so no
121+
big deal */
122+
123+
c = pty_space(to);
124+
if (c > count)
125+
c = count;
126+
if (c > 0) {
127+
/* Stuff the data into the input queue of the other end */
128+
c = tty_insert_flip_string(to, buf, c);
129+
/* And shovel */
130+
tty_flip_buffer_push(to);
131+
tty_wakeup(tty);
125132
}
126133
return c;
127134
}
128135

136+
/**
137+
* pty_write_room - write space
138+
* @tty: tty we are writing from
139+
*
140+
* Report how many bytes the ldisc can send into the queue for
141+
* the other device.
142+
*/
143+
129144
static int pty_write_room(struct tty_struct *tty)
130145
{
131-
struct tty_struct *to = tty->link;
132-
133-
if (!to || tty->stopped)
134-
return 0;
135-
136-
return to->receive_room;
146+
return pty_space(tty->link);
137147
}
138148

139-
/*
140-
* WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior
141-
* The chars_in_buffer() value is used by the ldisc select() function
142-
* to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
143-
* The pty driver chars_in_buffer() Master/Slave must behave differently:
144-
*
145-
* The Master side needs to allow typed-ahead commands to accumulate
146-
* while being canonicalized, so we report "our buffer" as empty until
147-
* some threshold is reached, and then report the count. (Any count >
148-
* WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock
149-
* the count returned must be 0 if no canonical data is available to be
150-
* read. (The N_TTY ldisc.chars_in_buffer now knows this.)
149+
/**
150+
* pty_chars_in_buffer - characters currently in our tx queue
151+
* @tty: our tty
151152
*
152-
* The Slave side passes all characters in raw mode to the Master side's
153-
* buffer where they can be read immediately, so in this case we can
154-
* return the true count in the buffer.
153+
* Report how much we have in the transmit queue. As everything is
154+
* instantly at the other end this is easy to implement.
155155
*/
156+
156157
static int pty_chars_in_buffer(struct tty_struct *tty)
157158
{
158-
struct tty_struct *to = tty->link;
159-
struct tty_ldisc *ld;
160-
int count = 0;
161-
162-
/* We should get the line discipline lock for "tty->link" */
163-
if (!to)
164-
return 0;
165-
/* We cannot take a sleeping reference here without deadlocking with
166-
an ldisc change - but it doesn't really matter */
167-
ld = tty_ldisc_ref(to);
168-
if (ld == NULL)
169-
return 0;
170-
171-
/* The ldisc must report 0 if no characters available to be read */
172-
if (ld->ops->chars_in_buffer)
173-
count = ld->ops->chars_in_buffer(to);
174-
175-
tty_ldisc_deref(ld);
176-
177-
if (tty->driver->subtype == PTY_TYPE_SLAVE)
178-
return count;
179-
180-
/* Master side driver ... if the other side's read buffer is less than
181-
* half full, return 0 to allow writers to proceed; otherwise return
182-
* the count. This leaves a comfortable margin to avoid overflow,
183-
* and still allows half a buffer's worth of typed-ahead commands.
184-
*/
185-
return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
159+
return 0;
186160
}
187161

188162
/* Set the lock flag on a pty */
@@ -202,20 +176,10 @@ static void pty_flush_buffer(struct tty_struct *tty)
202176
{
203177
struct tty_struct *to = tty->link;
204178
unsigned long flags;
205-
struct tty_ldisc *ld;
206179

207180
if (!to)
208181
return;
209-
ld = tty_ldisc_ref(to);
210-
211-
/* The other end is changing discipline */
212-
if (!ld)
213-
return;
214-
215-
if (ld->ops->flush_buffer)
216-
to->ldisc->ops->flush_buffer(to);
217-
tty_ldisc_deref(ld);
218-
182+
/* tty_buffer_flush(to); FIXME */
219183
if (to->packet) {
220184
spin_lock_irqsave(&tty->ctrl_lock, flags);
221185
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;

0 commit comments

Comments
 (0)